Moto su una griglia esagonale


15

Dato un input di una serie di caratteri che rappresentano i movimenti su una griglia esagonale, emette le coordinate finali del "puntatore".

I nostri esagoni saranno numerati in questo modo (immagina una griglia rettangolare con ogni colonna dispari spostata leggermente verso il basso):

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

Il puntatore inizia su (0, 0).

Le istruzioni che devi supportare sono le seguenti:

  • q: sposta in alto a sinistra
  • w: andare avanti
  • e: sposta in alto a destra
  • a: sposta in basso a sinistra
  • s: abbassati
  • d: sposta in basso a destra
  • r: ruota la griglia in senso orario
  • R: ruota la griglia in senso antiorario

I comandi di rotazione ruotano l'intera griglia mantenendo il puntatore alle stesse coordinate. (Perché qweasd? Si abbinano perfettamente con le indicazioni su una tastiera QWERTY.)

Per aiutare a visualizzarlo, ecco cosa farebbero i comandi di movimento, supponendo che il puntatore inizi nel mezzo:

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

Dopo una rotazione in senso orario ( r), i comandi vengono rimappati su (immaginatelo come rotazione dell'intera griglia esadecimale ma mantenendo comunque "w" su, ecc., Che equivale al seguente):

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

Analogamente, in senso antiorario (girevole R) dopo che restituirebbe la griglia alla normalità, e ruotando in senso antiorario nuovamente avrebbe "rimappatura" qwedsaa aqweds.

L'input deve essere dato come una singola stringa e l'output può essere una singola stringa unita da qualsiasi carattere non numerico (es. 1 2O 3,4) o da una matrice di numeri interi.

Poiché si tratta di , vincerà il codice più breve in byte.

Casi test:

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

Risposte:


2

Pyth, 81 byte

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

L'output è un elenco di numeri interi che rappresentano le coordinate.

La mia soluzione è davvero noiosa; cerca solo il carattere immesso in un array (il qwedsa), quindi accede a due array che rappresentano i rispettivi cambiamenti nelle coordinate. Ad esempio, se l'input è w, allora otteniamo 1 (in quanto è il secondo carattere dell'array). Quindi aggiungiamo A[1]a x(dove si Atrova l'array per le modifiche xrispetto ai diversi input) e B[1]a y(dove si Btrovano le modifiche y). re Rsi ottengono semplicemente ruotando l' qwedsaarray.

Sono sicuro che qualcuno può fare molto meglio usando Pyth. Continuerò a provare a golf la mia risposta però!

Puoi provarlo qui .


12

Retina , 353 339 178 175 150 130 129 117 byte

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

L'output è in unario, separato da due punti. Ciò significa che non vedrai davvero zero nell'output (anche se la presenza di due punti ti dirà quale delle due coordinate è zero, se ce n'è solo una).

Provalo online!

Questo è stato davvero divertente e alla fine è stato sorprendentemente breve. :)

Spiegazione

Prima alcuni retroscena. Esistono diversi sistemi di coordinate per descrivere le griglie esagonali. Quello richiesto usa le coordinate offset. È essenzialmente come le coordinate della griglia rettangolare, tranne per il fatto che un asse "oscilla" un po '. In particolare, la domanda richiede il layout "dispari-q" mostrato nella pagina collegata. Questo sistema di coordinate è un po 'noioso con cui lavorare, perché il modo in cui le coordinate cambiano durante uno spostamento dipende non solo dalla direzione dello spostamento ma anche dalla posizione corrente.

Un altro sistema di coordinate utilizza coordinate assiali. Questo essenzialmente immagina l'esgriglia come una fetta diagonale attraverso un volume di cubi e usa due degli assi (es. Xe z) per trovare una posizione sul piano 2D. Sulla griglia esadecimale, ciò significa che i due assi formano un angolo di 60 (o 120) gradi. Questo sistema è un po 'meno intuitivo ma molto più facile da lavorare, poiché ogni direzione corrisponde a un vettore "delta" fisso. (Per una migliore spiegazione di come arrivare a questo sistema di coordinate, controlla il link e gli splendidi diagrammi e animazioni lì.)

Quindi, ecco cosa faremo: calcoliamo il movimento in coordinate assiali (prendendoci cura della rotazione come suggerito nella sfida, rimappando il significato dei comandi), e quando abbiamo finito convertiamo assiale in offset dispari-q coordinate.

Le sei mosse si mappano ai seguenti vettori delta in coordinate assiali (xz):

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

Aspetta, questa è Retina, dovremo lavorare con numeri unari. Come lavoriamo con numeri unari negativi? L'idea è di usare due cifre diverse. Uno rappresenta+1 e l'altro rappresenta -1. Ciò significa che indipendentemente dal fatto che vogliamo aggiungere o sottrarre 1dalla posizione corrente, possiamo sempre farlo aggiungendo una cifra. Quando abbiamo finito comprimiamo il risultato nella sua grandezza (della cifra corrispondente) cancellando le cifre bilanciate. Quindi calcoliamo il segno in base alla cifra rimanente e sostituiamo tutte le cifre con 1.

Il piano è costruire i componenti assiali x e z a sinistra e a destra di un :(come separatore), davanti all'ingresso. we ssi aggiungerà al lato destro. qe dverrà aggiunto sul lato sinistro ee averrà aggiunto su entrambi i lati. Da wes sono già sul lato corretto del :(che andrà in primo piano), useremo quelli come i numeri -1e +1, rispettivamente.

Analizziamo il codice.

R
5$*r

Iniziamo trasformando ciascuno Rin cinquer secondi. Naturalmente, una svolta a sinistra è la stessa di cinque svolte a destra su una griglia esadecimale, e così facendo possiamo fare molte duplicazioni sul passaggio di rimappatura.

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

Questa è una fase di traslitterazione che ruota i sei comandi, se vengono trovati dopo il primo r(elaborando così il primo r). we ddevono essere evitati per impedire che si espandano in classi di caratteri. Ilo inserisce il set sorgente nel set di destinazione che salva un mazzo di byte per queste operazioni di rotazione. La mappatura dei caratteri è quindi:

aqweds
saqweds

dove l'ultimo s nella seconda riga può essere semplicemente ignorato.

)`r(.*)
$1

Questo rimuove il primo rdalla stringa, perché è stato elaborato (vorrei aver già implementato i limiti di sostituzione ...). Il) dice anche Retina per eseguire tutte le fasi fino a questo in un ciclo fino a quando la stringa smette di cambiare. Nelle iterazioni successive, il primo stadio è no-op perché non ci sono più se Ril secondo stadio applica un'altra rotazione fintanto che ci sono rs nella stringa.

Al termine, abbiamo mappato tutti i comandi nella direzione in cui corrispondono sulla griglia non ruotata e possiamo iniziare a elaborarli. Naturalmente questo movimento è solo una somma di quei vettori delta e le somme sono commutative, quindi non importa in quale ordine le elaboriamo ora che le rotazioni sono state eliminate.

^
:

Inserire il delimitatore di coordinate nella parte anteriore.

Ora non abbiamo davvero bisogno di elaborare se w. Sono nostre +1e -1cifre e sono già dalla parte corretta del, :quindi lasceranno cadere come richiesto alla fine. Possiamo fare un'altra semplificazione: aè semplicemente s + qed eè w + d. Facciamolo:

a
sq
e
wd

Ancora una volta, quelli se wcadranno. Tutto quello che dobbiamo fare è spostare quei qs e ds per la parte anteriore e li trasformano in ws e ssi s. Lo facciamo con due loop separati:

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

Quindi è fatto. Tempo per la conversione da coordinate assiali a coordinate offset. Per questo dobbiamo comprimere le cifre. Tuttavia, per ora ci preoccupiamo solo del lato sinistro. A causa del modo in cui abbiamo elaborato le qs e le ds, sappiamo che tutte le ss nella parte sinistra appariranno davanti a tutte le ws, quindi dobbiamo solo controllare una coppia per farle crollare:

+`sw

Ora la conversione effettiva. Ecco lo pseudocodice, preso dal link sopra:

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

Destra, quindi il lato sinistro è già corretto. Tuttavia, il lato destro richiede il termine di correzione (x - (x&1)) / 2. Prendendo &1è lo stesso del modulo 2. Questo in sostanza analizza come x/2, divisione intera, arrotondata verso meno infinito. Quindi, per positivo x, aggiungiamo la metà del numero di cifre (arrotondato per difetto) e per negativo x, sottraggiamo la metà del numero di cifre (arrotondato per eccesso). Questo può essere espresso in modo sorprendentemente conciso in regex:

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

A causa dell'avidità, anche il xgruppo 1 corrisponderà esattamente alla metà delle cifre, \1l'altra metà e possiamo ignorare il w?. Inseriamo quella metà dopo il :(che è x/2). Se xè pari, allora dobbiamo distinguere il positivo e il negativo. Se xè positivo, w?non corrisponderà mai, quindi i due gruppi dovranno comunque corrispondere allo stesso numero di cifre. Non è un problema se il primo sviene semplicemente ignorato, quindi arrotondiamo per difetto. Se xè negativo e dispari, la corrispondenza possibile è con \1(metà xarrotondata per difetto) e quella facoltativa w. Dato che entrambi vanno in gruppo 2, scriveremo x/2con la grandezza arrotondata per eccesso (come richiesto).

+`sw|ws

Ora comprimiamo le cifre sul lato destro. Questa volta, non conosciamo l'ordine di se w, quindi dobbiamo tenere conto di entrambe le coppie.

w+
-$0

Entrambe le parti sono ora ridotte a una singola cifra ripetuta (o nulla). Se quella cifra è w, inseriamo un segno meno davanti.

\w
1

E infine trasformiamo sia in wche sin un'unica cifra unaria ragionevole. (Suppongo di poter salvare un byte usando wo scome cifra unaria, ma sembra un po 'allungato.)


10
(Sono l'unico che ha visto questa risposta apparire nella pagina principale del sito e spera vivamente che sia stata scritta in esagonia?)
Addison Crump

9
@FlagAsSpam Le richieste di questa comunità stanno aumentando seriamente quando è possibile deludere 8 persone (e contando) risolvendo una sfida che coinvolge numeri interi e griglie esagonali con un linguaggio che può solo elaborare il suo input tramite regex. ;)
Martin Ender il

1

Python (3.5) 193 185 182 byte

Calcolo anche in coordinate assiali e converto alla fine.

Aggiungo un po 'di ottimizzazione secondo la soluzione @Martin Büttner: sostituisco R con r * 5, non cambia il conteggio dei byte. Ma con questa modifica possiamo sostituire il secondo test elif j=='r'con soloelse

La soluzione presuppone che non possiamo avere caratteri non validi nell'input.

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"

uso

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

0

Lotto, 708 636 586 569 byte

Ho usato le coordinate y raddoppiate perché ha semplificato la matematica. Non sono sicuro di aver preso in considerazione la rotazione nel modo più ideale, ma batte contando il numero di rs.

Modifica: salvato 72 byte migliorando la gestione di Rs. Ho salvato 60 byte ottimizzando le mie set/adichiarazioni. Salvato 17 byte con alcune ottimizzazioni minori.

@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%

0

05AB1E , 60 byte

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

Provalo online o verifica tutti i casi di test .

Spiegazione:

Spiegazione generale:

Iniziamo con una stringa "qwedsa" e una coordinata [0,0]e passiamo in rassegna i caratteri dell'input.
Se è una "r" o "R" ruotiamo questa stringa rispettivamente verso sinistra o destra.
In caso contrario, otteniamo l'indice basato su 0 in questa stringa e lo mappiamo come segue:

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 coordinate:

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

K come segue:

X=mion(K,un'BS(K-5))-1
y=(0K(mod3))+2(K>3)-1

yXX rimane lo stesso):

y=y+X-X(mod2)2

Spiegazione del codice:

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

Vedere questo 05AB1E punta del mio (sezione Come stringhe di comprimere che non fanno parte del dizionario? ) Per capire il motivo per cui .•F?äM•è "qwedsa".


-1

Python 3, 227 byte

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

Sto usando Python 3.5.0b3su MacOS, e mentre ho ricevuto un errore in 5 e 6, a causa dell'arrotondamento, il resto era corretto. (Poiché riparato tramite Modifica). Quale versione di Python stai usando?
Austin Hastings,

1
@AustinHastings Sono su Python 3 su Debian instabile.
Maniglia della porta
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.