Gültige Schlangen im Flugzeug

23

Inspiriert von einem von Vi Harts Videos (ein Schatz voller potenzieller Herausforderungsideen)

Eine Schlange besteht aus Segmenten gleicher Länge und die Verbindung zwischen jedem Segment kann gerade sein oder eine 90 ° -Drehung ausführen.
Wir können eine solche Schlange (bis zu einer Drehung, die von der Anfangsrichtung abhängt) kodieren, indem wir die Richtung der Umdrehungen (Gerade / Links / Rechts) aufschreiben . Dieser beginnt oben links und zeigt nach rechts

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

Würde durch das Rutschen vertreten sein SRSLSSLRLRSSRSRSS

Und natürlich kann sich eine planare Schlange nicht schneiden (wie in SSSSLLLSS), was zu einem schrecklichen pixeligen Game Over führen würde.

Ihre Aufgabe ist es festzustellen, ob ein Slither gültig ist oder nicht (führt zu mindestens einer Selbstüberschneidung)

Eingang
Eine Zeichenfolge aus Buchstaben gemacht SLRmit 2 < length < 10000
Output
Etwas truthy wenn es eine gültige schlittern und etwas Falsey ist , wenn es nicht.

Testfälle

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

__Invalid__
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

Sie können die Slithers hier zeichnen (R und L sind gespiegelt, aber es hat keinen Einfluss auf die Gültigkeit)

DenDenDo
quelle
Müssen Eingaben im Programm gemacht werden oder können sie aus einer Datei gelesen werden?
MI Wright
1
Sollte SRRR wahr oder falsch sein? Es verbindet sich, schneidet sich aber nicht.
Orlp
rührende Schlangen fordern NSFW heraus?
Ewan
3
Wenn Sie SRRRauf Millimeterpapier mit einem Quadrat pro Segment zeichnen, überlappt es sich und ist daher ungültig, belegt RRRjedoch genau ein 2x2-Quadrat ohne Überlappungen (genau wie im klassischen Spiel)
DenDenDo
Ähnlich, aber kein Duplikat (aufgrund unterschiedlicher Zielsetzungen und unterschiedlicher Konstruktionsregeln).
Trichoplax

Antworten:

20

Pyth, 22 bis 20 Bytes

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

Probieren Sie es aus oder führen Sie die Testsuite aus .

Beachten Sie die ASCII-Werte von SRL bzw. 83, 76, 82. Ich missbrauche die Tatsache, dass:

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

Von hier aus behalte ich nur eine Variable für die aktuelle Position und die aktuelle Richtung. Für jedes Zeichen multipliziere ich die aktuelle Richtung mit der obigen komplexen Zahl und addiere sie dann zur aktuellen Position.

Am Ende überprüfe ich, ob alle besuchten Positionen eindeutig sind.

orlp
quelle
SRRR = wahr ????
Ewan
@Ewan Bei näherer Betrachtung - Ich bin mir nicht sicher, ob das falsch sein sollte oder nicht. Kopf und Schwanz verbinden sich, kreuzen sich aber nicht.
Orlp
was ist mit SRRRS?
Ewan
@Ewan Gleiche Geschichte - Verbindung, aber keine Kreuzung. Die Frage ist nicht klar, was für diese zurückgegeben werden soll.
Orlp
1
Wie würdest du SRRR zeichnen?
Ewan
6

CJam, 30 Bytes

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

Erklärung folgt in Kürze.

Probieren Sie es hier online aus oder führen Sie die gesamte Suite aus .

Optimierer
quelle
Verdammt, das ging schnell. Ich habe noch nicht einmal an einen Algorithmus gedacht, um ihn selbst zu lösen.
DenDenDo
SRRRS = wahr ???
Ewan
@Ewan ähm, nehmen wir an, dass 0 anfänglich gefüllt ist und zählt?
Optimierer
1
Ich denke, ich interpretiere es wie ein Schlangenspiel, bei dem Bewegungen Blöcke von Raum einnehmen. und einige von euch interpretieren es als Null-Breiten-Linie
Ewan
@Ewan Meine Frage ist allerdings etwas anders. Wenn wir zum Beispiel einen einzigen Zug haben S, bedeutet das, dass die Schlange bereits sowohl (0,0) als auch (1,0) belegt hat?
Optimierer
6

JavaScript (ES6), 84 89

Führen Sie zum Testen das Snippet in Firefox aus.

Einige Notizen:

  • Die Schlange bewegt sich innerhalb des f-Arrays. Nicht besuchte Zellen haben Wert undefined. Beim ersten Besuch ändert der Tilde-Operator den Wert in -1, was der Wahrheit entspricht. Schließlich ändert sich der Wert bei einem zweiten Besuch auf 0, was falsch ist und die everySchleife endet , wenn false zurückgegeben wird.
  • In JS sind Array-Elemente mit nicht-kanonischen Indizes (nicht numerisch oder negativ) irgendwie „verborgen“, existieren jedoch. Hier verwende ich ohne Probleme negative Indizes.

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>

edc65
quelle
6

TI-BASIC, 49 56 53 51 Bytes

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

Ähnlich wie bei orlp wird eine Liste aller Punkte in der komplexen Ebene erstellt, die von der Schlange besucht werden, beginnend mit dem Ursprung. Wenn die Liste keine doppelten Elemente enthält, gibt der Code einen positiven Wert zurück. Beachten Sie, dass der Taschenrechner bei einer Zeichenfolge mit mehr als 999 Elementen keine ausreichend lange Liste generieren kann und eine Fehlermeldung ausgibt.

BEARBEITEN: Zwei Bytes auf Kosten der Hässlichkeit gespart, da keine zwei Gitterpunkte auf der komplexen Ebene den gleichen Abstand von e ^ i haben können.

Lirtosiast
quelle
5

TI-BASIC, 60 58 Bytes

Edit: Ignoriere alles unten: Eine funktionierende Ti-Basic-Lösung ist hier , von Thomas-Kwa. Stimmen Sie dem zu!

ist der [(-)]Schlüssel, und Ans ist [2ND]->[(-)]. Führen Sie es aus, indem Sie die Anweisungen der Schlange in Anführungszeichen ( [ALPHA]->[+]) setzen, gefolgt von einem Doppelpunkt und dem Namen des Programms. Wenn Sie beispielsweise das Programm "SNAKE" nennen, führen Sie den Testfall im OP als aus "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

Bearbeiten: Scheitert an SRRLSLLRRRS. Ich habe eine überarbeitete Version mit 61 Bytes, aber sie schlägt beim ersten ungültigen Testfall fehl:

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

Ich werde versuchen, morgen zu reparieren.


Update: also das Problem ist eigentlich, dass mein Algorithmus fehlerhaft ist. Wenn ich eine For (Schleife im Gegensatz zu seq ((um das Gleiche zu erreichen)) verwendet hätte, könnte sie (eigentlich beide oben genannten Algorithmen) folgendermaßen beschrieben werden:

  1. Initialisieren Sie die Zählervariable auf 1.
  2. Lesen Sie die Zeichenfolge. Wenn sich das Symbol ändert, erhöhen Sie die Zählervariable. Wenn sich das Symbol wiederholt, verringern Sie es.
  3. Ist die Zählervariable größer als 0, wird 1 (gültig) angezeigt. Andernfalls wird 0 angezeigt (ungültig).

Dies scheitert jedoch an ungültigen Slithern wie SRLRLRLRLRRRSS. Ich werde jetzt versuchen, einen besseren Algorithmus zu finden ... oder aus einer anderen Antwort zu stehlen.


Ich bin zu 90% sicher, dass dies durch einen einzigen seq(Befehl ersetzt werden kann, aber im Moment ist dies so klein, wie ich es bekommen kann. Wenn Sie beabsichtigen, dies mit Sourcecoder auf ein 8xp- Format umzustellen, anstatt es tatsächlich einzutippen , beachten Sie, dass das Bit durch !=und das ⁻1+Bit durch ersetzt werden sollte ~1+.

MI Wright
quelle
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}

Online-Test: http://ideone.com/pepeW2

Ungolfed-Version:

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
}
Cristian Lupascu
quelle
0

Golfscript 48 49 50

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

Erwartet, dass die Zeichenfolge auf dem Stapel vorhanden ist, und gibt entweder 0oder zurück 1.

Sie können es online mit Tests für gültige und ungültige Schlangen versuchen .

Dies ist im Grunde die gleiche Idee wie in meiner Ruby-Antwort . Lediglich das Richtungsarray wird unterschiedlich behandelt, da AFAIK Golfscript keine Arary-Rotate-Funktion besitzt. In diesem Fall erstelle ich ein ausreichend großes Richtungsarray, indem ich es 10000-mal multipliziere und dann von Anfang an 0, 1 oder 3 Elemente abschneide, je nach aktuellem Befehl (S, R oder L). Die aktuelle "Richtung", in die verschoben werden soll, ist immer das erste Element im Array.

Hier ist es mit Kommentaren:

# 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
..&=

Bearbeiten:

1 Zeichen gespart, indem geändert wurde, wie das Array "directions" verbraucht wird.

Bearbeiten:

1 Zeichen durch Verschieben von Schritten von 10 anstelle von 1 gespeichert, um die ?(Power-) Syntax zu verwenden.

Cristian Lupascu
quelle