Serpenti validi su un aereo


23

Ispirato da uno dei video di Vi Hart (che sono un tesoro pieno di potenziali idee di sfida)

Un serpente è costituito da segmenti della stessa lunghezza e la connessione tra ogni segmento può essere diritta o effettuare una rotazione di 90 °.
Possiamo codificare un tale serpente (fino a una rotazione, che dipende dalla direzione iniziale) scrivendo una striscia , la direzione delle svolte (Dritto / Sinistra / Destra) che ci vuole. Questo, iniziando in alto a sinistra e puntando a destra

-+    +--+    SR    RSSR
 |  +-+  |     S  RSL  S
 +--+  --+     LSSL  SSR

Sarebbe rappresentato dalla striscia SRSLSSLRLRSSRSRSS

E ovviamente un serpente planare non può intersecarsi (come in SSSSLLLSS), il che si tradurrebbe in un orribile Game Over pixel.

Il tuo compito è determinare se una striscia è valida o meno (si traduce in almeno un autointersezione)

Input
Una stringa composta da lettere SLRcon 2 < length < 10000
Output
Something Truthy se è una striscia valida e qualcosa Falsey in caso contrario.

Casi test

__Valid__
SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR (A hilbert curve)
RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR
SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS (Spiral)
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS (bigger, squigglier spiral)
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL

__Invalid__
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

Puoi disegnare gli slither qui (R e L sono capovolti, ma non influisce sulla validità)


L'input deve essere eseguito nel programma o può essere letto da un file?
MI Wright,

1
SRRR dovrebbe essere vero o falso? Si collega ma non si interseca.
orlp,

toccare serpenti sfida NSFW?
Ewan,

3
se si disegna SRRRsu una carta millimetrata con un quadrato per segmento, si sovrappone e quindi non è valido, RRRtuttavia, semplicemente occuperebbe esattamente un quadrato 2x2 senza sovrapposizioni (proprio come nel gioco classico)
DenDenDo

Simile ma non un duplicato (a causa di obiettivi diversi e regole di costruzione diverse).
trichoplax,

Risposte:


20

Pyth, 22 20 byte

ql{m+=Z*=T^.j)hCdzlz

Provalo tu stesso o esegui il testuite .

Notare i valori ASCII di SRL, rispettivamente 83, 76, 82. Abuso del fatto che:

i 83 + 1 = 1
i 76 + 1 = i
i 82 + 1 = -i

Da qui tengo solo una variabile per la posizione corrente e la direzione corrente. Per ogni personaggio moltiplico la direzione corrente per il numero complesso sopra, quindi lo aggiungo alla posizione corrente.

Alla fine controllo se tutte le posizioni visitate sono uniche.


SRRR = vero ????
Ewan,

@Ewan A un esame più attento - Non sono sicuro se ciò dovrebbe essere falso o meno. La testa e la coda si collegano, ma non si intersecano.
orlp

che dire di SRRRS?
Ewan,

@Ewan Stessa storia - connessione ma nessuna intersezione. La domanda non è chiara su cosa dovrebbe essere restituito per questi.
orlp,

1
come disegneresti SRRR?
Ewan,

6

CJam, 30 byte

q{iF%U+:U[XWe4W1e4]=T+:T}%__&=

Spiegazione a seguire presto.

Provalo online qui o esegui l'intera suite .


Accidenti, è stato veloce. Non ho nemmeno pensato a un algoritmo per risolverlo da solo.
DenDenDo

SRRRS = vero ???
Ewan,

@Ewan umm, stiamo assumendo che 0 sia inizialmente riempito e conti?
Ottimizzatore

1
Immagino di interpretarlo come un gioco di serpenti, in cui le mosse occupano blocchi di spazio. e alcuni di voi ragazzi la stanno interpretando come una linea di larghezza zero
Ewan

@Ewan La mia domanda è un po 'diversa però. Quando abbiamo una sola mossa, diciamo S, significa che il serpente ha già occupato sia (0,0) che (1,0)?
Ottimizzatore

6

JavaScript (ES6), 84 89

Esegui lo snippet in Firefox per testarlo.

Alcune note:

  • il serpente si muove all'interno dell'array f. Le celle non visitate hanno valore undefined. Alla prima visita, l'operatore tilde lo cambia in -1 che è una verità. Alla fine, in una seconda visita il valore cambia in 0 che è falso e il everyciclo termina restituendo false.
  • in JS, gli elementi dell'array con indici non canonici (non numerici o negativi) sono in qualche modo "nascosti", ma esistono. Qui uso indici negativi senza problemi.

F=s=>[...s].every(c=>f[p+=[1,1e5,-1,-1e5][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p],d=p=0,f=[])

//TEST
$('#S').on('keyup mouseup change', Draw);

function Draw(){
  var s = S.value.toUpperCase();
  if (!s) {
    C.width = C.height = 0;
    return
  }
  C.width = 600;
  C.height = 400;
  
  var ctx = C.getContext("2d");  
  var px, py, int=0;
  
  ctx.strokeStyle = '#008';
  ctx.lineWidth = 2;
  ctx.translate(300,200);
  ctx.beginPath();
  ctx.moveTo(0,0);
  
  [...s].forEach(c=>{
    (f[p+=[1,1e4,-1,-1e4][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p])
    ? 1 
    : (++int)
    if (int==1) ctx.stroke(), ctx.strokeStyle = '#800', ctx.beginPath(), ctx.moveTo(10*px,10*py);
    
    py = (p / 1e4 | 0) - 5e3;
    px = (p % 1e4) -5e3
    ctx.lineTo(10*px, 10*py);
  }, d=0,p=50005000,f=[]);
  ctx.stroke();
  
}

valid=["SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS",
"SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL"];
invalid=["SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"];

V.innerHTML=valid.map(s=>F(s)+' '+s).join('\n')
I.innerHTML=invalid.map(s=>F(s)+' '+s).join('\n')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Type to check and draw <input id=S>
(better full page)<br>
<canvas id=C width=1 height=1 ></canvas><br>
Valid<pre id=V></pre>
Invalid<pre id=I></pre>


6

TI-BASIC, 49 56 53 51 byte

abs(e^(i)-cumSum(i^cumSum(seq(inString("SL",sub(Ans,X,1))-1,X,1,length(Ans→X
SortA(∟X
min(ΔList(∟X

Simile al metodo di orlp, questo crea un elenco di tutti i punti nel piano complesso visitato dal serpente, a partire dall'origine. Se l'elenco non ha elementi duplicati, il codice restituisce un valore positivo. Notare che su una stringa di oltre 999 elementi, la calcolatrice non sarà in grado di generare un elenco sufficientemente lungo e si verificherà un errore.

EDIT: salvati due byte a scapito della bruttezza poiché nessun punto reticolare sul piano complesso può essere alla stessa distanza da e ^ i.


5

TI-BASIC, 60 58 byte

Modifica: ignora tutto ciò che segue: una soluzione ti-basic funzionante è qui , di thomas-kwa. Vai a votarlo!

è la [(-)]chiave e Ans lo è [2ND]->[(-)]. Eseguilo racchiudendo le istruzioni del serpente tra virgolette ( [ALPHA]->[+]) seguite da due punti, quindi dal nome del programma. Ad esempio, se si denomina il programma "SNAKE", si eseguirà il test case nell'OP come "SRSLSSLRLRSSRSRSS":prgmSNAKE.

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
Disp 0<sum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans

Modifica: errore SRRLSLLRRRS. Ho una versione rivista a 61 byte, ma non riesce sul primo caso di test non valido:

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
cumSum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans
Disp 0<Ans(dim(Ans

Proverò a riparare domani.


Aggiornamento: quindi il problema è che il mio algoritmo è difettoso. Se avessi usato un For (loop invece di seq ((per ottenere la stessa cosa) (entrambi gli algoritmi sopra, in realtà) potrebbero essere descritti come questo:

  1. Inizializza la variabile contatore su 1.
  2. Leggi la stringa. Se il simbolo cambia, incrementare la variabile contatore. Se il simbolo si ripete, diminuiscilo.
  3. Se la variabile del contatore è maggiore di 0, visualizzare 1 (valido). Altrimenti, visualizza 0 (non valido).

Tuttavia, questo non funziona su slither non validi come SRLRLRLRLRRRSS. Ora proverò a trovare un algoritmo migliore ... o rubare da un'altra risposta.


Sono sicuro al 90% che questo può essere sostituito con un singolo seq(comando, in realtà, ma per ora questo è il più piccolo possibile. Se avete intenzione di costruire l'accaduto a un 8XP utilizzando Sourcecoder al contrario di realtà digitando fuori, nota che dovrebbe essere sostituito con !=e il ⁻1+bit dovrebbe essere sostituito con ~1+.


1

Ruby 87 89

F=->s{d=[1,w=1e4,-1,-w]
v=[w]+s.chars.map{|c|w+=d.rotate!(c<?R?-1:c>?R?0:1)[0]}
v==v&v}

Test online: http://ideone.com/pepeW2

Versione non golfata:

F = -> input {
  # Coordinates are expressed using one number,
  # that is computed using the formula `y + x*max_x`.
  # Assume max horizontal field width (max_x) to be 10000,
  # since that's the max length of the input.
  position = max_x = 1e4

  # These are possible directions to move to (coordinate deltas).
  # The current direction is always the first in the array.
  directions = [1,max_x,-1,-max_x]

  visited = [position]

  visited += input.chars.map{|c|
    # adjust current direction...
    directions.rotate! case c
    when ?L
      -1
    when ?R
      1
    when ?S
      0
    end

    # ...and move there
    position += directions[0]
  }

  # Return `true` if `visited` only contains distinct elements, `false` otherwise
  visited == visited & visited
}

0

Golfscript 48 49 50

[10.4?:z-10z~)]z*z@{'R L S'?@>(@+.`n}%n/@;\;..&=

Si aspetta che la stringa esista nello stack e restituisce 0o 1.

Puoi provarlo online con i test per i serpenti validi e non validi .

Questa è sostanzialmente la stessa idea della mia risposta su Ruby . Solo l'array di direzione viene trattato in modo diverso, perché AFAIK Golfscript non ha una funzione di rotazione arary. In questo caso, creo un array di direzioni sufficientemente grande, moltiplicandolo per 10000 volte e quindi tagliando dal suo inizio 0, 1 o 3 elementi, a seconda del comando corrente (S, R o L). L'attuale "direzione" in cui spostarsi è sempre il primo elemento dell'array.

Eccolo con i commenti:

# Build the direction array and set current position
[1 10000:z-1z~)]z*z

@{
  # For each character in the input:

  # set current direction by cutting 0, 1 or 3 elements 
  # from the beginning of the directions array
  'SR L'?
  @>

  # move to current direction
  .0=@+.

  # format as number and addd newline
  `n
}%

# split by newlines
n/

# cleanup
@;\;

# return 1 if array contains distinct elements, 0 otherwise
..&=

Modificare:

Salvato 1 carattere modificando il modo in cui viene consumato l'array "direzioni".

Modificare:

salvato 1 carattere spostando incrementi di 10 anziché 1 per utilizzare la ?sintassi (potenza).

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.