Bewegung auf einem sechseckigen Raster

15

Geben Sie bei Eingabe einer Reihe von Zeichen, die Bewegungen auf einem hexagonalen Gitter darstellen, die endgültigen Koordinaten des "Zeigers" aus.

Unsere Sechsecke werden wie folgt nummeriert:

  _____         _____         _____         _____
 /     \       /     \       /     \       /     \
/ -3,-2 \_____/ -1,-2 \_____/  1,-2 \_____/  3,-2 \
\       /     \       /     \       /     \       /
 \_____/ -2,-1 \_____/  0,-1 \_____/  2,-1 \_____/
 /     \       /     \       /     \       /     \
/ -3,-1 \_____/ -1,-1 \_____/  1,-1 \_____/  3,-1 \
\       /     \       /     \       /     \       /
 \_____/ -2,0  \_____/  0,0  \_____/  2,0  \_____/
 /     \       /     \       /     \       /     \
/ -3,0  \_____/ -1,0  \_____/  1,0  \_____/  3,0  \
\       /     \       /     \       /     \       /
 \_____/ -2,1  \_____/  0,1  \_____/  2,1  \_____/
 /     \       /     \       /     \       /     \
/ -3,1  \_____/ -1,1  \_____/  1,1  \_____/  3,1  \
\       /     \       /     \       /     \       /
 \_____/       \_____/       \_____/       \_____/

Der Zeiger beginnt bei (0, 0).

Die Anweisungen, die Sie unterstützen müssen, lauten wie folgt:

  • q: nach links oben bewegen
  • w: nach oben bewegen
  • e: nach rechts oben gehen
  • a: nach links unten bewegen
  • s: sich abwärts bewegen
  • d: gehe nach rechts unten
  • r: Gitter im Uhrzeigersinn drehen
  • R: Gitter gegen den Uhrzeigersinn drehen

Die Rotationsbefehle drehen das gesamte Gitter, während der Zeiger auf den gleichen Koordinaten bleibt. (Warum qweasd? Sie stimmen gut mit den Anweisungen auf einer QWERTZ-Tastatur überein.)

Um dies besser zu veranschaulichen, gehen Sie wie folgt vor, wenn der Zeiger in der Mitte beginnt:

         _____
        /     \
  _____/   w   \_____
 /     \       /     \
/   q   \_____/   e   \
\       /     \       /
 \_____/       \_____/
 /     \       /     \
/   a   \_____/   d   \
\       /     \       /
 \_____/   s   \_____/
       \       /
        \_____/

Nach einer Drehung im Uhrzeigersinn ( r) werden die Befehle neu zugeordnet (stellen Sie sich vor, Sie drehen das gesamte Hex-Gitter, behalten aber weiterhin "w" usw. bei, was dem Folgenden entspricht):

         _____
        /     \
  _____/   e   \_____
 /     \       /     \
/   w   \_____/   d   \
\       /     \       /
 \_____/       \_____/
 /     \       /     \
/   q   \_____/   s   \
\       /     \       /
 \_____/   a   \_____/
       \       /
        \_____/

In ähnlicher Weise gegen den Uhrzeigersinn drehenden ( R) Danach würde das Raster zu normalisieren, und gegen den Uhrzeigersinn würde wieder „ Wiederabbildungs“ rotating qwedsazu aqweds.

Die Eingabe muss als einzelne Zeichenfolge angegeben werden, und die Ausgabe kann entweder eine einzelne Zeichenfolge sein, die durch nicht numerische Zeichen (z. B. 1 2oder 3,4) oder ein Array von Ganzzahlen verbunden ist.

Da es sich um , wird der kürzeste Code in Bytes gewinnen.

Testfälle:

In                         Out
---------------------------------
edeqaaaswwdqqs             -2, 0
dddddddddd                 10, 5
wswseaeadqdq               0, 0
<empty string>             0, 0
esaaqrweesrqrq             -1, 0
wrwrwrwrw                  -1, 0
RRssrrrs                   -1, -1
aRRRRwddrqrrqqq            -1, -4
rrrrrrrrrrrrRRRRRRrrrrrrq  -1, -1
rrRrRrrRrrrrRRrRrRR        0, 0
Türknauf
quelle

Antworten:

2

Pyth, 81 Bytes

J_K1=Y"qwedsa"A,ZZFNz=kxYN ?<kZ=Y?<x\rNZ.>Y1.<Y1A,+G@[JZ1KZJ)k+H@[J_2JK2K)k;,G/H2

Die Ausgabe ist eine Liste von Ganzzahlen, die die Koordinaten darstellen.

Meine Lösung ist eigentlich sehr langweilig; Es wird nur das eingegebene Zeichen in einem Array (dem qwedsa) gesucht und anschließend auf zwei Arrays zugegriffen, die die jeweiligen Änderungen in den Koordinaten darstellen. Wenn die Eingabe beispielsweise lautet w, erhalten wir 1 (da es sich um das zweite Zeichen im Array handelt). Dann addieren wir A[1]zu x(wo Aist das Array für die Änderungen in xBezug auf die verschiedenen Eingänge) und B[1]zu y(wo Bsind die Änderungen für y). rund Rwerden durch einfaches Drehen des qwedsaArrays erreicht.

Ich bin sicher, dass jemand mit Pyth viel besser umgehen kann. Ich werde weiterhin versuchen, meine Antwort zu Golf zu spielen!

Sie können es hier ausprobieren .

Rhyzomatisch
quelle
12

Retina , 353 339 178 175 150 130 129 117 Bytes

R
5$*r
T`aq\we\ds`so`r.+
)`r(.*)
$1
^
:
a
sq
e
wd
+`(.+)q
w$1
+`(.+)d
s$1
+`sw

(.*)(\1w?):
$0$2
+`sw|ws

w+
-$0
\w
1

Die Ausgabe erfolgt unär, getrennt durch einen Doppelpunkt. Das bedeutet, dass Sie in der Ausgabe keine wirklichen Nullen sehen (obwohl das Vorhandensein eines Doppelpunkts anzeigt, welche der beiden Koordinaten Null ist, wenn es nur eine gibt).

Probieren Sie es online!

Das hat wirklich Spaß gemacht und war überraschend kurz. :)

Erläuterung

Einige Hintergrundinformationen zuerst. Es gibt mehrere Koordinatensysteme, um hexagonale Gitter zu beschreiben. Die angeforderte verwendet Offset-Koordinaten. Das entspricht im Wesentlichen rechteckigen Gitterkoordinaten, mit der Ausnahme, dass eine Achse ein wenig "wackelt". In der Frage wird insbesondere das auf der verlinkten Seite angezeigte "ungerade-q" -Layout abgefragt. Die Arbeit mit diesem Koordinatensystem ist etwas ärgerlich, da die Änderung der Koordinaten während einer Bewegung nicht nur von der Bewegungsrichtung, sondern auch von der aktuellen Position abhängt.

Ein anderes Koordinatensystem verwendet axiale Koordinaten. Das heißt, Sie stellen sich das Hex-Gitter als eine diagonale Scheibe durch ein Volumen von Würfeln vor und verwenden zwei der Achsen (z. B. x und z), um eine Position auf der 2D-Ebene zu finden. Auf dem Sechskantgitter bedeutet dies, dass die beiden Achsen einen Winkel von 60 (oder 120) Grad bilden. Dieses System ist etwas weniger intuitiv, aber viel einfacher zu handhaben, da jede Richtung einem festen "Delta" -Vektor entspricht. (Für eine bessere Erklärung, wie Sie zu diesem Koordinatensystem gelangen, sehen Sie sich den Link und die schönen Diagramme und Animationen an.)

Wir berechnen die Bewegung in Axialkoordinaten (wobei die Rotation berücksichtigt wird, wie in der Aufforderung angegeben, indem die Bedeutung der Befehle neu zugeordnet wird). Anschließend konvertieren wir die axiale in die ungerade-q-Verschiebung Koordinaten.

Die sechs Bewegungen werden in (xz) Achsenkoordinaten auf die folgenden Delta-Vektoren abgebildet:

q => (-1,  0)
w => ( 0, -1)
e => ( 1, -1)
d => ( 1,  0)
s => ( 0,  1)
a => (-1,  1)

Warten Sie, das ist Retina, wir müssen mit unären Zahlen arbeiten. Wie arbeiten wir mit negativen Unärzahlen? Die Idee ist, zwei verschiedene Ziffern zu verwenden. Einer repräsentiert +1und der andere repräsentiert -1. Das heißt, unabhängig davon, ob wir 1von der aktuellen Position addieren oder subtrahieren möchten , können wir dies immer durch Hinzufügen einer Ziffer tun. Wenn wir fertig sind, reduzieren wir das Ergebnis auf seine Größe (der entsprechenden Ziffer), indem wir ausgeglichene Ziffern löschen. Dann ermitteln wir das Vorzeichen anhand der verbleibenden Ziffer und ersetzen alle Ziffern durch 1.

Es ist geplant, die axialen x- und z-Komponenten links und rechts von a :(als Trennzeichen) vor dem Eingang aufzubauen . wund swird auf der rechten Seite hinzugefügt. qund dwerden auf der linken Seite hinzugefügt , und eund awerden auf beiden Seiten hinzugefügt. Da wund sbereits auf der richtigen Seite von :(die voran gehen wird), werden wir diese als -1und +1Ziffern verwenden.

Lass uns den Code durchgehen.

R
5$*r

Wir fangen damit an, dass wir jeweils Rfünf rs machen. Natürlich entspricht eine Linkskurve fünf Rechtskurven in einem Hex-Gitter. Auf diese Weise können wir den Remapping-Schritt erheblich duplizieren.

T`aq\we\ds`so`r.+

Dies ist eine Transliterationsstufe, bei der die sechs Befehle rotiert werden, wenn sie nach dem ersten gefunden werden r(wodurch der erste verarbeitet wird r). wund dmüssen entkommen werden, um zu verhindern, dass sie in Charakterklassen expandieren. Der ofügt den Quellensatz in den Zielsatz ein, wodurch eine Reihe von Bytes für diese Rotationsaufgaben gespeichert werden. Die Zeichenzuordnung lautet daher:

aqweds
saqweds

wo der letzte sin der zweiten Reihe einfach ignoriert werden kann.

)`r(.*)
$1

Dadurch wird die erste rZeichenfolge aus der Zeichenfolge entfernt, da sie verarbeitet wurde (ich wünschte, ich hätte bereits Substitutionsbeschränkungen implementiert ...). Das )sagt Retina auch, dass sie alle Stufen bis zu dieser in einer Schleife durchlaufen soll, bis sich die Saite nicht mehr ändert. Bei nachfolgenden Iterationen ist die erste Stufe ein No-Op, da keine weiteren Rs vorhanden sind und die zweite Stufe eine weitere Drehung anwendet, solange noch rs in der Zeichenfolge vorhanden sind.

Wenn wir fertig sind, haben wir alle Befehle der Richtung zugeordnet, der sie auf dem nicht gedrehten Raster entsprechen, und können mit der Verarbeitung dieser Befehle beginnen. Natürlich ist diese Bewegung nur eine Summe dieser Delta-Vektoren, und die Summen sind kommutativ, so dass es nicht wirklich wichtig ist, in welcher Reihenfolge wir sie jetzt verarbeiten, da die Rotationen eliminiert wurden.

^
:

Fügen Sie den Koordinatenbegrenzer vorne ein.

Jetzt brauchen wir nicht wirklich zu verarbeiten sund w. Sie sind unsere +1und die -1Ziffern und befinden sich bereits auf der richtigen Seite, :sodass sie am Ende nur wie erforderlich aussteigen. Wir können eine weitere Vereinfachung vornehmen: aist einfach s + qund eist w + d. Lass uns das tun:

a
sq
e
wd

Auch diese sund wwerden einfach rausfallen. Alles, was wir tun müssen, ist, diese qs und ds nach vorne zu schieben und sie in ws und ss selbst zu verwandeln . Wir machen das mit zwei getrennten Schleifen:

+`(.+)q
w$1
+`(.+)d
s$1

Das ist also erledigt. Zeit für die Konvertierung von axialen zu versetzten Koordinaten. Dafür müssen wir die Ziffern kollabieren. Im Moment interessiert uns jedoch nur die linke Seite. Aufgrund der Art qund Weise, in der wir die s und ds verarbeitet haben, wissen wir, dass alle ss auf der linken Seite vor den ws angezeigt werden. Daher müssen wir nur ein Paar überprüfen, um sie zu reduzieren:

+`sw

Nun die eigentliche Umstellung. Hier ist der Pseudocode aus dem obigen Link:

# convert cube to odd-q offset
col = x
row = z + (x - (x&1)) / 2

Richtig, also die linke Seite ist schon richtig. Die rechte Seite benötigt jedoch den Korrekturterm (x - (x&1)) / 2. Taking &1ist dasselbe wie modulo 2. Dies wird im Grunde genommen als x/2Ganzzahldivision, gerundet gegen minus unendlich, analysiert . Für Positiv xaddieren wir also die Hälfte der Ziffern (abgerundet) und für Negativ xsubtrahieren wir die Hälfte der Ziffern (aufgerundet). Dies lässt sich in Regex überraschend prägnant ausdrücken:

(.*)(\1w?):
$0$2

Aufgrund der Habgier stimmt xGruppe 1 für gerade genau mit der Hälfte der Ziffern überein, \1die andere Hälfte und wir können die ignorieren w?. Wir fügen , dass die Hälfte nach der :(die x/2). Wenn xes gerade ist, müssen wir zwischen positiv und negativ unterscheiden. Wenn dies xpositiv ist, w?stimmen die Werte nie überein. Daher müssen die beiden Gruppen immer noch mit der gleichen Anzahl von Ziffern übereinstimmen. Das ist kein Problem, wenn der erste seinfach übersprungen wird und wir abrunden. Wenn xnegativ und ungerade ist, dann ist die mögliche Übereinstimmung mit \1(die Hälfte der xabgerundeten) und dieser optional w. Da beide in Gruppen zusammengefasst sind 2, schreiben wir x/2mit der aufgerundeten Größe (je nach Bedarf).

+`sw|ws

Jetzt reduzieren wir die Ziffern auf der rechten Seite. Dieses Mal kennen wir die Reihenfolge der sund nicht w, daher müssen wir beide Paare berücksichtigen.

w+
-$0

Beide Teile werden jetzt auf eine einzige wiederholte Ziffer (oder gar nichts) reduziert. Wenn diese Ziffer ist w, fügen wir ein Minuszeichen vor.

\w
1

Und schließlich verwandeln wir uns sowohl in eine wals auch sin eine einzige vernünftige unäre Ziffer. (Ich nehme an, ich könnte ein Byte speichern, indem ich woder sals unäre Ziffer verwende, aber das scheint ein bisschen lang zu sein.)

Martin Ender
quelle
10
(Bin ich der Einzige, der diese Antwort auf der Hauptseite gesehen und gehofft hat, dass sie in Sechsecken geschrieben wurde?)
Addison Crump
9
@FlagAsSpam Die Anforderungen dieser Community steigen erheblich, wenn es möglich ist, 8 Personen zu enttäuschen (und zu zählen), indem eine Herausforderung mit vorzeichenbehafteten Ganzzahlen und hexagonalen Gittern mit einer Sprache gelöst wird, die ihre Eingabe nur über reguläre Ausdrücke verarbeiten kann. ;)
Martin Ender
1

Python (3.5) 193 185 182 Bytes

Ich berechne auch in axialen Koordinaten und rechne am Ende um.

Ich füge einige Optimierungen gemäß der @ Martin Büttner-Lösung hinzu: Ich ersetze R durch r * 5, es ändert nichts an der Anzahl der Bytes. Aber mit dieser Änderung können wir den zweiten Test elif j=='r'durch nur ersetzenelse

Die Lösung geht davon aus, dass die Eingabe keine ungültigen Zeichen enthält.

def f(i):
 x=y=0;u=-1,0,-1,1,0,1,1,0,1,-1,0,-1;v='dewqas'
 for j in i.replace('R','r'*5):
  w=v.find(j)*2
  if-1<w:x+=u[w];y+=u[w+1]
  else:u=u[2:]+u[:2]
 print(-x,-x-y+(x-(x%2))/2)

Ungolfed

def f(i):
  x=y=0
  u=-1,0,-1,1,0,1,1,0,1,-1,0,-1    # operations list xd,yd,xe,ye...
  v='dewqas'                       # letters list in clockwise order 
  i.replace('R','r'*5)             # replace 'R' by 5*'r'
  for j in i:
    w=v.find(j)*2                  # extract letter index
    if-1<w:
      x+=u[w]                      # apply operations
      y+=u[w+1]
    else:
      u=u[2:]+u[:2]                # rotate clockwise the operation string
  print(-x,-x-y+(x-(x%2))/2)       # convert coordinates axial to "odd-q"

Verwendung

>>> f('wrwrwrwrw')
-1 0.0
>>> f('dddddddddd')
10 5.0
>>> f('edeqaaaswwdqqs')
-2 0.0
Erwan
quelle
0

Batch, 708 636 586 569 Bytes

Ich habe doppelte y-Koordinaten verwendet, weil es die Mathematik einfacher gemacht hat. Ich bin mir nicht sicher, ob ich die Rotation optimal berücksichtigt habe, aber es ist besser als die Anzahl der rs zu zählen.

Bearbeiten: 72 Bytes gespart, indem die Behandlung von Rs verbessert wurde . 60 Bytes gespart durch Optimierung meiner set/aAussagen. 17 Bytes mit einigen kleinen Optimierungen gespeichert.

@echo off
set m=%1
set/ay=x=0
set r=r
set g=goto l
:l
set/a"z=y>>1
if "%m%"=="" echo %x% %z%&exit/b
set c=%m:~0,1%
set m=%m:~1%
goto %r:rrrrrr=%%c%
:a
:rq
:rrw
:rrre
:rrrrd
:rrrrrs
set/ax-=2
:w
:re
:rrd
:rrrs
:rrrra
:rrrrrq
set/ax+=1,y-=1
%g%
:q
:rw
:rre
:rrrd
:rrrrs
:rrrrra
set/ay-=2
%g%
:s
:ra
:rrq
:rrrw
:rrrre
:rrrrrd
set/ax-=2
:e
:rd
:rrs
:rrra
:rrrrq
:rrrrrw
set/ax+=+1,y+=1
%g%
:d
:rs
:rra
:rrrq
:rrrrw
:rrrrre
set/ay+=2
%g%
:r
:rr
:rrr
:rrrr
:rrrrr
:rrrrrr
if %c%==R set c=rrrrr
set r=%c%%r%
%g%
Neil
quelle
0

05AB1E , 60 Bytes

.•F?äM•U2Å0IvXy'rQiÀUëy'RQiÁUëykÐ5α‚ßsD3%_s3›·+‚<+]Ć`DÉ-2÷+‚

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

Allgemeine Erklärung:

Wir beginnen mit einer Zeichenfolge "qwedsa"und einer Koordinate [0,0]und durchlaufen die Zeichen der Eingabe.
Wenn es ein "r" oder "R" ist, drehen wir diese Saite nach links oder rechts.
Wenn nicht, erhalten wir den 0-basierten Index in dieser Zeichenfolge und ordnen ihn wie folgt zu:

q → 0 → [-1,  0]
w → 1 → [ 0, -1]
e → 2 → [ 1, -1]
d → 3 → [ 1,  0]
s → 4 → [ 0,  1]
a → 5 → [-1,  1]

xy

 x   indices     y   indices
-1 ← 0;5        -1 ← 1;2
 0 ← 1;4         0 ← 0;3
 1 ← 2;3         1 ← 4;5

k

x=michn(k,einbs(k-5))-1
y=(0k(mod3))+2(k>3)-1

yxx

y=y+x-x(mod2)2

Code Erklärung:

.•FM         # Push compressed string "qwedsa"
       U        # Pop and store it in variable `X`
2Å0             # Push list [0,0]
                # (many 3-byte alternatives for this: `00S`; `т¦S`; `0D‚`; `1¾‰`; etc.)
   Iv           # Loop over each character `y` of the input:
     X          #  Push string `X`
      y'rQi    '#  If `y` equals "r":
           À    #   Rotate string `X` once towards the left
            U   #   And pop and store it as new value for `X`
      ëy'RQi   '#  Else-if `y` equals "R":
            ÁU  #   Do the same, but rotate right instead
      ë         #  Else:
       yk       #   Get the 0-based index of `y` in the string `X`
         Ð      #   Triplicate this index
          5α    #   Take the absolute difference with 5
            ‚ß  #   Pair it with the original index, and pop and push the minimum
                #   (maps 0→[0,5]→0; 1→[1,4]→1; 2→[2,3]→2;
                #         3→[3,2]→2; 4→[4,1]→1; 5→[5,0]→0)
         sD     #   Swap to get the original index again, and duplicate it
           3%   #   Take modulo 3
             _  #   And check if it's equals to 0 (1 if truthy; 0 if falsey)
          s3   #   Swap to take the index again, and check if it's larger than 
                #   (again, 1 if truthy; 0 if falsey)
             ·  #   Double this
          +     #   And add both checks together
                #   (maps 0→1+0→1; 1→0+0→0; 2→0+0→0;
                #         3→1+0→1; 4→0+2→2; 5→0+2→2)
               #   Pair both mapped values together
          <     #   Decrease both by 1, so it becomes: 0→-1; 1→0; 2→1
           +    #   And add it to the current coordinates
    ]           # After the loop with inner if-else statements:
     Ć          # Enclose the coordinate, appending its own head: [x,y] becomes [x,y,x]
      `         # Push all three values separated to the stack
       D        # Duplicate this x
        É       # Check if its odd (1 if truthy; 0 if falsey)
         -      # Subtract it from the duplicated x
          2÷    # Integer-divide it by 2
            +   # Add it to y
               # And pair it with the original x again
                # (after which the result is output implicitly)

Sehen Sie diese 05AB1E Spitze Mine (Abschnitt Wie Kompresse Strings nicht Teil des Wörterbuchs? ) Zu verstehen , warum .•F?äM•ist "qwedsa".

Kevin Cruijssen
quelle
-1

Python 3, 227 Bytes

def G(s):
 q='qwedsa'
 d=[-1,0,1,1,0,-1,-1,-2,-1,1,2,1]
 X=Y=0
 for c in s:
  if c in q:
   n = q.find(c)
   X += d[n]
   Y += d[n+6]
  if c == 'r':
   q = q[1:]+q[0]
  if c == 'R':
   q = q[5]+q[0:5]
 print(X, int((Y-X%2)/2))
Austin Hastings
quelle
Ich verwende Python 3.5.0b3unter MacOS, und obwohl ich in 5 und 6 aufgrund von Rundungen einen Fehler erhalten habe, war der Rest korrekt. (Da über Bearbeiten behoben). Welche Version von Python verwenden Sie?
Austin Hastings
1
@AustinHastings Ich bin auf Python 3 unter Debian instabil.
Türklinke