Ruch na siatce sześciokątnej

15

Biorąc pod uwagę serię znaków reprezentujących ruchy na sześciokątnej siatce, wyślij końcowe współrzędne „wskaźnika”.

Nasze sześciokąty będą ponumerowane w ten sposób (wyobraź sobie prostokątną siatkę z każdą kolumną o nieparzystym przesunięciu nieznacznie w dół):

  _____         _____         _____         _____
 /     \       /     \       /     \       /     \
/ -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  \
\       /     \       /     \       /     \       /
 \_____/       \_____/       \_____/       \_____/

Wskaźnik zaczyna się od (0, 0).

Instrukcje, które musisz wesprzeć, są następujące:

  • q: przesuń w górę-w lewo
  • w: przesuń w górę
  • e: przesuń w górę, w prawo
  • a: przesuń w dół w lewo
  • s: padnij
  • d: przesuń w dół w prawo
  • r: obróć siatkę zgodnie z ruchem wskazówek zegara
  • R: obróć siatkę przeciwnie do ruchu wskazówek zegara

Polecenia obrotu obracają całą siatkę, utrzymując wskaźnik na tych samych współrzędnych. (Dlaczego qweasd? Ładnie pasują do wskazówek na klawiaturze QWERTY.)

Aby to zobrazować, oto, co zrobiłyby polecenia ruchu, zakładając, że wskaźnik zaczyna się na środku:

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

Po obrocie zgodnie z ruchem wskazówek zegara ( r) polecenia są ponownie mapowane na (wyobraź sobie, że obraca całą siatkę heksadecymalną, ale nadal utrzymuje „w” na górze itd., Co jest równoważne z poniższym):

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

Podobnie, obrót w lewo ( R) po czym by powrócić do normalnego stanu sieci, i obraca się w kierunku przeciwnym znowu będzie „remap” qwedsaz aqweds.

Dane wejściowe muszą być podawane jako pojedynczy ciąg, a wyjściem może być pojedynczy ciąg połączony dowolnymi znakami nienumerycznymi (np. 1 2Lub 3,4) lub tablica liczb całkowitych.

Ponieważ jest to , wygra najkrótszy kod w bajtach.

Przypadki testowe:

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
Klamka
źródło

Odpowiedzi:

2

Pyth, 81 bajtów

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

Dane wyjściowe to lista liczb całkowitych reprezentujących współrzędne.

Moje rozwiązanie jest naprawdę nudne; po prostu wyszukuje wprowadzony znak w tablicy ( qwedsa), a następnie uzyskuje dostęp do dwóch tablic, które reprezentują odpowiednie zmiany we współrzędnych. Na przykład, jeśli dane wejściowe to w, to otrzymujemy 1 (ponieważ jest to drugi znak w tablicy). Następnie dodajemy A[1]do x(gdzie Ajest tablica zmian w xodniesieniu do różnych danych wejściowych) i B[1]do y(gdzie Bsą zmiany y). ri Rsą osiągane przez obrócenie qwedsatablicy.

Jestem pewien, że ktoś może zrobić znacznie lepiej, używając Pyth. Będę jednak nadal próbował odpowiedzieć na moją odpowiedź!

Możesz to wypróbować tutaj .

Rhyzomatic
źródło
12

Retina , 353 339 178 175 150 130 129 117 bajtów

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

Dane wyjściowe są jednostkowe, oddzielone dwukropkiem. Oznacza to, że tak naprawdę nie zobaczysz zer na wyjściu (chociaż obecność dwukropka powie ci, która z dwóch współrzędnych jest równa zero, jeśli jest tylko jedna).

Wypróbuj online!

To było naprawdę zabawne i skończyło się zaskakująco krótko. :)

Wyjaśnienie

Najpierw trochę tła. Istnieje kilka układów współrzędnych opisujących siatki heksagonalne. Ten, o który prosi się, używa współrzędnych przesunięcia. Zasadniczo przypomina to prostokątne współrzędne siatki, z tą różnicą, że jedna oś „trochę się chwieje”. W szczególności pytanie dotyczy układu „nieparzystego q” pokazanego na połączonej stronie. Ten układ współrzędnych jest nieco denerwujący w pracy, ponieważ sposób zmiany współrzędnych podczas ruchu zależy nie tylko od kierunku ruchu, ale także od bieżącej pozycji.

Inny układ współrzędnych wykorzystuje współrzędne osiowe. Zasadniczo wyobrażam sobie sześciokąt jako przekątny przekrój przez objętość sześcianów i użycie dwóch osi (np. Xiz), aby znaleźć pozycję na płaszczyźnie 2D. Na siatce sześciokątnej oznacza to, że dwie osie tworzą kąt 60 (lub 120) stopni. Ten system jest nieco mniej intuicyjny, ale o wiele łatwiejszy w obsłudze, ponieważ każdy kierunek odpowiada ustalonemu wektorowi „delta”. (Aby uzyskać lepsze wyjaśnienie, jak dojść do tego układu współrzędnych, sprawdź link oraz piękne diagramy i animacje).

Oto co zrobimy: obliczamy ruch we współrzędnych osiowych (dbając o obrót zgodnie z sugestią w wyzwaniu, zmieniając znaczenie poleceń), a kiedy skończymy, konwertujemy osiowe na przesunięcie nieparzyste współrzędne

Sześć ruchów odwzorowuje się na następujące wektory delta we współrzędnych osiowych (xz):

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

Czekaj, to jest Retina, będziemy musieli pracować z liczbami jednoargumentowymi. Jak pracujemy z ujemnymi liczbami jednoargumentowymi? Chodzi o to, aby użyć dwóch różnych cyfr. Jeden reprezentuje, +1a drugi reprezentuje -1. Oznacza to, że niezależnie od tego, czy chcemy dodać, czy odjąć 1od bieżącej pozycji, zawsze możemy to zrobić, dodając cyfrę. Po zakończeniu zwijamy wynik do jego wielkości (odpowiadającej mu cyfry), anulując cyfry zrównoważone. Następnie obliczamy znak na podstawie pozostałej cyfry i zastępujemy wszystkie cyfry znakiem 1.

Plan polega na zbudowaniu osiowych komponentów xiz po lewej i prawej stronie :(jako separatora), przed wejściem. wi sdoda po prawej stronie. qi dprzyczyni się do lewej strony, a ei adoda do obu stron. Ponieważ wi ssą już po właściwej stronie :(która będzie na wierzchu), użyjemy ich odpowiednio jako cyfr -1i +1.

Przejdźmy przez kod.

R
5$*r

Zaczynamy od przekształcenia każdego z nich Rw pięć rsekund. Oczywiście jeden skręt w lewo jest taki sam jak pięć skrętów w prawo na siatce heksów, a dzięki temu możemy dużo powielić na etapie odwzorowywania.

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

Jest to etap transliteracji, który obraca sześć poleceń, jeśli zostaną one znalezione po pierwszym r(przetwarzając w ten sposób pierwsze r). wi dtrzeba uciec, aby nie mogły się rozwinąć w klasy postaci. oWstawia zestaw źródłowy do zbioru docelowego co oszczędza kilka bajtów dla tych zadań obrotu. Mapowanie znaków jest zatem następujące:

aqweds
saqweds

gdzie ostatni sw drugim rzędzie można po prostu zignorować.

)`r(.*)
$1

To usuwa pierwszy r z ciągu, ponieważ został przetworzony (szkoda, że ​​nie wprowadziłem już limitów podstawień ...). )Mówi również Retina uruchomić wszystkie etapy aż do tego w pętli aż łańcuch przestaje się zmieniać. W kolejnych iteracjach pierwszy etap jest bezoperacyjny, ponieważ nie ma już Rs, a drugi etap zastosuje kolejny obrót, dopóki rpozostanie s w ciągu.

Kiedy skończyliśmy, zamapowaliśmy wszystkie polecenia w kierunku, w którym odpowiadają na nieobrotowej siatce i możemy je przetworzyć. Oczywiście ruch ten jest tylko sumą tych wektorów delta, a sumy są przemienne, więc tak naprawdę nie ma znaczenia, w jakiej kolejności je przetwarzamy teraz, gdy rotacje zostały wyeliminowane.

^
:

Wstaw ogranicznik współrzędnych z przodu.

Teraz tak naprawdę nie musimy przetwarzać si w. Oni są naszymi +1i -1cyfr, a oni już na właściwej stronie :, więc oni po prostu rezygnują wymagane w końcu. Możemy wprowadzić kolejne uproszczenie: ajest po prostu s + qi ejest w + d. Zróbmy to:

a
sq
e
wd

Ponownie, te si wpo prostu odpadną. Wszystko, co musimy zrobić, to przenieść te qs i ds do przodu i przekształcić je w ws i ss sami. Robimy to za pomocą dwóch oddzielnych pętli:

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

To już koniec. Czas konwersji ze współrzędnych osiowych na przesunięte. W tym celu musimy zwinąć cyfry. Jednak na razie dbamy tylko o lewą stronę. Ze względu na sposób, w jaki przetworzyliśmy qs i ds, wiemy, że wszystkie ss po lewej stronie pojawią się przed dowolnymi ws, więc musimy sprawdzić tylko jedną parę pod kątem ich zwinięcia:

+`sw

Teraz faktyczna konwersja. Oto pseudokod pobrany z powyższego linku:

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

Racja, więc lewa strona jest już poprawna. Prawa strona potrzebuje jednak terminu korekty (x - (x&1)) / 2. Przyjmowanie &1jest takie samo jak modulo 2. Zasadniczo analizuje się to jako x/2dzielenie liczb całkowitych, zaokrąglone w kierunku minus nieskończoności. Tak więc dla xliczby dodatniej dodajemy połowę liczby cyfr (zaokrągloną w dół), a dla wartości ujemnej xodejmujemy połowę liczby cyfr (zaokrągloną w górę). Można to wyrazić zaskakująco zwięźle w wyrażeniu regularnym:

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

Ze względu na chciwość, na przykład x, grupa 1 będzie pasować dokładnie do połowy cyfr, \1druga połowa i możemy zignorować w?. Wstawiamy tę połowę po :(która jest x/2). Jeśli xjest parzyste, musimy rozróżnić pozytywne i negatywne. Jeśli xjest dodatni, to w?nigdy nie będzie pasował, więc obie grupy będą musiały dopasować tę samą liczbę cyfr. Nie ma problemu, jeśli pierwszy szostanie po prostu pominięty, więc zaokrąglamy w dół. Jeśli xjest ujemne i nieparzyste, to możliwe dopasowanie jest z \1(połowa xzaokrąglona w dół) i to opcjonalne w. Ponieważ oba z nich wchodzą w grupę 2, piszemy x/2z wielkością zaokrągloną w górę (zgodnie z wymaganiami).

+`sw|ws

Teraz zwijamy cyfry po prawej stronie. Tym razem nie znamy kolejności si w, więc musimy uwzględnić obie pary.

w+
-$0

Obie części są teraz zredukowane do jednej powtarzającej się cyfry (lub nic). Jeśli ta cyfra jest w, wstawiamy znak minus z przodu.

\w
1

I w końcu zamieniamy zarówno w, jak wi sw jedną rozsądną, jednolitą cyfrę. (Przypuszczam, że mógłbym zapisać bajt za pomocą wlub sjako jednoznaczną cyfrę, ale wydaje się to trochę rozciągnięte.)

Martin Ender
źródło
10
(Czy jestem jedynym, który widział tę odpowiedź na stronie głównej i mam wielką nadzieję, że została napisana w formie sześciokąta?)
Addison Crump
9
@FlagAsSpam Wymagania tej społeczności poważnie rosną, gdy możliwe jest rozczarowanie 8 osób (i wciąż rośnie), rozwiązując wyzwanie obejmujące podpisane liczby całkowite i sześciokątne siatki za pomocą języka, który może przetwarzać dane wejściowe tylko przez wyrażenia regularne. ;)
Martin Ender
1

Python (3.5) 193 185 182 bajtów

Obliczam również we współrzędnych osiowych i przeliczam na końcu.

Dodaję optymalizację zgodnie z rozwiązaniem @Martin Büttner: zastępuję R przez r * 5, nie zmienia to liczby bajtów. Ale dzięki tej zmianie możemy zastąpić drugi test elif j=='r'tylkoelse

Rozwiązanie zakłada, że ​​nie możemy mieć nieprawidłowych znaków na wejściu.

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)

Nie golfił

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"

Stosowanie

>>> f('wrwrwrwrw')
-1 0.0
>>> f('dddddddddd')
10 5.0
>>> f('edeqaaaswwdqqs')
-2 0.0
Erwan
źródło
0

Partia, 708 636 586 569 bajtów

Użyłem podwójnych współrzędnych y, ponieważ ułatwiło to matematykę. Nie jestem pewien, czy wziąłem pod uwagę rotację w najbardziej idealny sposób, ale bije ona liczenie liczby rs.

Edycja: Zapisano 72 bajty, poprawiając obsługę Rs. Zaoszczędziłem 60 bajtów, optymalizując moje set/awyciągi. Zapisano 17 bajtów z pewnymi drobnymi optymalizacjami.

@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
źródło
0

05AB1E , 60 bajtów

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

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

Ogólne wyjaśnienie:

Zaczynamy od łańcucha "qwedsa"i współrzędnej [0,0]oraz zapętlamy znaki na wejściu.
Jeśli jest to „r” lub „R”, obracamy ten ciąg odpowiednio w lewo lub w prawo.
Jeśli nie, otrzymujemy w tym ciągu indeks oparty na 0 i zamapujemy go w następujący sposób:

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=mjan(k,zabs(k-5))-1
y=(0k(mod3)))+2)(k>3))-1

yxx

y=y+x-x(mod2))2)

Objaśnienie kodu:

.•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)

Zobacz moją wskazówkę 05AB1E (sekcja Jak kompresować ciągi znaków, które nie są częścią słownika? ), Aby zrozumieć, dlaczego tak .•F?äM•jest "qwedsa".

Kevin Cruijssen
źródło
-1

Python 3, 227 bajtów

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
źródło
Używam Python 3.5.0b3na MacOS i chociaż dostałem błąd w 5 i 6, z powodu zaokrąglenia, pozostałe były prawidłowe. (Ponieważ naprawiono przez edycję). Jakiej wersji Pythona używasz?
Austin Hastings
1
@AustinHastings Jestem na Pythonie 3 na Debianie niestabilny.
Klamka