中国チェッカー最長移動


12

中国のチェッカー、ピースは、他の部分の上にホッピングすることによって、又はそのようなホップのシーケンスを行うことで移動することができます。あなたの仕事は、ホップの可能な限り長いシーケンスを見つけることです。

入力

それぞれがボード上の場所を表す121個のゼロまたは1のシーケンス。ゼロは、場所が空であることを意味します。1はその場所が占有されていることを意味します。位置は左から右にリストされています。上から下へ。たとえば、このセットアップの入力は次のようになります

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

説明:

一番上の場所は緑色の部分で占められているため、入力の最初の数字は1です。2番目の行には空の位置が1つあり、次に占有位置が1つあるので、01次に来ます。3番目の行はすべて占有されているため、111です。4番目の行には、2つの空のスペースと2つの占有スペース(左から右へ)があり0011ます。次に、次の行に5 0、a 1、7が続き0ます。

そのセットアップのように、まっすぐ上を指すコーナーがあります。ボードにはいくつのピース(1から121)があってもかまいません。異なる色の部分は、異なって表されないことに注意してください。

出力

ボード上の任意のピースを使用したリーガルホップの最大長。同じ場所に複数回アクセスすることはできません(開始位置と終了位置を含む)。ただし、同じ部分に複数回ホップすることができます。正当なホップがない場合、output 0。合法的な非ホップ移動が存在するかどうかを考慮しないでください。

たとえば、上記のセットアップへの出力は3です。

入力と出力は、stdinとstdout、コマンドライン引数、関数呼び出し、または同様の方法で実行できます。

テストケース

入力:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

出力:0(2つの部分が隣り合っていない)


入力:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

出力:(1左上隅の1人のプレーヤーの初期設定)


私はこれを私の素晴らしい叔母と一緒に演奏します。私たちは両方ともかなり良いです。これは興味深い挑戦です。
cjfaure 14年

1
たぶん、入力がどのように保存されるか/どのビットがどこに行くかについてもっと指定する必要があります。
TheDoctor 14年

どの部分を「ホップ」できますか?母と私がプレイしていた方法では、途中に曲がなければ、6方向のいずれか1つで(曲がった曲の反対側のスポットに)曲がります。そのホップのパス。他の人は、あなたが隣接するピースの上を飛び越えることができるだけであることを果たします。
ジョーZ.

1
@TheDoctorより詳細な説明を追加しました。
Ypnypn

詳細を明確にできますか?同じポジションを2回占有することはできますか?無限にループすることはできないと思いますが、左から右に移動する場所にヒットし、後で左上から右下に移動して再びヒットすると、可能性が広がります。
デボンパーソンズ

回答:


1

Perl、345 322

編集:ゴルフ、わずかに。

より多くのテストケースがあればいいのですが、今のところは動作するようです。必要に応じて後でコメントを追加します。読みやすくするために改行とインデントを使用:

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

いくつかのテストケースを追加しました。
Ypnypn

これらは問題なく動作しますが、簡単すぎます:-)。
user2846289

2

C、262 260

ゴルフコード(デバッグコードと不要な空白が削除されました。stdinを介した入力からコマンドラインを介した入力に変更され、変数iを宣言する機会を利用しました。最新の編集:コードはforループの括弧に移動して2つのセミコロンを保存します。)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

説明

これは、次のような20x21ボードに依存しています。最初は、プログラムの開始時にゼロで埋められます(このASCIIアートは、プログラムの修正バージョンによって生成され、iループが下向きにカウントされるため、右下隅にゼロがあります)。

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

ループiがこのボードを2回実行し、xとyを使用して、正方形が実際にチェッカーボードに属するかどうかを計算します(これには、xとyに6つの別々の不等式が必要です)。

存在する場合、最初のラウンドで正方形がいっぱいになり01(占有されている)には1(偽)、0(占有されていない)には(真実)が置かれます。すべての境界外の正方形にはすでに0が含まれているため、この反転は重要です。つまり、占有された正方形に似ており、特定のチェックを必要とせずにジャンプできないことは明らかです。

2回目のラウンドでは、正方形が占有されている(0を含む)場合f、動きを検索する関数を呼び出します。

f式でエンコードされた+/- 1(水平)、+ /-20(垂直)、+ /-19(対角)でエンコードされた6つの可能な方向で再帰的に検索します"AST?-,"[k]-64。ヒットを見つけると、再帰的に呼び出す前にそのセルを0(占有)に設定し、関数が返されると1(空)に戻します。セルの値は、そのセルに複数回ホッピングしないように、再帰呼び出しの前に変更する必要があります。

未ゴルフコード

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.