Interprete RoboZZle


10

Il tuo compito è scrivere un interprete RoboZZle. Se non hai familiarità con il gioco, guarda il video su robozzle.com o leggi la mia descrizione di seguito.

Un robot vive su una griglia rettangolare di quadrati colorati di rosso, verde, blu o nero. I quadrati neri sono inaccessibili. Gli altri sono accessibili e alcuni contengono una stella. L'obiettivo è quello di raccogliere tutte le stelle senza calpestare i quadrati neri o cadere dalla mappa. Il robot occupa un quadrato e si trova in una direzione particolare: sinistra, destra, su o giù. Segue le istruzioni di assemblaggio raggruppate in subroutine F1, F2, ..., F5. Un'istruzione è una coppia di predicato ("none", "if on red", "if on green", "if on blue") e un'azione ("vai avanti", "gira a sinistra", "gira a destra", "dipingi il quadrato rosso attuale", "dipingilo di verde", "dipingilo di blu", "non fare nulla", "chiama F1", ..., "chiama F5"). Le chiamate alle subroutine utilizzano uno stack e possono essere ricorsive. Proprio come nella programmazione convenzionale, dopo che è stata completata l'ultima istruzione di una subroutine, l'esecuzione prosegue dal punto in cui è stata chiamata la subroutine. L'esecuzione inizia dalla prima istruzione di F1 e continua fino a quando il robot non ha visitato tutti i quadrati con le stelle, o quando il robot cammina su un quadrato nero o fuori dalla mappa, o sono state eseguite 1000 istruzioni (predicati falliti e azioni "non fare nulla" non contare) o non ci sono più istruzioni da eseguire (stack underflow).

ingressi:

  • a- una matrice di caratteri 12x16 (come di solito rappresentata nella tua lingua, ad esempio una matrice di stringhe) che codifica una mappa - '#'per quadrati inaccessibili (neri), '*'per quadrati con una stella, '.'per il resto

  • c- una matrice di caratteri 12x16 che descrive i colori dei quadrati accessibili - 'R'(rosso), 'G'(verde) o 'B'(blu). I quadrati inaccessibili saranno rappresentati da una lettera arbitraria dei tre.

  • ye x- la riga e la colonna a base di 0 del robot; a[y][x]è garantito per essere'.'

  • d- la direzione del robot è rivestimento: 0 1 2 3per destra, giù, sinistra, su, cioè verso (y,x+1), (y+1,x), (y,x-1),(y-1,x)

  • f- una singola stringa, le implementazioni concatenate di F1 ... F5. Ogni implementazione è una sequenza (possibilmente vuota) di coppie predicato-azione (al massimo 10 coppie per subroutine), terminata con a '|'.

    • predicati: '_'nessuno, 'r'rosso, 'g'verde, 'b'blu

    • azioni: 'F'vai avanti, 'L'gira a sinistra, 'R'gira a destra, 'r'dipingi di rosso, 'g'dipingi di verde, 'b'dipingi di blu, '1'chiama F1, ..., '5'chiama F5, '_'non fare nulla

Non è necessario nominare gli input come sopra, ma i loro valori devono essere come specificato.

Output: 1(o true) se il robot raccoglie tutte le stelle in base alle regole, 0( false) altrimenti.

Esempio :

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)

Un altro esempio , che coinvolge le istruzioni "vernice":

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

Per generare il tuo test, vai a un puzzle dall'elenco su robozzle.com , prova a risolverlo (o non risolverlo), premi F12 nel tuo browser, digita la console 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()))

e riformatta il risultato per la tua lingua.

Vittorie più brevi. Nessuna scappatoia.


1
Possiamo usare caratteri distinti per rappresentare i dati anziché quelli forniti?
HyperNeutrino,

1
Per la tua risposta APL alla sfida "Loop it", puoi ordinare l'ultimo valore dell'angolo diminuendo la grandezza complessa.
user202729

1
@ user202729 Uh, non mi aspettavo un commento su quella sfida qui :) La tua idea funziona, grazie! Cercherò di implementarlo senza rendere il conto troppo disonorevole.
ngn

1
Possiamo prendere le matrici dei caratteri come un elenco di coppie di posizioni e caratteri?
0

1
@ 0 'Il principio che ho seguito qui (vedi anche il commento di HyperNeutrino) è quello di stare il più vicino possibile al formato di input effettivamente utilizzato su robozzle.com, quindi temo che non dovrebbe essere un elenco di coppie.
ngn

Risposte:


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.

Provalo online!

Questo definisce un predicato che quando chiamato ha successo se tutte le stelle vengono raccolte con successo e fallisce altrimenti. Il predicato prende gli argomenti in quanto tali: a+c+f+x^y^d.. ae cdeve essere un elenco di stringhe tra virgolette, mentre fdeve essere una stringa tra virgolette doppie.

Spiegazione

Questo programma contiene tre predicati, */2, ^/2, e +/2. I */2predicati definiti nella prima riga sono responsabili di parte dell'elaborazione dell'input. Il ^/2predicato calcola in modo ricorsivo come il robot si muove passo dopo passo e ha successo se il robot raccoglie legalmente tutte le stelle e altrimenti fallisce. Il +/2predicato è il predicato principale del programma e prepara l'input per il ^/2predicato con l'aiuto del */2predicato. Si noti che ciascuno di questi predicati prende tecnicamente solo due argomenti, ma usando operatori e pattern matching possono comportarsi come se avessero più argomenti (discuterò questo fenomeno più in profondità qui ).

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

Questo predicato accetta due argomenti. Il primo è un elenco di elenchi di codici di caratteri (questo è il modo in cui Prolog analizza le stringhe citate nel backtick). La seconda è una mappa associativa dai punti nella mappa 12x16 (rappresentata come X^Y) a 32 più il codice carattere memorizzato in quel punto nell'elenco di elenchi di codici carattere. Il 32 viene aggiunto a ciascuno dei codici dei caratteri in modo che per la matrice dei colori trasformi i caratteri di colore maiuscoli in caratteri di colore minuscoli.

Il modo in cui lo fa genera un elenco di coppie di punti e i codici carattere in quel punto usando findall/3. Quindi utilizza list_to_assoc/2per creare la corrispondente mappa associativa dai punti al codice carattere in quel punto.

Il findall/3predicato è un builtin prende un "modello" come primo argomento, un obiettivo come secondo argomento e un elenco come terzo argomento. Il predicato riempie l'elenco con tutti i possibili valori del modello che fanno sì che l'obiettivo abbia successo. A causa della precedenza degli operatori, il modello che viene passato findall/3in */2viene scandito come (X^Y)-D. L' -operatore rappresenta una coppia di due valori in Prolog, quindi il modello rappresenta la posizione del punto ( X^Y) associata a 32 più il codice carattere del punto ( D). Si noti che l' ^utilizzato nella rappresentazione del punto non è in alcun modo collegato al ^/2predicato.

Consideriamo l'obiettivo che viene passato al findall/3predicato.

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

L'obiettivo contiene tre predicati, ognuno dei quali deve avere successo affinché l'obiettivo abbia successo. Il nth0/3predicato che viene utilizzato due volte viene utilizzato per ottenere il valore in un determinato indice dell'elenco (il 0nome nel suo nome indica che è indicizzato zero). La prima chiamata memorizza la Yth riga della matrice di caratteri Omentre la seconda call memorizza il Xth carattere in quella riga C. Il predicato finale ha esito plus/3positivo se i suoi primi due argomenti si sommano al terzo argomento. Questo è usato per rendere il codice di carattere nella coppia maggiore di 32 rispetto al codice di carattere nella matrice di caratteri che come indicato sopra trasformerà tutte le lettere maiuscole in lettere minuscole.

Infine, findall/3memorizza tutte le X^Y-Dcombinazioni che determinano il raggiungimento dell'obiettivo nell'elenco da Lcui è stata creata la mappa associativa.

Maggiori informazioni tra breve...


4

JavaScript (ES6), 298 276 264 byte

8 byte salvati grazie a @ngn

Accetta input come (a,c,x,y,d,f), dove ae csono matrici di matrici di caratteri. Restituisce 0o 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

Casi test

Commentate

(                                           // 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
xcambia al massimo 1, quindi penso che tu possa sostituirlo x&~15conx&16
ngn

1

APL (Dyalog Classic) , 236 233 byte

-3 grazie a Erik the Outgolfer

Ora che ho dato il bonus, sto pubblicando una soluzione di esempio per la mia sfida. Qui c'è spazio per miglioramenti: sentiti libero di copiare e giocare a golf.

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

Provalo online!

Come sopra, espanso con commenti:

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)


Modifica @EriktheOutgolfer applicata, grazie
ngn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.