Fai una BackFlip per ais523!


16

Questa sfida è un premio per ais523 per aver vinto la categoria " Rookie of the Year " in " Best of PPCG 2016 ". Congratulazioni!


BackFlip è un linguaggio di programmazione esoterico creato dall'utente ais523 , che ha creato ben oltre 30 altri esolang interessanti .

BackFlip è un linguaggio 2D come Befunge o > <> in cui il puntatore dell'istruzione attraversa una griglia di testo (il programma), si sposta in alto, in basso, a sinistra e a destra, cambiando direzione a seconda del carattere su cui si trova. Criticamente, la griglia in un programma BackFlip cambia mentre viene attraversata, un po 'come la formica di Langton .

Per questa sfida puoi supporre che un programma BackFlip sia sempre una griglia rettangolare di testo (tutte le righe hanno la stessa lunghezza), almeno 1 × 1, contenente solo i caratteri ./\<>^V. ( .è usato per la visibilità piuttosto che per lo spazio.) Semanticamente la BackFlip che useremo qui è identica alla specifica originale .

Il puntatore di istruzioni (IP) in BackFlip inizia sempre a sinistra dell'angolo in alto a sinistra del programma, andando a destra. Esistono tre tipi di comandi che può incontrare:

  1. .è una no-op. L'IP continua nella direzione in cui stava andando. Il no-op rimane no-op.

  2. /e \sono specchi. Riflettono l'IP nella direzione indicata dal loro angolo, quindi cambiano nell'altro tipo di specchio .

    • Ad esempio, se l'IP punta a sinistra in a \, inizia a spostarsi verso l'alto anziché a sinistra e \diventa a/ .
  3. <, >, ^, E Vsono frecce. Reindirizzano l'IP nella direzione in cui puntano, quindi si trasformano in una freccia che punta nella direzione da cui proveniva l'IP (opposta alla direzione in cui si stava muovendo l'IP) .

    • Ad esempio, se l'IP si dirige verso il basso >, inizia a spostarsi a destra anziché verso il basso e >diventa a ^perché è la direzione da cui proviene l'IP.

Un programma BackFlip termina quando l'IP esce dai limiti, ovvero esce dalla griglia. Si scopre che alla fine tutti i programmi BackFlip finiscono perché i loop infiniti sono impossibili. (Puoi presumere che sia vero.)

Il tuo obiettivo in questa sfida è quello di scrivere un programma o una funzione che accetta un programma BackFlip ed emette il numero di mosse che il puntatore dell'istruzione esegue prima che il programma termini. Questo è, quanti passi compie l'IP durante l'esecuzione di un programma? Ciò include il passaggio iniziale sulla griglia e il passaggio finale di esso.

Ad esempio, il puntatore dell'istruzione esegue 5 passaggi nella griglia banale ....:

 ....  <- empty 4×1 grid
012345 <- step number of the IP

Quindi l'output a .... è 5.

Nella griglia 4 × 2 più complessa

\...
\.><

l'IP esce dalla griglia al suo nono passo, quindi l'output è 9:

step  grid  IP position (@)
0     \...  @....
      \.><   ....

1     \...   @...
      \.><   ....

2     /...   ....
      \.><   @...

3     /...   ....
      /.><   .@..

4     /...   ....
      /.><   ..@.

5     /...   ....
      /.<<   ...@

6     /...   ....
      /.<<   ..@.

7     /...   ....
      /.><   .@..

8     /...   ....
      /.><   @...

9     /...   ....
      \.><   ....
             @

Vince il codice più breve in byte.

Se lo si desidera, è possibile utilizzare l'input come una matrice di righe o matrice di caratteri anziché come una stringa multilinea, ma è necessario utilizzare i caratteri ./\<>^V(non i codici operativi interi). È possibile utilizzare lo spazio anziché .se preferito. Va bene se ai personaggi piacciono\ devono essere evitati in input. L'output è sempre un numero intero più di uno.

Casi test

....
5

\...
\.><
9

.
2

..
3

.
.
2

\
2

^
2

.^.
3

<.
2

\\
\/
7

>V
^<
6

>\
>/
6

\><
2

\><
\><
7

\><
\><
\><
12

\.V.
\.\<
5

\.V.
\./<
9

V./\
V./\
>./<
..\/
14

\V..
.^..
\/><
.V..
.^..
20

\.V.V.
\./.\<
.>\<..
..^.^.
31

\.V.V.V.
\./>/.\<
.>\>\<..
..^.^.^.
69

\.V.V.V.V.
\./>/>/.\<
.>\>\>\<..
..^.^.^.^.
145

\.V.V.V.V.V.V.V.V.V.V.
\./>/>/>/>/>/>/>/>/.\<
.>\>\>\>\>\>\>\>\>\<..
..^.^.^.^.^.^.^.^.^.^.
9721

1
È un peccato che non sia possibile creare una soluzione
BackFlip

Confuso riguardo agli specchi ... fa / inverte le direzioni come a sinistra => su e su => sinistra ,?
officialaimm,

1
@officialaimm La direzione da sinistra in /farà salire l'IP e salendo su /farà andare l'IP a destra, come se fosse una palla che rimbalza su un muro. (Ma ricorda le /modifiche alla barra rovesciata dopo che l'IP l'ha toccato.)
Calvin's Hobbies

perché '\\' <LF> '\ /' è 7 anziché 6?
martedì

Risposte:


3

JavaScript (ES6), 158 byte

f=(a,x=0,y=0,d=3)=>a[x]&&(c=a[x][y])?(a[x][y]=c=='.'?c:c=='/'?(d^=3,'\\'):c=='\\'?(d^=1,'/'):'v>^<'[d][d='^<v>'.search(c),0],f(a,d<3?x+d-1:x,d?y+d-2:y,d)+1):1

Sviluppato indipendentemente dalla risposta di @ tsh anche se sorprendentemente simile.

La mappatura delle direzioni ^<v>verso numeri interi 0-3 è governata dal fatto che .search('^')restituisce 0 poiché ^è un metacarattere regexp.


Mi sento così profondamente picchiato. Ero abbastanza confuso alla fine lì fino a quando non ho realizzato che x e y erano capovolti rispetto a quanto mi aspettassi.
Ørjan Johansen,

@ ØrjanJohansen Questo è un buon punto; forse dovrei scambiare x con y ovunque per rendere più facile la comprensione.
Neil,

2

Haskell , 333 325 byte

MODIFICARE:

  • -8 byte: reso finutile e unito in b.

bprende un elenco di se Stringrestituisce un Integer.

data C a=C{c::a->(a,C a)}
b g=[0,0]#([0,1],map(maybe(C$m 1)C.(`lookup`zip"./^>V<"[n,m(-1),a[-1,0],a[0,1],a[1,0],a[0,-1]]))<$>g)
[y,x]#(d,g)|g&y||g!!0&x=1|n@([f,e],_)<-(($d).c)?x?y$g=1+[y+f,x+e]#n
l&i=i<0||i>=length l
(f?i)l|(p,a:r)<-splitAt i l=(p++).(:r)<$>f a
n d=(d,C n)
a v d=(v,C$a$(0-)<$>d)
m s[d,e]=([s*e,s*d],C$m(-s))

Provalo online!

Come funziona

  • C aè un tipo di dati utilizzato perché Haskell non consente a un tipo di essere ricorsivo senza dichiararlo esplicitamente. Cè anche un costruttore di wrapping ed cè la corrispondente funzione di wrapping . È usato solo con a=[Int].
    • Il tipo C [Int]rappresenta un comando di cella, come una funzione che accetta un [Int]argomento direction ( ) e restituisce una coppia di una nuova direzione e un nuovo C [Int]valore.
  • bè la funzione principale. Converte ogni personaggio in un Cvalore, quindi chiama #.
    • g è la griglia come un elenco di stringhe.
    • Dal momento che \deve essere evitato e quindi è il carattere più lungo da menzionare, il suo risultato viene invece utilizzato come valore predefinito per la ricerca dell'elenco.
  • #esegue la simulazione principale, verificando i limiti &e generando nuove griglie con ?. [y,x]è la posizione corrente, dla direzione corrente e gla griglia corrente. [f,e]è la direzione successiva, ed nè una coppia di esso e la griglia successiva.
  • l&icontrolla se l'indice inon ha limiti per l'elenco l. (Ritorna Truefuori limite, poiché evita una condizione di guardia fittizia #.)
  • Quando f(l!!i)==(d,x), (f?i)l==(d,m)dove si mtrova l'elenco lcon l' ielemento th sostituito dax .
    • Tecnicamente (?i)è un obiettivo più generale, focalizzato sull'i-esimo elemento di un elenco, in questo caso utilizzato con l' (,) [Int]istanza functor.
  • n è la funzione che rappresenta un punto.
  • a vè una funzione che rappresenta una freccia in direzione v.
  • m sè una funzione che rappresenta uno specchio; s==1per \\e s==-1per /.

1

JavaScript, 172 byte

f=(a,d=3,x=0,y=0,n=1)=>(p=a[y]||[],q=p[x])?(p[x]=~(t='^<V>'.indexOf(q))?'^<V>'[d^2]:q=='/'?(t=3-d,'\\'):q=='\\'?(t=d^1,'/'):(t=d,q),f(a,t,x+(t&1&&t-2),y+(~t&1&&t-1),n+1)):n

Ma non posso testare l'ultimo testcase dal momento che ho overflow dello stack sulla mia macchina. (dovrebbe funzionare se c'è una macchina con un ram più grande)

Usiamo un numero per la direzione:

  • 0: ^
  • 1: <
  • 2: V
  • 3:>

Lascia che dsia il numero della direzione ...

  • se incontriamo un '/', abbiamo bisogno di d = 3 - d;
  • se incontriamo un '\' abbiamo bisogno di d = d ^ 1;
  • se incontriamo un '^ <V>' abbiamo bisogno di d = '^ <V>' .indexOf (nota)

Lasciate (x, y)essere la posizione corrente, la posizione successiva è: x+(t&1&&t-2),y+(~t&1&&t-1)

Nota:

La funzione accetta un parametro con il seguente formato:

[ [ '\\', '.', 'V', '.', 'V', '.', 'V', '.', 'V', '.' ],
  [ '\\', '.', '/', '>', '/', '>', '/', '.', '\\', '<' ],
  [ '.', '>', '\\', '>', '\\', '>', '\\', '<', '.', '.' ],
  [ '.', '.', '^', '.', '^', '.', '^', '.', '^', '.' ] ]

Provalo qui

f=(a,d=3,x=0,y=0,n=1)=>(p=a[y]||[],q=p[x])?(p[x]=~(t='^<V>'.indexOf(q))?'^<V>'[d^2]:q=='/'?(t=3-d,'\\'):q=='\\'?(t=d^1,'/'):(t=d,q),f(a,t,x+(t&1&&t-2),y+(~t&1&&t-1),n+1)):n

    ;k=x=>x.split('\n').map(t=>t.split(''));
<textarea id=v>\.V.V.V.V.
\./>/>/.\<
.>\>\>\<..
..^.^.^.^.</textarea><br/><button onclick="r.textContent=f(k(v.value))">Solve</button>
<p>Result: <output id=r></output></p>


Solo per documentare, sto ottenendo Uncaught RangeError: Maximum call stack size exceededcon 16 GB di RAM.
Zeb McCorkle,

1
@ZebMcCorkle aha, basta scoprire che "usa rigoroso" e alcune vardichiarazioni fanno superare l'ultimo testcase (l'interprete js ottimizza le chiamate di coda in modalità rigorosa)
tsh

1

C, 232 221 byte

d,n,t,m[4]={1,-1};char*w="><^V/\\.",*P;main(o,v)char**v;{for(P=v[1],m[2]=-(m[3]=strchr(P,10)-P+1);P>=v[1]&&P<strchr(v[1],0)&&*P^10;++n)*P=w[((o=d,t=strchr(w,*P)-w)<4)?d=t,o^1:(t<6)?d^=t-2,9-t:6],P+=m[d];printf("%d",n+1);}

Accetta input nel primo argomento, stampa il risultato. Richiede che l'input contenga almeno 1 riga (quindi se c'è solo 1 riga, deve terminare con una riga)

Esempio di utilizzo:

./backflip '....
';

Abbattersi:

d,                                          // Direction
n,                                          // Step counter
t,
m[4]={1,-1};                                // Movement offsets
char*w="><^V/\\.",                          // Command lookup
*P;                                         // Cursor location
main(o,v)char**v;{
    for(P=v[1],                             // Begin at 0,0
        m[2]=-(m[3]=strchr(P,10)-P+1);      // Find width of grid
        P>=v[1]&&P<strchr(v[1],0)&&*P^10;   // While inside grid:
        ++n)                                //  Increment step
        *P=w[                               //  Update the current cell
            ((o=d,t=strchr(w,*P)-w)         //  (store current direction & command)
              <4)?d=t,o^1:                  //   If <>^V, write backflip & set dir
            (t<6)?d^=t-2,9-t:               //   If / or \, write flip & bounce
            6],                             //   If ., write unchanged & continue
        P+=m[d];                            //  Move
    printf("%d",n+1);                       // Print result
}

1

Python 3 , 286 byte

[f () accetta input sotto forma di {(0,0):'/',(0,1):'.'}quindi ho anche scritto una funzione g () per convertire una matrice di linee in quella forma]

def f(r):
 x=y=0;d='>';s=1
 while 1:
  try:c=r[y,x];m='>^<V'.find(d)
  except:break
  if(c=="\\"):d='V<^>'[m];r[y,x]="/"
  elif(c=="/"):d='^>V<'[m];r[y,x]="\\"
  elif(c!="."):r[y,x]='<V>^'[m];d=c
  x+=1if(d=='>')else-1if(d=='<')else 0;y+=1if(d=='V')else-1if(d=='^')else 0;s+=1
 return s

Provalo online!

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.