Thông dịch viên RoboZZle


10

Nhiệm vụ của bạn là viết một trình thông dịch RoboZZle. Nếu bạn không quen thuộc với trò chơi, vui lòng xem video tại robozz.com hoặc đọc mô tả của tôi dưới đây.

Một robot sống trên một lưới hình chữ nhật gồm các hình vuông có màu đỏ, xanh lá cây, xanh dương hoặc đen. Hình vuông màu đen là không thể tiếp cận. Những cái khác có thể truy cập và một số trong số chúng có chứa một ngôi sao. Mục tiêu là thu thập tất cả các ngôi sao mà không bước lên các ô vuông màu đen hoặc rơi khỏi bản đồ. Robot chiếm một hình vuông và phải đối mặt với một hướng cụ thể - trái, phải, lên hoặc xuống. Nó tuân theo các hướng dẫn giống như lắp ráp được nhóm lại thành các chương trình con F1, F2, ..., F5. Một lệnh là một cặp vị ngữ ("none", "if on red", "if on green", "if on blue") và một hành động ("đi tiếp", "rẽ trái", "rẽ phải", "Vẽ hình vuông màu đỏ hiện tại", "sơn màu xanh lá cây", "sơn màu xanh lam", "không làm gì", "gọi F1", ..., "gọi F5"). Các cuộc gọi đến chương trình con sử dụng một ngăn xếp và có thể được đệ quy. Giống như trong lập trình thông thường, sau khi hướng dẫn cuối cùng của chương trình con được hoàn thành, việc thực thi tiếp tục từ điểm mà chương trình con được gọi. Việc thực thi bắt đầu từ hướng dẫn đầu tiên của F1 và tiếp tục cho đến khi robot đã truy cập tất cả các hình vuông có ngôi sao hoặc khi robot bước trên một hình vuông màu đen hoặc bên ngoài bản đồ, hoặc 1000 lệnh đã được thực hiện (dự đoán thất bại và hành động "không làm gì" không được tính) hoặc không có thêm hướng dẫn nào để thực hiện (ngăn xếp ngăn xếp).

Đầu vào:

  • a- ma trận ký tự 12x16 (như thường được biểu thị bằng ngôn ngữ của bạn, ví dụ như chuỗi các chuỗi) mã hóa bản đồ - '#'cho các ô vuông không thể tiếp cận (màu đen), '*'cho các hình vuông có ngôi sao, '.'cho phần còn lại

  • c- ma trận ký tự 12x16 mô tả màu sắc của các ô vuông có thể truy cập - 'R'(đỏ), 'G'(xanh lá cây) hoặc 'B'(xanh lam). Các ô vuông không thể truy cập sẽ được thể hiện bằng một chữ cái tùy ý từ ba.

  • yx- hàng và cột dựa trên 0 của robot; a[y][x]được đảm bảo'.'

  • d- hướng robot đang phải đối mặt: 0 1 2 3cho phải, xuống, trái, lên, tức là về phía (y,x+1), (y+1,x), (y,x-1),(y-1,x)

  • f- một chuỗi đơn, các triển khai được nối của F1 ... F5. Mỗi lần thực hiện là một chuỗi (có thể trống) các cặp hành động vị ngữ (nhiều nhất là 10 cặp trên mỗi chương trình con), được kết thúc bằng a '|'.

    • vị ngữ: '_'không có, 'r'đỏ, 'g'xanh lá cây, 'b'xanh dương

    • hành động: 'F'đi tiếp, 'L'rẽ trái, 'R'rẽ phải, 'r'sơn đỏ, 'g'sơn xanh, 'b'sơn xanh, '1'gọi F1, ..., '5'gọi F5, '_'không làm gì cả

Bạn không phải đặt tên cho đầu vào của mình như trên, nhưng giá trị của chúng phải được chỉ định.

Đầu ra: 1(hoặc true) nếu robot thu thập tất cả các ngôi sao theo quy tắc, 0( false) nếu không.

Ví dụ :

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)

Một ví dụ khác , liên quan đến hướng dẫn "sơn":

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

Để tạo bài kiểm tra của riêng bạn, hãy truy cập một câu đố từ danh sách tại robozz.com , cố gắng giải nó (hoặc không giải quyết nó), nhấn F12 trong trình duyệt của bạn, nhập vào bảng điều khiển 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()))

và định dạng lại kết quả cho ngôn ngữ của bạn.

Chiến thắng ngắn nhất. Không sơ hở.


1
Chúng ta có thể sử dụng bất kỳ ký tự riêng biệt nào để thể hiện dữ liệu thay vì các ký tự được cung cấp không?
HyperNeutrino

1
Đối với câu trả lời APL của bạn cho thử thách "Lặp lại", bạn có thể sắp xếp giá trị góc cuối cùng bằng cách giảm cường độ phức tạp.
dùng202729

1
@ user202729 Uh, tôi không mong đợi nhận xét về thử thách đó ở đây :) Ý tưởng của bạn hoạt động, cảm ơn! Tôi sẽ cố gắng thực hiện nó mà không làm cho số lượng nhân vật quá ô nhục.
ngn

1
Chúng ta có thể lấy ma trận ký tự làm danh sách các cặp vị trí và ký tự không?
0 '

1
@ 0 'Nguyên tắc tôi đã theo dõi ở đây (xem thêm bình luận của HyperNeutrino) là ở gần nhất có thể với định dạng đầu vào thực sự được sử dụng tại robo Muff.com, vì vậy tôi sợ rằng nó không nên là một danh sách các cặp.
ngn

Câu trả lời:


5

Prolog (SWI) , 574 byte

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.

Hãy thử trực tuyến!

Điều này xác định một vị ngữ mà khi được gọi thành công nếu tất cả các ngôi sao được thu thập thành công và thất bại khác. Vị ngữ lấy các đối số như vậy : a+c+f+x^y^d.. acphải là danh sách các chuỗi trích dẫn backtick, trong khi fphải là một chuỗi trích dẫn kép.

Giải trình

Chương trình này chứa ba vị từ, */2, ^/2, và +/2. Các */2vị từ được xác định trên dòng đầu tiên chịu trách nhiệm cho một phần của xử lý đầu vào. Vị ^/2ngữ tính toán đệ quy cách robot di chuyển từng bước và thành công nếu robot thu thập hợp pháp tất cả các ngôi sao và thất bại theo cách khác. Vị +/2ngữ là vị ngữ chính của chương trình và chuẩn bị đầu vào cho ^/2vị từ với một số trợ giúp từ */2vị ngữ. Lưu ý rằng mỗi vị từ này về mặt kỹ thuật chỉ cần hai đối số nhưng sử dụng toán tử và khớp mẫu, chúng có thể hành xử như thể chúng có nhiều đối số hơn (tôi sẽ thảo luận sâu hơn về hiện tượng này ở đây ).

*/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).

Vị ngữ này có hai đối số. Đầu tiên là danh sách các danh sách mã ký tự (đây là cách Prolog phân tích cú pháp backtick trích dẫn chuỗi). Thứ hai là một bản đồ liên kết từ các điểm trong bản đồ 12x16 (được biểu thị là X^Y) đến 32 cộng với mã ký tự được lưu trữ tại điểm đó trong danh sách các danh sách mã ký tự. Số 32 được thêm vào mỗi mã ký tự để cho ma trận màu, nó sẽ biến các ký tự màu chữ hoa thành ký tự màu chữ thường.

Cách thức thực hiện việc này là tạo ra một danh sách các cặp điểm và mã ký tự tại điểm đó bằng cách sử dụng findall/3. Sau đó, nó sử dụng list_to_assoc/2để tạo bản đồ liên kết tương ứng từ các điểm đến mã ký tự tại điểm đó.

Vị findall/3từ là một nội trang lấy "mẫu" làm đối số đầu tiên, mục tiêu là đối số thứ hai và danh sách làm đối số thứ ba. Vị từ điền vào danh sách với tất cả các giá trị có thể có của mẫu khiến mục tiêu thành công. Do quyền ưu tiên của toán tử, mẫu được truyền findall/3vào */2được phân tích cú pháp là (X^Y)-D. Các -nhà điều hành đại diện cho một cặp hai giá trị trong Prolog nên mẫu đại diện cho vị trí của điểm ( X^Y) kết hợp với mã ký tự 32 cộng của điểm ( D). Lưu ý rằng việc ^sử dụng để biểu diễn điểm không được kết nối với ^/2vị ngữ.

Chúng ta hãy xem xét mục tiêu được truyền đến findall/3vị ngữ.

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

Mục tiêu chứa ba vị từ mà mỗi mục tiêu cần thành công để mục tiêu thành công. Vị nth0/3từ được sử dụng hai lần được sử dụng để lấy giá trị tại một chỉ mục cụ thể của danh sách ( 0trong tên của nó cho biết nó không được lập chỉ mục). Cuộc gọi đầu tiên đến nó lưu hàng Ythứ của ma trận ký tự trong Okhi cuộc gọi thứ hai lưu Xký tự thứ trong hàng đó vào C. Vị từ cuối cùng plus/3thành công nếu hai đối số đầu tiên của nó kết hợp với đối số thứ ba của nó. Điều này được sử dụng để làm cho mã ký tự trong cặp lớn hơn 32 mã ký tự trong ma trận ký tự, như đã nêu ở trên sẽ biến tất cả các chữ cái viết hoa thành chữ thường.

Cuối cùng findall/3lưu trữ tất cả các X^Y-Dkết hợp khiến mục tiêu của nó thành công trong danh sách Lmà bản đồ kết hợp được xây dựng từ đó.

Sắp có thêm ...


4

JavaScript (ES6), 298 276 264 byte

Đã lưu 8 byte nhờ @ngn

Lấy đầu vào là (a,c,x,y,d,f), ở đâu aclà mảng các mảng ký tự. Trả về 0hoặc 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

Các trường hợp thử nghiệm

Đã bình luận

(                                           // 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
xthay đổi nhiều nhất là 1, vì vậy tôi nghĩ bạn có thể thay thế x&~15bằngx&16
ngn

1

APL (Dyalog Classic) , 236 233 byte

-3 cảm ơn Erik the Outgolfer

Bây giờ tôi đã cho đi phần thưởng, tôi đang đăng một giải pháp mẫu cho thử thách của riêng tôi. Có chỗ để cải thiện ở đây - thoải mái sao chép và chơi gôn hơn nữa.

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

Hãy thử trực tuyến!

Tương tự như trên, mở rộng với các bình luận:

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 thay đổi được áp dụng, cảm ơn
ngn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.