Перекладач RoboZZle


10

Ваше завдання - написати перекладач RoboZZle. Якщо ви не знайомі з грою, перегляньте це відео на robozzle.com або прочитайте опис нижче.

Робот живе на прямокутній сітці квадратів кольорового червоного, зеленого, синього або чорного кольорів. Чорні квадрати недоступні. Інші доступні, а деякі з них містять зірку. Мета - зібрати всі зірки, не наступаючи на чорні квадрати і не падаючи з карти. Робот займає один квадрат і стикається з певним напрямком - вліво, вправо, вгору або вниз. Дотримується інструкцій, схожих на збірку, згрупованих у підпрограми F1, F2, ..., F5. Інструкція - це пара присудка ("немає", "якщо на червоному", "якщо на зеленому", "якщо на синьому") та дії ("йти вперед", "повернути ліворуч", "повернути праворуч", "пофарбуйте поточний квадрат червоним", "пофарбуйте його в зелений колір", "пофарбуйте його в синій колір", "не робіть нічого", "зателефонуйте F1", ..., "зателефонуйте F5"). Виклики до підпрограм використовують стек і можуть бути рекурсивними. Як і у звичайному програмуванні, після останньої інструкції підпрограми виконання виконується з того моменту, коли викликалася підпрограма. Виконання починається з першої інструкції F1 і триває до тих пір, поки робот не відвідав усі квадрати із зірками, або коли робот крокує на чорному квадраті чи за межами карти, або виконано 1000 інструкцій (невдалі предикати і дії "нічого не робити") не рахувати), або немає більше інструкцій для виконання (стек під переливом).

Вхідні дані:

  • a- матриця символів 12х16 (як це зазвичай представлено вашою мовою, наприклад, масив рядків), що кодує карту - '#'для недоступних (чорних) квадратів, '*'для квадратів із зіркою, '.'для решти

  • c- матриця символів 12х16, що описує кольори доступних квадратів - 'R'(червоний), 'G'(зелений) або 'B'(синій). Недоступні квадрати будуть представлені довільною літерою з трьох.

  • yі x- рядок і стовпець на основі робота; a[y][x]гарантовано буде'.'

  • d- напрямок робот облицювальний: 0 1 2 3для правого, вниз, вліво, вгору, тобто в напрямку (y,x+1), (y+1,x), (y,x-1),(y-1,x)

  • f- один рядок, об'єднані реалізації F1 ... F5. Кожна реалізація - це (можливо, порожня) послідовність пар предикатних дій (щонайбільше 10 пар на підпрограму), що закінчується символом a '|'.

    • предикати: '_'жоден, 'r'червоний, 'g'зелений, 'b'синій

    • дії: 'F'йти вперед, 'L'повернути ліворуч, 'R'повернути праворуч, 'r'пофарбувати в червоний, 'g'пофарбувати в зелений, 'b'пофарбувати в синій, '1'подзвонити F1, ..., '5'зателефонувати F5, '_'нічого не робити

Вам не потрібно називати вводи, як зазначено вище, але їх значення повинні бути зазначеними.

Вихід: 1(або true), якщо робот збирає всі зірки за правилами, 0( false) в іншому випадку.

Приклад :

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 на виклик "Цикл це" ви можете сортувати останнє значення кута, зменшуючи складну величину.
користувач202729

1
@ user202729 Ні, я не очікував коментарів щодо цього виклику тут :) Ваша ідея працює, дякую! Я спробую реалізувати це, не роблячи символу занадто ганебним.
ngn

1
Чи можна вважати матриці символів списками пар місць та символів?
0

1
@ 0 'Принцип, якого я тут дотримуюсь (див. Також коментар HyperNeutrino), - це максимально наблизитись до вхідного формату, який фактично використовується на robozzle.com, тому я боюся, що це не повинен бути список пар.
ngn

Відповіді:


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повинен бути рядок з подвійним цитуванням.

Пояснення

Ця програма містить три предиката, */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 аналізує рядки з цитатами, що цитуються. Друга - це асоціативна карта від точок на карті 12х16 (представлена ​​як X^Y) до 32 плюс код символів, що зберігається в цій точці у списку списків кодів символів. 32 додається до кожного з символьних кодів, так що для кольорової матриці він перетворює великі символи кольорів у великі кольори.

Як це робиться, генерується список пар точок і код символів у цій точці, використовуючи findall/3. Потім він використовує list_to_assoc/2для створення відповідної асоціативної карти від точок до коду символів у цій точці.

findall/3Предикат є вбудованим приймає «шаблон» в якості першого аргументу, цілі в якості другого аргументу і списку в якості третьої аргументу. Присудок заповнює список усіма можливими значеннями шаблону, які спричиняють успіх мети. Через перевагу оператора шаблон, який передається findall/3в */2, аналізується як (X^Y)-D. -Оператор є пару з двох значень в Пролозі тому шаблон представляє положення точки ( 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рядок символьної матриці, Oтоді як другий виклик зберігає Xth-символ у цьому рядку C. Остаточний предикат plus/3досягається успіху, якщо перші два його аргументи дорівнюють третьому аргументу. Це використовується для того, щоб код символу в парі був на 32 більше, ніж код символу в матриці символів, який, як зазначено вище, перетворить всі великі літери в малі літери.

Нарешті, findall/3зберігається всі X^Y-Dкомбінації, які спричиняють досягнення його мети в списку, з Lякого побудована асоціативна карта.

Більше скоро ...


4

JavaScript (ES6), 298 276 264 байт

Збережено 8 байт завдяки @ngn

Приймає введення як (a,c,x,y,d,f), де aі cє масивами масивів символів. Повертається 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

1
xзмінюється НЕ більш ніж на 1, так що я думаю , що ви можете замінити x&~15зx&16
NGN

1

APL (Dyalog Classic) , 236 233 байт

-3 подяки Еріку Переверху

Тепер, коли я видав бонус, я розміщую зразок рішення для власного виклику. Тут є можливість для вдосконалення - сміливо копіюйте та гольфуйте далі.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.