Aiuto, sono intrappolato in una fabbrica infinita!


26

Questa sfida è liberamente ispirata al gioco Zachtronics Infinifactory .

Ti viene data una vista dall'alto verso il basso di una griglia rettangolare di nastri trasportatori, rappresentata da >v<^. Potrebbero esserci celle senza convogliatori, rappresentate da spazi. Ecco un esempio:

> <vv    <
 v ^ >v v 
  >v^^>vv^
    ^>^ v 
>  v<v  >>
  >v v<^  

Questa configurazione è implicitamente circondata da un numero infinito di spazi.

Inoltre, ti vengono fornite le dimensioni di un pezzo di carico rettangolare che viene posizionato sui nastri trasportatori nell'angolo in alto a sinistra della griglia. Il tuo compito è capire se il carico si ferma mai o se finirà per muoversi in loop.

Naturalmente, è probabile che il carico copra più trasportatori contemporaneamente, quindi ecco le regole per capire la direzione del carico in ogni passaggio:

  1. I trasportatori di fronte si annullano a vicenda. Quindi, se un carico 3x2 copre una delle seguenti patch (delineate con trattini e tubi per chiarezza), il risultato sarebbe lo stesso:

    +---+   +---+   +---+
    |>>^|   |  ^|   |v^^|
    |^<<|   |^  |   |^^v|
    +---+   +---+   +---+
    

    Lo stesso vale per questi:

    +---+   +---+   +---+
    |v^<|   |   |   |><>|
    |>>>|   |>> |   |>><|
    +---+   +---+   +---+
    

    Poiché la posizione esatta di un trasportatore sotto il carico è irrilevante, non importa quali coppie si annullano.

    Questa cancellazione viene applicata prima delle altre regole. Pertanto, per le altre regole ci saranno solo nastri trasportatori al massimo in due direzioni.

  2. Se il carico non copre affatto i nastri trasportatori (sia perché tutti i nastri trasportatori si annullano, perché copre solo gli spazi o perché si è spostato completamente dalla griglia), si ferma.
  3. Se il carico copre più convogliatori di una direzione rispetto all'altra, il carico si sposta in quella direzione. Ad esempio, se un carico 3x2 copre la seguente patch

    >>
    ^>^
    

    si sposterà a destra, perché ci sono più >di ^. D'altra parte, se coperto

    >>^
      ^
    

    questa regola non si applica, perché esiste un legame tra >e ^.

  4. Ciò lascia solo casi in cui esiste un legame tra direzioni adiacenti (un legame tra direzioni opposte avrebbe annullato). In questo caso, il carico continua a muoversi lungo l'asse in cui si sta già muovendo. Ad esempio, se un carico 3x2 con movimento a destra o a sinistra copre ora il patch

    >>^
    ^  
    

    si sposterà a destra. Se fosse arrivato su questa patch spostandosi verso l'alto o verso il basso, ora si sposta invece verso l'alto. Se questo tipo di conflitto si verifica nel primo passo della simulazione, supponiamo che il carico si sia spostato a destra.

Esempi dettagliati

Considera la griglia di trasporto in alto e un carico 3x2. Di seguito è riportata una visualizzazione dettagliata del processo. Ogni passaggio è costituito dalla griglia, con il carico rappresentato da #, una piccola scatola che mostra i trasportatori coperti dal carico, un'altra scatola con i trasportatori dopo la cancellazione e la regola che determina dove si muove il carico:

 ###vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <
 ###^ >v v     ###^ >v v      v ^ >v v      v ^ >v v      v ^ >v v      v ^ >v v 
   >v^^>vv^    ###v^^>vv^    ###v^^>vv^     ###^^>vv^      ###^>vv^      >###>vv^
     ^>^ v         ^>^ v     ### ^>^ v      ###^>^ v       ###>^ v        ###^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>
   >v v<^        >v v<^        >v v<^        >v v<^        >v v<^        >v v<^  

+---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+
|> <|  |   |  | v |  | v |  |  >|  |  >|  | >v|  | >v|  |>v^|  |> ^|  |v^^|  | ^^|
| v |  | v |  |  >|  |  >|  |   |  |   |  |   |  |   |  |  ^|  |   |  | ^>|  |  >|
+---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+

   Rule 3        Rule 4        Rule 3        Rule 4        Rule 4        Rule 3

 ================================================================================

 > <vv    <    > <###   <    > <vv    <
  v ###v v      v ###v v      v ###v v 
   >###>vv^      >v^^>vv^      >###>vv^
     ^>^ v         ^>^ v         ^>^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>
   >v v<^        >v v<^        >v v<^  

+---+  +---+  +---+  +---+  +---+  +---+
|^ >|  |  >|  |vv |  | v |  |^ >|  |  >|
|v^^|  | ^^|  |^ >|  |  >|  |v^^|  | ^^|
+---+  +---+  +---+  +---+  +---+  +---+

   Rule 3        Rule 4        Rule 3

A questo punto, il carico entra in un loop tra gli ultimi due frame.

Ora considera invece un carico 2x3:

 ##<vv    <    >##vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <
 ## ^ >v v      ##^ >v v      ##^ >v v      v ^ >v v      v ^ >v v      v ^ >v v 
 ##>v^^>vv^     ##v^^>vv^     ##v^^>vv^     ##v^^>vv^      ##^^>vv^      >v^^>vv^
     ^>^ v         ^>^ v      ## ^>^ v      ## ^>^ v       ##^>^ v       ##^>^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>    >##v<v  >>    > ##<v  >>    > ##<v  >>
   >v v<^        >v v<^        >v v<^        >v v<^        >v v<^        ## v<^  

 +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+
 |> |  |> |    | <|  |  |    |v |  |v |    | >|  | >|    |>v|  |>v|    |  |  |  |
 | v|  | v|    |v |  |v |    | >|  | >|    |  |  |  |    |  |  |  |    | v|  | v|
 |  |  |  |    | >|  |  |    |  |  |  |    |  |  |  |    | v|  | v|    |>v|  |>v|
 +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+

   Rule 4        Rule 3        Rule 4        Rule 3        Rule 3        Rule 3

 ================================================================================

 > <vv    <    > <vv    <    > <vv    <
  v ^ >v v      v ^ >v v      v ^ >v v 
   >v^^>vv^      >v^^>vv^      >v^^>vv^
     ^>^ v         ^>^ v         ^>^ v 
 > ##<v  >>    >  v<v  >>    >  v<v  >>
   ## v<^        ## v<^        >v v<^  
   ##            ##            ##
                 ##            ##
                               ##

 +--+  +--+    +--+  +--+    +--+  +--+
 | v|  | v|    |>v|  |>v|    |  |  |  |
 |>v|  |>v|    |  |  |  |    |  |  |  |
 |  |  |  |    |  |  |  |    |  |  |  |
 +--+  +--+    +--+  +--+    +--+  +--+

   Rule 3        Rule 4        Rule 2

Nell'ultimo passaggio, si applica la regola 2 perché il carico si è spostato dalla griglia, quindi si ferma e non ci sarà un anello.

Regole e presupposti

Il tuo input sarà la griglia del trasportatore come descritto sopra insieme alla larghezza e altezza del carico. Puoi prendere questi tre parametri in qualsiasi ordine e formato convenienti. Per la griglia, ciò significa che è possibile leggere una singola stringa con linee separate da newline o altri caratteri, oppure una matrice di stringhe o una matrice di matrici di caratteri, purché le singole celle della griglia siano ancora rappresentate dai caratteri >v<^e spazi.

Dovresti produrre un valore veritiero se l'installazione risulta in un ciclo di almeno due fotogrammi o un valore falso se il carico si ferma.

Si può presumere che la griglia sarà riempita con un rettangolo con spazi e che il carico inizialmente si adatterà alla griglia.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Questo è il golf del codice, quindi vince la risposta più breve (in byte).

Casi test

I casi di test sono raggruppati per griglia.

Grid (2x2):

>v
^<

Width  Height  Loop?
1      1       True
1      2       True
2      1       True
2      2       False

Grid (3x3):

> v

^ <

Width  Height  Loop?
1      1       False
1      2       False
1      3       False
2      1       False
2      2       True
2      3       True
3      1       False
3      2       True
3      3       False

Grid (4x3):

>^>v
v^v 
^ <<

Width  Height  Loop?
2      2       False

Grid (6x5):

>v>v>v
^v^v^v
^v^v^v
^>^>^v
^<<<<<

Width  Height  Loop?
1      1       True
1      2       False
2      1       True
2      2       True
2      4       True
2      5       False
3      1       False
3      2       True
3      3       True
3      5       True
6      2       False
6      3       True
6      5       False

Grid (10x6):

> <vv    <
 v ^ >v v 
  >v^^>vv^
    ^>^ v 
>  v<v  >>
  >v v<^  

Width  Height  Loop?
1      1       False
2      3       False
2      6       False
3      2       True
5      4       False
6      1       True
10     6       False

Come set aggiuntivo di casi di test, considerare che qualsiasi input in cui la griglia è costituita esclusivamente da spazi deve produrre un risultato errato.

Ho controllato manualmente tutti i casi di test, quindi fammi sapere se pensi di aver fatto un errore.



4
@Fatalize Sto ottenendo Twitch gioca a flashback di Pokemon ...
undergroundmonorail

"Il tuo input sarà la griglia del trasportatore come descritto sopra insieme alla larghezza e all'altezza del carico. Puoi prendere questi tre parametri in qualsiasi ordine e formato convenienti." - significa che possiamo avere la griglia del trasportatore inserita come una matrice di array? Cioè, [^^/v<]diventa una griglia 2x2 con [[0,1] [0,1];[0,-1] [-1,0]]? O vuoi dire che dipende da STDIN, un input di stringa, un input di array di caratteri, ecc., Ma deve comunque essere nella forma di ^, v,> e <?
Glen O

@GlenO Puoi prendere una stringa separata da una nuova riga (o altro carattere), una matrice di stringhe o una matrice di array di caratteri, ma ogni cella dovrebbe essere comunque rappresentata dai caratteri ><^vo da uno spazio. Lo chiarirò.
Martin Ender,

Quindi cosa succede se il carico si sposta in un conflitto in cui la direzione continua non è una delle scelte? Cioè, se si stava muovendo a destra, e ora deve scegliere tra su e sinistra.
Giosuè,

Risposte:


7

Rubino, 306298251 204 198

->g,w,h{m=->y,x,d,v=[]{q=y,x
r=->s{([""]*h+g)[y+h,h].map{|l|(?x*w+l)[x+w,w]}.join.count s}
z=k=r[?v]-r[?^],j=r[?>]-r[?<]
q[d=[d,1,0][j*j<=>k*k]]+=z[d]<=>0
v&[q<<d]!=[]?q!=v[-1]:m[*q,v<<q]}
m[0,0,1]}

Modifica: Grazie mille a Ventero che ha abbreviato molto il codice applicando alcuni trucchi incredibili!

Ingresso e uscita

Il codice rappresenta una funzione ruby ​​che accetta tre parametri:

  • la griglia, rappresentata come una matrice di stringhe (ogni riga è una stringa diversa)
  • la larghezza del carico
  • l'altezza del carico

Ritorna 1(in verità) nel caso ci sia un anello, o nil(falsa) nel caso in cui il carico riposi.

test

Qui sta superando tutti i test di Martin: http://ideone.com/zPPZdR

Spiegazione

Non ci sono trucchi intelligenti nel codice; è un'implementazione piuttosto semplice delle regole.

Nel codice seguente, moveè una funzione ricorsiva che fa una mossa secondo le regole e:

  • restituisce la verità in caso di loop
  • restituisce la falsità in caso di riposo
  • altrimenti si chiama per eseguire la mossa successiva

Una versione più leggibile è disponibile qui .

Nota: il codice golf ha subito diverse modifiche e non è più simile alla versione leggibile.


Dal momento che non importa se rcontiene voci aggiuntive oltre alle quattro direzioni, r[y>=0&&x>=0&&g[y]&&g[y][x]]+=1dovrebbe salvare alcuni byte.
Ventero,

Mi sono preso la libertà di giocare a golf un po 'oltre, spero che non ti dispiaccia: ideone.com/k69BmH
Ventero

@Ventero Wow, hai fatto cose incredibili al codice. Non avrei mai pensato di trasformare l'hash in una lambda. Stavo provando alcune delle mie idee per abbreviare il programma, ma non ero affatto vicino a quello che hai fatto. Molte grazie!
Cristian Lupascu,

2
Sono arrivato a 200 grazie a una gestione leggermente più breve degli indici negativi, suppongo che per ora lo lascerò
Ventero

2
In realtà, 198: ideone.com/ptKrzf :)
Ventero,

8

Python 2, 207 byte

def f(L,w,h,u=0,v=0,D=1,S=[]):a,b,c,d=map(`[r[u*(u>0):u+w]for r in L[v*(v>0):v+h]]`.count,"v^><");D=cmp(abs(a-b),abs(c-d))<D;T=u,v,D;return T in S or a-b|c-d and f(L,w,h,u+cmp(c,d)*D,v+cmp(a,b)*0**D,D,S+[T])

Immettere la griglia come un elenco di righe, ad es

['>v>v>v', '^v^v^v', '^v^v^v', '^>^>^v', '^<<<<<']

seguito da larghezza e altezza. Resi 0o di Trueconseguenza.

Spiegazione

def f(L,          # Grid
      w,h,        # Width, height of cargo
      u=0,v=0,    # Position of top-left of cargo, initially (0, 0)
      D=1,        # Moving left/right = 1, up/down = 0
      S=[]        # Seen (pos, axis) pairs, initially empty
     ):     

     # Arrows under cargo - no need for "".join since we only need to count v^<>
     A = `[r[u*(u>0):u+w]for r in L[v*(v>0):v+h]]`

     # Count for each arrow
     a,b,c,d=map(A.count,"v^><")

     # Golfed form of abs(a-b) < abs(c-d) or (abs(a-b) == abs(c-d) and D == 1)
     D=cmp(abs(a-b),abs(c-d))<D
     T=u,v,D

     return (T in S                # Return True if (pos, axis) previously seen
             or a-b|c-d               # Return 0 if all conveyors cancel
             and f(L,w,h,             # Otherwise, recurse
                   u+cmp(c,d)*D,      # Update u if moving left/right
                   v+cmp(a,b)*0**D,   # Update v if moving up/down
                   D,
                   S+[T]          # Add (pos, axis) to seen
                  )
            )

Non puoi accorciarlo assegnando cmpa una variabile?
Blu

È sufficiente rilevare i cicli controllando le posizioni già visitate? In base alla regola 4, il passaggio successivo può anche essere influenzato dalla direzione precedente. Quindi sembra possibile che tu possa arrivare nella stessa posizione due volte, ma non avere un ciclo perché ti sposti in direzioni diverse in base a direzioni precedenti diverse.
Reto Koradi,

@muddyfish Quello sarebbe solo in pareggio
Sp3000

@RetoKoradi Speriamo risolto
Sp3000

Sì, l'aggiunta Dal tasto di posizione dovrebbe farlo.
Reto Koradi,

8

Julia - 394 300 246 214 byte

f(A,x,y)=(Z=sign;(S,T)=size(A);X=x+1;Y=y+1;G=fill(5,S+2y,T+2x);G[Y:S+y,X:T+x]=A;C=0G;D=1;while C[Y,X]!=D C[Y,X]=D;i,j=sum(i->1-[19 8]i%82%3,G[Y:Y+y-1,X:X+x-1]);D=Z(2i^2-2j^2+(i!=0)D);X+=Z(i+D*i);Y+=Z(j-D*j)end;D^2)

Restituisce 1 se il carico gira e 0 se si ferma. Non è "rigorosamente" verità / falsità, in quanto Julia non consente 0 e 1 in contesti booleani ... ma considero valori xper i quali bool(x)==truesono veritieri e bool(x)==falsefalsi.

L'input Adeve essere nella forma di un array di caratteri. Se stai copiando / incollando la griglia del trasportatore, dovrai inserirla nel modulo appropriato. Per evitare di doverlo gestire manualmente, utilizzare quanto segue:

A=foldl(hcat,map(collect,split("""(PASTE GRID HERE)""","\n")))'

Dove ovviamente, (PASTE GRID HERE)dovrebbe essere sostituito con la griglia stessa. Ricontrolla gli spazi alla fine di ogni linea, per assicurarti che abbia effettivamente tutti gli spazi (non controlla per assicurarti che tutte le linee abbiano la stessa lunghezza). Nota che questa riga non fa parte dell'effettivo codice della soluzione, ma solo un comodo pezzo di codice per rendere l'uso del codice della soluzione un po 'più semplice.

Ungolfed:

function f(A,x,y)
  # Determine size of grid for use later
  (S,T)=size(A)
  # Initialise starting position (performed here to save characters)
  X=x+1
  Y=y+1
  # Create an expanded field that is functionally "spaces" (to provide
  # spaces at edges for the cargo to stop in)
  G=fill(5,S+2y,T+2x)
  # Put the conveyor grid into centre of the expanded field
  G[Y:S+y,X:T+x]=A
  # Create an array storing the most recent movement direction:
  # will use 1=horizontal, -1=vertical, 0=stopped
  C=0G
  # Initialise current direction (same system as C)
  D=1
  # Loop until it finds itself repeating a coordinate/direction pair
  while C[Y,X]!=D
    # Mark current coordinate/direction pair in array
    C[Y,X]=D
    # Determine the net coordinate pairing, stored in two variables
    # for golf purposes *SEE NOTE*
    i,j=sum(i->1-[19 8]i%82%3,G[Y:Y+y-1,X:X+x-1])
    # Determine new movement axis (if D=0, cargo stopped)
    D=sign(2i^2-2j^2+(i!=0)D)
    # Update X or Y depending on signs of D and the appropriate direction
    X+=sign(i+D*i)
    Y+=sign(j-D*j)
  end
  # if D=±1, return 1 (cargo is still moving), otherwise return 0
  return D^2
end

Nota: 1-[19 8]i%82%3è stato scelto per mappare i cinque possibili caratteri alle coppie di coordinate appropriate con il metodo più efficiente che ho trovato. Questo è anche il motivo per cui usi 5 per riempire gli spazi durante la creazione G: è un carattere a una cifra a cui è associato [0 0].

Esempio di utilizzo:

julia> A=foldl(hcat,map(collect,split(""">v>v>v
       ^v^v^v
       ^v^v^v
       ^>^>^v
       ^<<<<<""","\n")))';

julia> f(A,2,1)
true

julia> f(A,3,3)
true

julia> f(A,5,2)
false

f(A,x,y)= è più corto di f=(A,x,y)-> .
Alex A.

@AlexA. - vero, ma probabilmente rimuoverò f=e renderò una funzione anonima quando finirò di giocare a golf.
Glen O

1
Avrà la stessa lunghezza se è una funzione denominata rispetto a una funzione anonima quando ci sono più parametri. f()=contro ()->.
Alex A.
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.