RoboZZle口译员


10

您的任务是编写RoboZZle解释器。如果您不熟悉该游戏,请在robozzle.com上观看视频或阅读下面的说明。

机器人生活在一个正方形的红色,绿色,蓝色或黑色正方形网格中。黑色方块无法访问。其他的则可以访问,其中一些包含星号。目标是收集所有星星,而不会踩到黑色方块或从地图上掉下来。机器人占据一个正方形并面向特定方向-左,右,上或下。它遵循类似汇编的指令,分为子程序F1,F2,...,F5。一条指令是一对谓词(“无”,“如果红色”,“如果绿色”,“如果蓝色”)和一个动作(“前进”,“左转”,“右转”), “将当前方块涂成红色”,“将其涂成绿色”,“将其涂成蓝色”,“什么都不做”,“调用F1”,...,“调用F5”)。对子例程的调用使用堆栈,并且可以是递归的。就像在常规编程中一样,在子例程的最后一条指令完成之后,从调用子例程的那一点开始执行。从F1的第一条指令开始执行,一直持续到机器人访问带有星星的所有正方形,或者机器人踩到黑色正方形或在地图外部或执行了1000条指令(谓词失败且“不执行任何操作”) (不计算在内),或者没有更多要执行的指令(堆栈下溢)。

输入:

  • a-编码地图的12x16字符矩阵(通常用您的语言表示,例如字符串数组)对地图'#'进行编码- 不可访问的(黑色)正方形,'*'带有星星的正方形,'.'其余的

  • c-12x16字符矩阵,描述可访问正方形的颜色- 'R'(红色),'G'(绿色)或'B'(蓝色)。无法访问的方块将由三个中的任意字母表示。

  • yx-机器人的基于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,'_'不执行任何操作

您不必像上面一样命名输入,但是它们的值必须与指定的相同。

输出:(1true)如果机器人根据规则收集了所有恒星,则为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

1
对于您的APL解决“ Loop it”挑战,您可以通过降低复杂幅度来对最后一个角度值进行排序。
user202729

1
@ user202729嗯,我没想到在这里对此挑战发表评论:)您的想法可行,谢谢!我将尝试实现它而不会使字符计数过于可耻。
ngn

1
我们可以将字符矩阵作为位置和字符对的列表吗?
0

1
@ 0'我在这里遵循的原则(另请参见HyperNeutrino的注释)是保持尽可能接近robozzle.com实际使用的输入格式,因此,恐怕它不应该是成对的列表。
ngn

Answers:


5

Prolog(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必须是双引号引起来的字符串。

说明

这项计划包含三个谓语*/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).

该谓词有两个参数。第一个是字符代码列表的列表(这是Prolog解析反引号引起来的字符串的方式)。第二个是从12x16映射中的点(表示为X^Y)到32 的关联映射,再加上存储在该字符代码列表中该点的字符代码。将32个字符添加到每个字符代码中,以便对于颜色矩阵,它将大写的颜色字符转换为小写的颜色字符。

这样做的方式是使用生成点对列表以及该点的字符代码findall/3。然后,它list_to_assoc/2用于创建从点到该点字符代码的对应关联图。

findall/3谓词是一个内置采用“模板”作为第一个参数,一个目标,作为其第二个参数列表作为它的第三个参数。谓词用导致目标成功的模板的所有可能值填充列表。由于运算符的优先级,传递给findall/3in 的模板*/2被解析为(X^Y)-D。的-操作者表示的Prolog一对两个数值,以便该模板代表点的位置(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)

目标包含三个谓词,每个谓词都需要成功才能使目标成功。nth0/3两次使用的谓词用于获取列表的特定索引处的值(0名称中的表示该索引为零索引)。对其的第一次调用Y将字符矩阵的第th行存储在中,O而第二次调用将其存储X在该行的第th个字符中C。如果最后一个谓词plus/3的前两个参数加到第三个参数,则该谓词成功。这用于使字符对中的字符代码比字符矩阵中的字符代码大32,如上所述,字符矩阵会将所有大写字母变成小写字母。

最后,findall/3X^Y-D导致其目标成功的所有组合存储在L构建关联映射表的列表中。

更多即将推出...


4

的JavaScript(ES6),298个 276 264字节

@ngn节省了8个字节

将输入作为(a,c,x,y,d,f),其中ac是字符数组的数组。返回01

(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

1
x变化最多为1,所以我认为您可以替换x&~15x&16
ngn

1

APL(Dyalog经典)236个 233字节

-3感谢外长艾里克(Erik the Outgolfer)

现在,我已经发放了奖金,我将发布一个针对自己挑战的示例解决方案。这里还有改进的空间-随时可以复制和打高尔夫。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.