Kürzester selbstvermeidender Pfad bei einer Abfolge von Kurven

15

Schreiben Sie ein Programm oder eine Funktion, die bei einer nicht leeren Folge von Rechts- oder Linkskurven die Länge des kürzesten selbstvermeidenden Pfades auf einem 2D-Gitter mit diesen Windungen ausgibt.

Die Eingabe sollte als String, wobei jedes Zeichen Befinden eingenommen werden Roder Ljeweils für ein Rechts- oder Linksabbiegen.

Die Ausgabe sollte eine ganze Zahl sein, die Länge des kürzesten Pfades mit den gegebenen Windungen.

Dies ist ein Gode Golf - der kürzeste Code gewinnt.

Beispiel

Angesichts der Eingabe

LLLLLLLLLLRRL

Der kürzeste Weg ist der folgende (beginnend mit #):

+-+-+-+-+-+-+
|           |  
+ . + +-+-+ +
|   | |   | |  
+ +-+ + #-+ +
| |   |     |  
+ +-+ +-+-+-+
|   |          
+-+-+ . . . .

Und die Gesamtlänge dieses Pfades ist 29(Zählen der -s und |s, nicht der +s).

Testfälle

L 2
RRRRRRRRRR 23
LRRLRLRRRRL 15
LLRRLRRRRLLL 17
LLRRRRRRLLLL 21
LLLLRLLRRLLRL 16
LRLRLRLLRLRRL 14
RLLRRRRLLRRLRL 17
RRRRLLRLLLRLRL 20
LLLLRRLRLRRRLRL 19
RRRLRRRLRRLRLRL 20
Pappkarton
quelle
Selbstvermeidung auch an Ecken (z. B. auf dem Main nach Süden in Richtung Elm zu gehen und nach Osten auf Elm abzubiegen und später auf dem Main nach Norden in Richtung Elm zu gehen und nach Westen auf Elm abzubiegen, ist ein Nein-Nein)?
msh210
2
@ msh210 ja, es kann nicht zweimal denselben Punkt besuchen, auch nicht an einer Ecke.
cardboard_box

Antworten:

8

Prolog, 284 Bytes

e(S,[0|X]):-e(S,X).
e([A|S],[A|X]):-S=X;e(S,X).
v(X/Y,76,Y/Z):-Z is -X.
v(X/Y,82,Z/X):-Z is -Y.
v(D,0,D).  
c([],0/0-0/1,[0/0]).
c([H|T],K/L-D/E,[K/L|C]):-c(T,I/J-X/Y,C),v(X/Y,H,D/E),K is I+X,L is J+Y,\+member(K/L,C).
n(X):-X=0;n(Y),X#=Y+1.
p(S,L):-n(L),length(X,L),e([0|S],X),c(X,_,_).

Dies ist eine ziemlich einfache Aussage des Algorithmus und ziemlich ineffizient (nicht alle Testfälle liefen in angemessener Zeit, obwohl die meisten dies taten). Es funktioniert durch Generieren aller möglichen Längen für die Ausgabe von 1 aufwärts ( n); Erzeugen aller möglichen Sequenzen von links / vorwärts / rechts dieser Länge, die mit der Eingabe übereinstimmen (implementiert in e; der neue Pfad wird aufgerufen X); Suchen Sie dann nach dem ersten gültigen Pfad ( cder vdie Auswirkungen von Links- und Rechtskurven auf die x- und y-Deltas behandelt). Die Rücklauflänge ist die erste Ausgabe inL. (+2 Strafe, wenn Sie verhindern möchten, dass die Funktion andere mögliche Ausgaben für die Länge zurückgibt, wenn Sie zurückverfolgen; es ist nie ganz klar, wie die eigenwilligen Funktionsrückgaben von Prolog gezählt werden sollten.)

Hier gibt es nicht viel Golf-Tricks, aber es gibt einige. nwurde mit einem Constraint-Solver implementiert, da dadurch mehr Leerzeichen entfernt werden können, ohne den Parser zu verwirren. Dies kann die Verwendung von GNU Prolog erfordern, da Sie sich nicht sicher sind. (Ich konnte nicht das Gleiche tun, cda es mit negativen Zahlen umgehen muss.) Die Implementierung von eist erheblich weniger effizient als nötig, da eine Liste auf mehrere Arten abgeglichen wird. Das effizientere e([],[]).wäre sechs Bytes länger (es würde das S=X;Entfernen von Zeile 2 ermöglichen, aber das ist nur ein Gewinn von vier im Vergleich zu einem Verlust von zehn). Damit ich Koordinaten und Richtungen als Ganzes oder nur als Teil X/Yabgleichen kann , stelle ich sie als (dh als nicht bewertete AST, die angepasst werden kann) dar, sodass ich die Infix-Notation verwenden kann.

Prolog, 256 Bytes, zu ineffizient, um einfach getestet zu werden

Da dies Prolog ist, sind natürlich viele der Funktionen reversibel, z. B. ckönnen sie verwendet werden, um alle Pfade vom Ursprung zu einem bestimmten Koordinatenpaar zu generieren. Darüber hinaus cerzeugt natürlich vom kürzesten zum längsten. Dies bedeutet, dass wir, anstatt explizit nach einer Mindestlänge zu fragen, einfach alle Pfadec generieren können, die irgendwohin führen , und dann nach dem ersten suchen können, der mit der Eingabe übereinstimmt:

e(S,[0|X]):-e(S,X).
e([A|S],[A|X]):-S=X;e(S,X).
v(X/Y,76,Y/Z):-Z is -X.
v(X/Y,82,Z/X):-Z is -Y.
v(D,0,D).
c([],0/0-0/1,[0/0]).
c([H|T],K/L-D/E,[K/L|C]):-c(T,I/J-X/Y,C),v(X/Y,H,D/E),K is I+X,L is J+Y,\+member(K/L,C).
p(S,L):-c(X,_,_),length(X,L),e([0|S],X).

Dies hat eine exponentielle Leistung (O (3 n ), wobei n die Ausgabe ist). Ich habe es jedoch geschafft, es bei einigen der kleineren Tests zu überprüfen (es dauert ungefähr 7 Sekunden, um 14 auszugeben, und ungefähr 20, um 15 auf meinem Computer auszugeben).


quelle
Ich konnte das bei TIO nicht zum Laufen bringen , aber ich könnte etwas Dummes tun.
Peter Kagey
@PeterKagey Ich weiß nicht viel Prolog, aber ich denke, das funktioniert. Für die Eingabe "LRRLRLRRRRL"
H.PWiz
4

Pyth , 36 Bytes

ff{I.u+NYY0f>r8YlQ.C+1*M._m^.j)hCdQT

Probieren Sie es online aus!

Dies ist ziemlich langsam, funktioniert aber und ist schnell genug für kurze Eingaben.

Das Programm stellt Richtungen als komplexe Einheiten (1, -1, i, -i) und Punkte als komplexe Zahlen dar. Zuerst konvertiere ich die Liste der Abbiegungen in eine Liste von Richtungen, generiere dann alle Listen von n Schritten, filtere nach denen mit mindestens einem Schritt zwischen jeder Abbiegung und konvertiere die Richtungen in eine Liste der besuchten Punkte und überprüfe, ob diese Liste vorhanden ist einzigartig. Ich inkrementiere n in einer Schleife, bis ich erfolgreich bin.

Zuordnung zu komplexen Zahlen:

m^.j)hCdQ
m       Q    Map over the input
      Cd     Convert to ASCII codepoint
     h       Increment
 ^.j)        Raise i to that power.

Da LASCII - Codepunkt 76 hat und RASCII - Codepunkt 82 hat, ordnet diese Lzu iund Rzu -i.

Karte zu absoluten Richtungen:

+1*M._ ...
    ._      Form all prefixes
  *M        Map each to its product
+1          Add the first direction, before any turns

Bilden Sie Listen mit n Schritten mit mindestens 1 Schritt zwischen den einzelnen Runden

f>r8YlQ.C ... T
       .C     T    Form all list of T steps
f                  Filter for lists where
  r8Y              Run length encoding of list
 >   lQ            With the first len(input) removed
                   is nonempty

Es sollte eine Bewegung mehr geben, als der Eingang dreht. Jede Bewegung verläuft in eine andere Richtung, daher sollte die Lauflängencodierung länger als die Eingabe sein.

Karte zu den besuchten Punkten:

.u+NYY0  ...
.u   Y0   Reduce the following function over
          the list of steps, starting at 0.
          Return all intermediates.
  +NY     Add the new step to the current position.

Filter nach nicht sich selbst überschneidenden:

f{I ...
f     Filter on
  I   Invariant under
 {    Deduplication

Finden Sie die erste, Two dies erfolgreich ist : f.

isaacg
quelle