RoboZZleインタープリター


10

あなたの仕事は、RoboZZleインタープリターを作成することです。ゲームに慣れていない場合は、robozzle.comビデオをご覧になるか、以下の説明をお読みください。

ロボットは、赤、緑、青、または黒に着色された正方形の長方形のグリッドに住んでいます。黒い四角はアクセスできません。他はアクセス可能であり、それらのいくつかは星を含んでいます。目標は、黒い四角を踏んだり、地図から落ちたりすることなく、すべての星を集めることです。ロボットは1つの正方形を占め、特定の方向(左、右、上、または下)を向きます。これは、サブルーチンF1、F2、...、F5にグループ化されたアセンブリのような命令に従います。指示は、述語(「なし」、「赤の場合」、「緑の場合」、「青の場合」)とアクション(「進む」、「左に曲がる」、「右に曲がる」)のペアです。 「現在の正方形の赤をペイント」、「緑をペイント」、「青をペイント」、「何もしない」、「F1を呼び出す」、「F5を呼び出す」)。サブルーチンの呼び出しはスタックを使用し、再帰的である場合があります。従来のプログラミングと同様に、サブルーチンの最後の命令が完了した後、サブルーチンが呼び出されたところから実行が続行されます。実行はF1の最初の命令から始まり、ロボットが星のあるすべての正方形を訪問するか、ロボットが黒い四角またはマップの外側を踏むか、1000命令が実行されるまで続きます(失敗した述語と「何もしない」アクション)カウントしない)、または実行する命令がなくなる(スタックアンダーフロー)。

入力:

  • a-マップをエンコードする12x16文字のマトリックス(通常は言語で表される文字列の配列など)- '#'アクセスできない(黒い)四角形、'*'星付きの四角形'.'、その他

  • c-アクセシブルな正方形の色を表す12x16文字のマトリックス- 'R'(赤)、'G'(緑)、または'B'(青)。アクセスできない正方形は、3つのうち任意の文字で表されます。

  • yおよびx-ロボットの0ベースの行と列。a[y][x]であることが保証されています'.'

  • d-ロボットが向いている方向:0 1 2 3右用、下、左、上、すなわちに向けました(y,x+1)(y+1,x)(y,x-1)(y-1,x)

  • f-単一の文字列、F1 ... F5の連結された実装。各実装は、(空の可能性がある)述語とアクションのペアのシーケンスであり(サブルーチンごとに最大10ペア)、で終了します'|'

    • 述語:'_'なし、'r'赤、'g'緑、'b'

    • アクション:'F'前進、'L'左折、'R'右折、'r'赤く'g'塗る、緑に'b'塗る、青に塗る、'1'F1を'5'呼び出す...、F5を呼び出す、'_'何もしない

上記のように入力に名前を付ける必要はありませんが、それらの値は指定どおりでなければなりません。

出力:(1またはtrue)ロボットがルールに従ってすべての星を収集する場合、0false)そうでない場合。

a=["################","################","##*....*...*#.##","##.####.#####.##","##.####.#####.##","##.####*...*#.##","##.########.####","##*........*#.##","################","################","################","################"]
c=["RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRBBBBRGGGGRRRR","RRBRRRRGRRRRRRRR","RRBRRRRGRRRRRRRR","RRBRRRRRGGGBRRRR","RRBRRRRRRRRGRRRR","RRRBBBBGGGGBRBRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR"]
y=2; x=6; d=2

// and then depending on "f":
f="_FrLg2_1|_FbLrR_2||||" // result:1
f="_FrRg2_1|_FbLrR_2||||" // result:0 (stepped on a black square)
f="_FrLrL_1|_FbLrR_2||||" // result:0 (1000-step limit exceeded)
f="_FrLg2__|________||||" // result:0 (stack underflow)

「ペイント」命令を含む別の

a=["#***************","#*###*###*###*##","#*###*###*###*##","***#***#***#***#","***#***#***#***#","*###*###*###*###","***#***#***#***#","***#***#***#***#","***#***#***#***#","*###*###*###*###","*.*#***#***#***#","***#***#***#***#"]
c=["RGGGGGGGGGGGGGGG","RBRRRGRRRGRRRGRR","RBRRRGRRRGRRRGRR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BRRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BGRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR"]
y=10; x=1; d=0
f="_2_R_R_1|_FgRgFgFg3rRr4b2_Fgb|_F_F_R|_2_L_r||"
// result:1

独自のテストを生成するには、robozzle.comのリストからパズルに移動し、それを解決する(または解決しない)ことを試み、ブラウザーでF12を押し、JSコンソールに入力します。

r=robozzle;s=JSON.stringify;with(r.level)console.log('a='+s(Items)+'\nc='+s(Colors)+'\ny='+RobotRow+'\nx='+RobotCol+'\nd='+RobotDir+'\nf='+s(r.encodeSolution()))

そしてあなたの言語に合わせて結果を再フォーマットします。

最短の勝利。抜け穴はありません。


1
提供された文字の代わりに、個別の文字を使用してデータを表すことはできますか?
HyperNeutrino 2018年

1
「ループする」という課題に対するAPLの回答については、複雑な大きさを減らすことによって最後の角度の値を並べ替えることができます。
user202729

1
@ user202729ええと、私はここでその課題についてのコメントを期待していませんでした:)あなたのアイデアはうまくいきました、ありがとう!私は、文字数を過度に不快にしないように実装しようとします。
2018年

1
文字マトリックスを場所と文字のペアのリストとして取得できますか?
0 '

1
@ 0 '私がここで従った原則(HyperNeutrinoのコメントも参照)は、robozzle.comで実際に使用されている入力フォーマットにできるだけ近づけることです。そのため、ペアのリストであってはなりません。
ngn 2018年

回答:


5

プロローグ(SWI)、574バイト

Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).
N^C^G^[P,I|R]^F^X^Y^D:-map_assoc(\=(74),G);N<1e3,get_assoc(X^Y,G,J),J>67,put_assoc(X^Y,G,78,H),T=N+1,((I\=95,(P=95;get_assoc(X^Y,C,P)))->(between(49,53,I),plus(48,M,I),nth1(M,F,Q),append(Q,R,S),T^C^H^S^F^X^Y^D;member(I,`RL`),E is(D-I//3)mod 4,T^C^H^R^F^X^Y^E;I=70,(D=0,U is X+1;D=1,V is Y+1;D=2,U is X-1;D=3,V is Y-1),(U=X;V=Y),T^C^H^R^F^U^V^D;I>97,put_assoc(X^Y,C,I,W),T^W^H^R^F^X^Y^D);N^C^H^R^F^X^Y^D).
A+C+F+L:-A*G,C*B,split_string(F,"|","",P),maplist(string_codes,P,[M|N]),0^B^G^M^[M|N]^L.

オンラインでお試しください!

これは、すべての星が正常に収集された場合に呼び出されたときに成功し、それ以外の場合に失敗するという述語を定義します。述語は次のような引数を取りますa+c+f+x^y^d.aそしてc一方で、バッククォート引用符で囲まれた文字列のリストにする必要がありf、二重引用符で囲まれた文字列でなければなりません。

説明

このプログラムは、3つの述語が含まれている*/2^/2+/2*/2最初の行に定義されている述語は、入力された処理の一部を担当します。^/2述語は、再帰的にロボットが動くが、ステップバイステップでどのように計算し、ロボットが合法的にすべての星を収集し、それ以外の場合は失敗した場合に成功します。+/2述語は、プログラムの主な述語であるとの入力準備^/2からいくつかの助けを借りて、述語を*/2述語。これらの各述語は技術的には2つの引数しか取りませんが、演算子とパターンマッチングを使用すると、引数が多いかのように動作することに注意してください(この現象については、ここで詳しく説明します)。

*/2

Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).

この述語は2つの引数を取ります。1つ目は、文字コードのリストのリストです(これは、Prologがバックティックで引用された文字列を解析する方法です)。2番目は、12x16マップのポイント(として表されますX^Y)から32に加えて、文字コードのリストのそのポイントに格納されている文字コードに関連付けられたマップです。32が各文字コードに追加されるので、カラーマトリックスでは、大文字のカラー文字が小文字のカラー文字に変換されます。

これを行う方法は、を使用して、ポイントとそのポイントの文字コードのペアのリストを生成しfindall/3ます。次に、を使用list_to_assoc/2して、ポイントからそのポイントの文字コードへの対応する連想マップを作成します。

findall/3述語は、最初の引数、第2引数と第三引数としてリストとしての目標として「テンプレート」をとる組み込みです。述語は、目標を成功させるテンプレートのすべての可能な値でリストを埋めます。演算子の優先順位に渡され、テンプレートが原因findall/3*/2として解析されます(X^Y)-D-テンプレートは(点の位置を表すように、オペレータは、Prologで2つの値の対を表すX^Y)(プラスポイントの文字コード32と対をなしますD)。^ポイントの表現に使用されているは、^/2述語とはまったく関係がないことに注意してください。

findall/3述語に渡される目標を考えてみましょう。

nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D) % Note that the O (oh) is not a 0 (zero)

目標には、目標を成功させるために成功する必要のある3つの述語が含まれています。nth0/3二回使用されている述語は(リストの特定のインデックスの値を取得するために使用され0、その名前には、それがインデックスゼロであることを示します)。最初の呼び出しYは文字マトリックスのth行をO格納し、2番目の呼び出しXはその行のth文字をに格納しCます。plus/3最初の2つの引数の合計が3番目の引数になる場合、最後の述語は成功します。これは、ペアの文字コードを、上記のようにすべての大文字を小文字に変換する文字マトリックスの文字コードより32大きくするために使用されます。

最後findall/3に、X^Y-Dその目的を成功させるすべての組み合わせLを、連想マップが作成されたリストに格納します。

さらに近日公開...


4

JavaScript(ES6)、298 276 264バイト

@ngnのおかげで8バイトを節約

入力をとして受け取ります(a,c,x,y,d,f)。ここでacは文字の配列の配列です。0またはを返します1

(a,c,x,y,d,f,k=1e3)=>(g=(F,p=0,s=f.split`|`[F],r=a[y])=>!k|!r|x&16||r[x]<'$'?2:/\*/.test(a)?(r[x]=o=0,(I=s[p+1],P=s[p])&&(P<'b'|P==c[y][x].toLowerCase()&&I!='_'&&k--?+I?o=g(I-1):I=='L'?d--:I=='R'?d++:I<'b'?y+=(d&=3,x-=~-d%2,2-d)%2:c[y][x]=I:0,o||g(F,p+2))):1)(0)&1

テストケース

コメントしました

(                                           // main function taking:
  a, c, x, y, d, f,                         //   - input variables
  k = 1e3                                   //   - k = instruction counter
) => (                                      //
  g = (                                     // g = recursive execution function, taking:
    F,                                      //   - F = subroutine id
    p = 0,                                  //   - p = instruction pointer
    s = f.split`|`[F],                      //   - s = instruction string
    r = a[y]                                //   - r = current row in a[]
  ) =>                                      //
    !k |                                    // if we've executed 1000 instructions
    !r | x & 16 ||                          // or we've felt out of the map
    r[x] < '$' ?                            // or we've reached a black square:
      2                                     //   exit with error code 2
    :                                       // else:
      /\*/.test(a) ? (                      //   if there are still some stars:
        r[x] = o = 0,                       //     mark the current cell as visited
        (I = s[p + 1], P = s[p]) &&         //     I = instruction, P = predicate
        (                                   //     if P is defined:
          P < 'b' |                         //       if the predicate is '_'
          P == c[y][x].toLowerCase()        //       or it matches the color of the cell
          && I != '_'                       //       and the instruction is not '_',
          && k-- ?                          //       then decrement k and:
            +I ?                            //         if I is '1' ... '5':
              o = g(I - 1)                  //           process call to subroutine
            :                               //         else:
              I == 'L' ?                    //           if I is 'L':
                d--                         //             turn left
              :                             //           else:
                I == 'R' ?                  //             if I is 'R':
                  d++                       //               turn right
                :                           //             else:
                  I < 'b' ? (               //               if I is not a color:
                    y += (                  //                 I must be 'F',
                      d &= 3,               //                 so make the bot advance
                      x -= ~-d % 2,         //                 by updating x
                      2 - d                 //                 and y
                    ) % 2                   //
                  ) :                       //               else:
                    c[y][x] = I             //                 paint the current cell
          :                                 //       else:
            0,                              //         do nothing
          o ||                              //       provided that o is equal to 0,
          g(F, p + 2)                       //       go on with the next instruction
        )                                   //     end of instruction execution
      ) :                                   //   else:
        1                                   //     success: return 1
  )(0) & 1                                  // initial call to the subroutine F1

x+='2101'[d&3]-1,y+='1210'[d&3]-1->d&=3,x+=(1-d)%2,y+=(2-d)%2
ngn 2018年

1
x私はあなたが交換することができると思うので、1せいぜいによって変化しx&~15x&16
NGN

1

APL(Dyalog Classic)236 233バイト

-3 OutgolferのErikに感謝

ボーナスを提供したので、自分の課題に対するサンプルソリューションを投稿します。ここには改善の余地があります。自由にコピーして、さらにゴルフしてください。

a c r d f←⎕⋄c819cF0,('|'1f)/⍳≢ftn0
{~(⊂r)∊⍳⍴a:0'#'=ra:0p q2f↓⍨⊃⌽t⋄(_p'|')∧×≢t:0_:∇t↓←¯1⋄(⊃⌽t)+←2⋄~p'_',rc:∇0n+←1n>999:0⋄(ra)←'.'⋄~'*'a:1r+←(q'F'11 90j1*dd+←4|'.R.L'qq'rgb':∇(rc)←qq∊⎕d:∇t,←F[⍎q]⋄∇0}0

オンラインでお試しください!

上記と同じ、コメントで展開:

io0                    0-based indices (not counted in the score)
a c r d f←⎕              decompose eval'ed input (⎕) into variables
c←819⌶c                 ⍝ make c lowercase
F←0,('|'=¯1⌽f)/⍳≢f      ⍝ split f at the '|'-s
t←n←0                   ⍝ t:stack, n:step counter
{                       ⍝ lambda
  ~(⊂r)∊⍳⍴a:0           ⍝ if the robot is off the map, return 0
  '#'=r⌷a:0             ⍝ if the robot is on a wall, return 0
  p q2f↓⍨⊃⌽t           current instruction - p:predicate, q:action
  (_p'|')∧1≥≢t:0       if at end of func and stack is empty, return 0
  _:∇t↓←¯1               if at end of func, pop from stack and recurse
  (⊃⌽t)+←2               increment program counter (top of stack)
  ~p'_',rc:∇0          if predicate doesn't match cell colour, recurse
  n+←1⋄n>999:0          ⍝ if too meany steps, return 0
  (r⌷a)←'.'             ⍝ consume star
  ~'*'∊a:1              ⍝ if no more stars left, return 1
  r+←(q≡'F')×11 9○0j1*d ⍝ if action is F, move forward
  d+←4|'.R.L'⍳q         ⍝ if action is L or R, turn left or right
  q∊'rgb':∇(r⌷c)←q      ⍝ if action is paint (r,g,b), do it
  q∊⎕d:∇t,←F[⍎q]        ⍝ if action is F1...F5, push on stack and recurse
  ∇0                    ⍝ action is nop (_), recurse
}0                      ⍝ call the lambda (argument will be ignored)


@EriktheOutgolferの変更が適用されました、ありがとう
ngn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.