Gerak pada kisi heksagonal

15

Diberikan masukan dari serangkaian karakter yang mewakili gerakan pada kisi heksagonal, menghasilkan koordinat akhir dari "penunjuk."

Segi enam kami akan diberi nomor seperti itu (bayangkan sebuah kotak persegi panjang dengan setiap kolom bernomor ganjil sedikit bergeser ke bawah):

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

Pointer dimulai pada (0, 0).

Instruksi yang harus Anda dukung adalah sebagai berikut:

  • q: pindah ke kiri
  • w: bergerak ke atas
  • e: bergerak ke kanan
  • a: bergerak ke kiri bawah
  • s: Turunkan
  • d: bergerak ke kanan bawah
  • r: memutar kotak searah jarum jam
  • R: memutar kotak berlawanan arah jarum jam

Perintah rotasi memutar seluruh grid sambil menjaga pointer pada koordinat yang sama. (Kenapa qweasd? Mereka cocok dengan petunjuk di papan ketik QWERTY.)

Untuk membantu memvisualisasikan ini, inilah yang akan dilakukan perintah gerakan, dengan asumsi pointer dimulai di tengah:

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

Setelah rotasi searah jarum jam ( r), perintah dipetakan kembali ke (bayangkan sebagai memutar seluruh kisi heks tetapi tetap menjaga "w" sebagai naik, dll, yang setara dengan yang berikut):

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

Demikian pula, berputar berlawanan ( R) setelah itu akan kembali grid normal, dan berputar berlawanan lagi akan "remap" qwedsauntuk aqweds.

Input harus diberikan sebagai string tunggal, dan output dapat berupa string tunggal yang bergabung dengan karakter non-numerik (mis. 1 2Atau 3,4) atau array bilangan bulat.

Karena ini adalah , kode terpendek dalam byte akan menang.

Kasus uji:

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
Gagang pintu
sumber

Jawaban:

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

Output adalah daftar bilangan bulat yang mewakili koordinat.

Solusi saya sebenarnya sangat membosankan; itu hanya mencari karakter yang dimasukkan dalam array (yang qwedsa), dan kemudian mengakses dua array yang mewakili perubahan masing-masing dalam koordinat. Misalnya, jika inputnya adalah w, maka kita mendapatkan 1 (karena itu adalah karakter kedua dalam array). Kemudian kita tambahkan A[1]ke x(di mana Aarray untuk perubahan xsehubungan dengan input yang berbeda) dan B[1]ke y(di mana Bperubahan untuk y). rdan Rdicapai dengan hanya memutar qwedsaarray.

Saya yakin seseorang dapat melakukan jauh lebih baik menggunakan Pyth. Saya akan terus mencoba golf jawaban saya!

Anda bisa mencobanya di sini .

Berirama
sumber
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

Keluaran dalam unary, dipisahkan oleh titik dua. Itu berarti Anda tidak akan benar-benar melihat nol di output (walaupun keberadaan titik dua akan memberi tahu Anda yang mana dari dua koordinat tersebut nol, jika hanya ada satu).

Cobalah online!

Ini benar-benar menyenangkan dan akhirnya menjadi sangat singkat. :)

Penjelasan

Beberapa latar belakang terlebih dahulu. Ada beberapa sistem koordinat untuk menggambarkan kisi heksagonal. Yang meminta menggunakan koordinat offset. Itu pada dasarnya seperti koordinat kotak persegi panjang, kecuali bahwa satu sumbu "bergoyang" sedikit. Secara khusus, pertanyaannya menanyakan tata letak "odd-q" yang ditunjukkan pada halaman yang ditautkan. Sistem koordinat ini agak menjengkelkan untuk digunakan, karena bagaimana koordinat berubah selama gerakan tidak hanya bergantung pada arah gerakan tetapi juga pada posisi saat ini.

Sistem koordinat lain menggunakan koordinat aksial. Itu pada dasarnya membayangkan hexgrid sebagai irisan diagonal melalui volume kubus, dan menggunakan dua sumbu (misalnya x dan z) untuk menemukan posisi pada bidang 2D. Pada kisi hex, itu berarti bahwa kedua sumbu membentuk sudut 60 (atau 120) derajat. Sistem ini sedikit kurang intuitif tetapi jauh lebih mudah untuk dikerjakan, karena setiap arah sesuai dengan vektor "delta" yang diperbaiki. (Untuk penjelasan yang lebih baik tentang cara tiba di sistem koordinat ini, lihat tautan dan diagram serta animasi yang indah di sana.)

Jadi inilah yang akan kita lakukan: kita menghitung pergerakan dalam koordinat aksial (menjaga rotasi seperti yang disarankan dalam tantangan, dengan memetakan kembali makna perintah), dan ketika kita selesai kita mengonversi aksial ke aneh-q offset koordinat.

Enam bergerak peta ke vektor delta berikut di (xz) koordinat aksial:

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

Tunggu, ini Retina, kita harus bekerja dengan angka-angka unary. Bagaimana cara kita bekerja dengan angka unary negatif? Idenya adalah menggunakan dua digit berbeda. Satu mewakili +1dan yang lainnya mewakili -1. Itu berarti terlepas dari apakah kita ingin menambah atau mengurangi 1posisi sekarang, kita selalu dapat melakukannya dengan menambahkan angka. Setelah selesai, kami menciutkan hasilnya menjadi besarnya (dari angka yang sesuai) dengan membatalkan angka seimbang. Kemudian kami mencari tanda berdasarkan digit yang tersisa, dan mengganti semua digit 1.

Rencananya adalah untuk membangun komponen aksial x dan z ke kiri dan kanan a :(sebagai pemisah), di depan input. wdan sakan ditambahkan ke sisi kanan. qdan dakan menambah ke sisi kiri, dan edan aakan menambah ke kedua sisi. Karena wdan ssudah berada di sisi yang benar dari :(yang akan berada di depan), kita akan menggunakannya sebagai masing-masing -1dan +1digit.

Mari kita lihat kodenya.

R
5$*r

Kita mulai dengan mengubah masing R- masing menjadi lima r. Tentu saja, satu belokan kiri sama dengan lima belokan kanan pada hex grid, dan dengan melakukan itu kita dapat banyak duplikasi pada langkah pemetaan ulang.

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

Ini adalah tahap transliterasi yang memutar enam perintah, jika ditemukan setelah yang pertama r(dengan demikian memproses yang pertama r). wdan dperlu melarikan diri untuk mencegah mereka berkembang ke kelas karakter. The omenyisipkan sumber set ke target yang ditetapkan yang menyimpan banyak byte untuk tugas-tugas rotasi ini. Karenanya pemetaan karakter:

aqweds
saqweds

di mana yang terakhir sdi baris kedua bisa diabaikan begitu saja.

)`r(.*)
$1

Ini menghapus yang pertama rdari string, karena sudah diproses (saya berharap saya sudah menerapkan batas substitusi ...). The )juga memberitahu Retina untuk menjalankan semua tahapan hingga satu ini dalam satu lingkaran sampai string berhenti berubah. Pada iterasi berikutnya, tahap pertama adalah no-op karena tidak ada lagi Rs dan tahap kedua akan menerapkan rotasi lain selama ada yang rtersisa di string.

Setelah selesai, kami telah memetakan semua perintah ke arah yang sesuai pada kisi yang tidak diputar dan dapat mulai memprosesnya. Tentu saja pergerakan ini hanyalah jumlah dari vektor-vektor delta itu, dan penjumlahannya bersifat komutatif, jadi tidak masalah dalam urutan mana kita memprosesnya sekarang karena rotasi telah dihilangkan.

^
:

Masukkan pembatas koordinat di depan.

Sekarang kita tidak benar-benar perlu memproses sdan w. Mereka adalah milik kita +1dan -1angka dan mereka sudah berada di sisi yang benar :sehingga mereka hanya akan keluar seperti yang dibutuhkan pada akhirnya. Kita dapat membuat penyederhanaan lain: asederhana s + qdan esedang w + d. Ayo lakukan itu:

a
sq
e
wd

Sekali lagi, itu sdan whanya akan putus. Yang perlu kita lakukan adalah memindahkan qitu dan dke depan dan mengubahnya menjadi wdan situ sendiri. Kami melakukannya dengan dua loop terpisah:

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

Jadi sudah selesai. Saatnya konversi dari koordinat aksial ke offset. Untuk itu kita perlu menciutkan digit. Namun, untuk saat ini kami hanya peduli dengan sisi kiri. Karena cara kami memproses huruf qs dan ds, kami tahu bahwa semua shuruf s di sisi kiri akan muncul di depan huruf ws, jadi kami hanya perlu memeriksa satu pasangan untuk menciutkannya:

+`sw

Sekarang konversi yang sebenarnya. Ini adalah kodesemu, diambil dari tautan di atas:

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

Benar, jadi sisi kiri sudah benar. Sisi kanan membutuhkan jangka waktu koreksi (x - (x&1)) / 2. Pengambilan &1sama dengan modulo 2. Ini pada dasarnya diurai sebagai x/2, pembagian bilangan bulat, dibulatkan ke arah minus tanpa batas. Jadi untuk positif x, kita tambahkan setengah jumlah digit (dibulatkan ke bawah), dan untuk negatif x, kita kurangi setengah jumlah digit (dibulatkan ke atas). Hal ini dapat diekspresikan secara mengejutkan dalam regex:

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

Karena keserakahan, untuk genap x, grup 1 akan cocok persis setengah digit, \1separuh lainnya dan kita bisa mengabaikannya w?. Kami memasukkan setengah setelah :(yang x/2). Jika xgenap, maka kita perlu membedakan positif dan negatif. Jika xpositif, maka w?tidak akan pernah cocok, sehingga kedua kelompok masih harus mencocokkan jumlah digit yang sama. Itu tidak masalah jika yang pertama shanya dilewati, jadi kami membulatkannya. Jika xnegatif dan ganjil, maka kemungkinan kecocokannya adalah dengan \1(setengah xdibulatkan ke bawah) dan opsional itu w. Karena keduanya masuk dalam grup 2, kita akan menulis x/2dengan magnitudo yang dibulatkan (sesuai kebutuhan).

+`sw|ws

Sekarang kita meruntuhkan angka di sisi kanan. Kali ini, kami tidak tahu urutan sdan w, jadi kami harus memperhitungkan kedua pasangan.

w+
-$0

Kedua bagian sekarang dikurangi menjadi satu digit berulang (atau tidak sama sekali). Jika digit itu adalah w, kami menyisipkan tanda minus di depan.

\w
1

Dan akhirnya kita mengubah keduanya menjadi wdan smenjadi satu digit unary yang masuk akal. (Saya kira saya bisa menyimpan byte dengan menggunakan watau ssebagai digit unary, tapi sepertinya sedikit peregangan.)

Martin Ender
sumber
10
(Apakah saya satu-satunya yang melihat jawaban ini muncul di halaman situs utama dan sangat berharap itu ditulis dalam hexagony?)
Addison Crump
9
@FlagAsSpam Tuntutan komunitas ini secara serius meningkat ketika memungkinkan untuk mengecewakan 8 orang (dan terus bertambah) dengan memecahkan tantangan yang melibatkan bilangan bulat yang ditandatangani dan kisi heksagonal dengan bahasa yang hanya dapat memproses inputnya melalui regex. ;)
Martin Ender
1

Python (3.5) 193 185 182 byte

Saya juga menghitung dalam koordinat aksial dan mengkonversi di akhir.

Saya menambahkan beberapa optimasi sesuai dengan solusi @ Martin Büttner: Saya mengganti R dengan r * 5, itu tidak mengubah jumlah byte. Tetapi dengan perubahan ini kita bisa mengganti tes kedua elif j=='r'dengan adilelse

Solusinya berasumsi kita tidak dapat memiliki karakter yang tidak valid dalam 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)

Tidak disatukan

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"

Pemakaian

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

Batch, 708 636 586 569 byte

Saya menggunakan koordinat y berlipat ganda karena itu membuat matematika lebih sederhana. Saya tidak yakin saya memperhitungkan rotasi dengan cara yang paling ideal, tetapi ini menghitung jumlah rs.

Sunting: Disimpan 72 byte dengan meningkatkan penanganan Rs. Disimpan 60 byte dengan mengoptimalkan set/apernyataan saya . Disimpan 17 byte dengan beberapa optimasi kecil.

@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
sumber
0

05AB1E , 60 byte

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

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

Penjelasan umum:

Kita mulai dengan string "qwedsa"dan koordinat [0,0], dan mengulang karakter input.
Jika ini adalah "r" atau "R", kami memutar string ini ke kiri atau kanan.
Jika tidak, kami mendapatkan indeks berbasis 0 di string ini, dan memetakannya sebagai berikut:

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

Kami perlu mengonversi angka indeks menjadi yang berikut x dan y koordinat:

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

Kami melakukan ini, dengan mengonversi indeks k sebagai berikut:

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

Dan setelah seluruh loop, kita harus memperbaiki off-set dari y-berkoordinasi berdasarkan x-Koordinasi, yang kita lakukan seperti ini (x tetap sama):

y=y+x-x(mod2)2

Penjelasan kode:

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

Lihat ini 05AB1E ujung tambang (bagian Cara string kompres bukan bagian dari kamus? ) Untuk memahami mengapa .•F?äM•adalah "qwedsa".

Kevin Cruijssen
sumber
-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))
Austin Hastings
sumber
Saya menggunakan Python 3.5.0b3MacOS, dan sementara saya mendapatkan kesalahan di 5 dan 6, karena pembulatan, sisanya benar. (Sejak diperbaiki melalui Edit). Versi Python apa yang Anda gunakan?
Austin Hastings
1
@AustinHastings Saya menggunakan Python 3 di Debian tidak stabil.
Gagang Pintu