Altıgen ızgarada hareket


15

Altıgen bir ızgaradaki hareketleri temsil eden bir dizi karakterden oluşan bir girdi verildiğinde, "işaretçi" nin son koordinatlarını çıktılayın.

Altıgenlerimiz bu şekilde numaralandırılacaktır (her tek numaralı sütunun biraz aşağı doğru kaydırıldığı dikdörtgen bir ızgara düşünün):

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

İşaretçi (0, 0) konumunda başlar.

Desteklemeniz gereken talimatlar aşağıdaki gibidir:

  • q: yukarı-sola hareket et
  • w: yukarı git
  • e: sağa hareket et
  • a: aşağı-sola hareket et
  • s: aşağı inmek
  • d: aşağı sağa hareket et
  • r: ızgarayı saat yönünde döndür
  • R: ızgarayı saat yönünün tersine döndür

Döndürme komutları, işaretçiyi aynı koordinatlarda tutarken tüm ızgarayı döndürür. (Neden qweasd? Bir QWERTY klavyedeki talimatlarla uyumludurlar.)

Bunu görselleştirmeye yardımcı olmak için, işaretçinin ortada başladığını varsayarak, hareket komutlarının yapacağı şey:

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

Saat yönünde döndürüldükten sonra ( r) komutlar yeniden eşleştirilir (tüm altıgen ızgarayı döndürdüğünü, ancak yine de aşağıdakine eşdeğer olan "w" yi yukarıda tuttuğunu hayal edin):

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

Benzer şekilde, saat yönünün tersine (döner Rsonra) normale ızgara dönmek ve "Remap" would saat yönünün yine döner qwedsaiçin aqweds.

Giriş tek bir dize olarak verilmelidir ve çıktı sayısal olmayan karakterler (ör. 1 2Veya 3,4) ile birleştirilen tek bir dize veya bir tamsayı dizisi olabilir.

Bu , bayt cinsinden en kısa kod kazanacaktır.

Test senaryoları:

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

Yanıtlar:


2

Pyth, 81 bayt

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

Çıktı, koordinatları temsil eden tamsayıların bir listesidir.

Benim çözümüm aslında gerçekten sıkıcı; bir dizide (the qwedsa) girilen karakteri arar ve ardından koordinatlarda ilgili değişiklikleri temsil eden iki diziye erişir. Örneğin, giriş ise w, 1 alırız (dizideki ikinci karakter olduğu için). Daha sonra eklemek A[1]için x(burada Adeğişikliklerin dizi xfarklı girişlere ilgili olarak) B[1]için y( Bdeğişiklikleri olan y). rve Rsadeceqwedsa dizi .

Eminim birileri Pyth kullanarak daha iyisini yapabilir. Cevabımı golf oynamaya devam edeceğim!

Burada deneyebilirsiniz .


12

Retina , 353 339 178 175 150 130 129 117 bayt

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

Çıktı tekli, iki nokta üst üste ile ayrılır. Bu, çıktıda gerçekten sıfır görmeyeceğiniz anlamına gelir (bir kolonun varlığı size, yalnızca bir tane varsa iki koordinattan hangisinin sıfır olduğunu söyleyecektir).

Çevrimiçi deneyin!

Bu gerçekten eğlenceliydi ve şaşırtıcı derecede kısa oldu. :)

açıklama

Önce biraz arka plan. Altıgen ızgaraları tanımlamak için çeşitli koordinat sistemleri vardır. İstenen ofset koordinatlarını kullanır. Bu, esasen dikdörtgen ızgara koordinatlarına benzer, ancak bir eksen biraz "sallanıyor". Özellikle, soru bağlantılı sayfada gösterilen "tek-q" düzenini sorar. Bu koordinat sistemi, çalışmak için biraz can sıkıcıdır, çünkü bir hareket sırasında koordinatların nasıl değiştiği sadece hareketin yönüne değil, aynı zamanda geçerli konuma da bağlıdır.

Başka bir koordinat sistemi eksenel koordinatları kullanır. Bu aslında altıgen çizgiyi bir küp hacminde diyagonal bir dilim olarak hayal etmek ve 2B düzlemde bir konum bulmak için eksenlerden ikisini (örn. X ve z) kullanmaktır. Altıgen ızgarada, bu iki eksenin 60 (veya 120) derecelik bir açı oluşturduğu anlamına gelir. Her yöne sabit bir "delta" vektörüne karşılık geldiğinden, bu sistem biraz daha az sezgiseldir ancak çalışması çok daha kolaydır. (Bu koordinat sistemine nasıl ulaşılacağına dair daha iyi bir açıklama için bağlantıya ve oradaki güzel şemalara ve animasyonlara göz atın.)

İşte yapacağımız şey: hareketi eksenel koordinatlarda hesaplıyoruz (meydan okumada önerildiği gibi rotasyona dikkat ederek, komutların anlamını yeniden eşleştirerek) ve işimiz bittiğinde eksenel olanı tek-q ofsetine dönüştürüyoruz koordinatlar.

Altı hareket haritayı (xz) eksenel koordinatlarında aşağıdaki delta vektörlerine taşır:

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

Bekle, bu Retina, tekli numaralarla çalışmak zorundayız. Negatif tekli sayılarla nasıl çalışırız? Fikir iki farklı basamak kullanmaktır. Biri temsil eder +1, diğeri temsil eder -1. Bu 1, geçerli konuma toplama veya çıkarma yapmak isteyip istemediğimize bakılmaksızın , bunu her zaman bir rakam ekleyerek yapabiliriz. İşimiz bittiğinde, dengeli rakamları iptal ederek sonucu (ilgili basamağın) büyüklüğüne daraltırız. Sonra kalan rakamı temel alarak işareti buluruz ve tüm rakamları değiştiririz 1.

Plan, :girişin önünde a'nın (ayırıcı olarak) solunda ve sağında eksenel x ve z bileşenlerini oluşturmaktır . wve ssağ tarafa eklenir. qve dsol tarafına katacak ve eve aher iki tarafa da ekleyecektir. Yana wve sdoğru tarafında zaten :(önünde gidecek), biz bu kullanacağız -1ve +1sırasıyla basamak.

Koddan geçelim.

R
5$*r

Her Rbirini beş rsaniyeye çevirerek başlıyoruz . Tabii ki, bir sola dönüş onaltılık bir ızgarada beş sağa dönüşle aynıdır ve bunu yaparak yeniden eşleme adımında çok fazla çoğaltma yapabiliriz.

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

Bu, birinciden sonra bulunurlarsa r(böylece ilkini işliyorsa) altı komutu döndüren bir harf çevirisi aşamasıdır r. wve dkarakter sınıflarına genişlemelerini önlemek için kaçmaları gerekir. oBu dönme görevler için bayt bir demet kaydeder hedef dizi içine kaynak seti ekler. Karakter eşleme bu nedenle:

aqweds
saqweds

burada sikinci satırdaki sonuncusu yok sayılabilir.

)`r(.*)
$1

Bu rişlenmiş dize ilk çıkarır , çünkü işlenmiş (Keşke zaten ikame sınırları uygulamıştı ...). )Ayrıca dize değişen durana kadar bir döngü içinde bu bir bütün aşamalarını kadar çalıştırmak için Retina söyler. Müteakip iterasyonlarda, birinci aşama bir op-op değildir, çünkü daha fazla Rs yoktur ve ikinci aşama r, dizede s kaldığı sürece başka bir dönüş uygular .

İşimiz bittiğinde, tüm komutları döndürülmemiş ızgarada karşılık gelen yöne eşledik ve bunları işlemeye başlayabiliriz. Tabii ki bu hareket sadece bu delta vektörlerinin bir toplamı ve toplamlar değişmeli, bu yüzden rotasyonların ortadan kaldırıldığı şimdi bunları hangi sırada işlediğimiz önemli değil.

^
:

Koordinat sınırlayıcıyı öne yerleştirin.

Şimdi gerçekten işlememize gerek yok sve w. Onlar bizim +1ve -1rakamlarımız ve zaten doğru taraftalar, :böylece sonunda gerektiği gibi bırakacaklar. Başka bir basitleştirme yapabiliriz: abasittir s + qve eöyle w + d. Hadi bunu yapalım:

a
sq
e
wd

Yine, bunlar sve wsadece bırakacaklar. Yapmamız gereken tek şey bu hareket olduğunu qs ve dön s ve bunları açmak ws ve skendilerini bu. Bunu iki ayrı döngü ile yapıyoruz:

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

Yani bitti. Eksenelden ofset koordinatlarına dönüşüm zamanı. Bunun için rakamları daraltmamız gerekiyor. Ancak şimdilik sadece sol tarafı önemsiyoruz. qS ve ds'yi işleme şeklimiz nedeniyle s, sol taraftaki tüm s'lerin herhangi bir ws'nin önünde görüneceğini biliyoruz, bu yüzden onları çökertmek için sadece bir çifti kontrol etmeliyiz:

+`sw

Şimdi gerçek dönüşüm. Yukarıdaki bağlantıdan alınan sözde kod:

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

Sağ, böylece sol taraf zaten doğru. Sağ taraf da düzeltme terimine ihtiyaç duyar (x - (x&1)) / 2. Alma &1, modulo 2 ile aynıdır. Bu, temel olarak x/2, eksi sonsuza yuvarlanmış tamsayı bölünmesi olarak ayrıştırılır . Bu yüzden pozitif için xrakam sayısının yarısını (aşağı yuvarlanır) ekler ve negatif için rakam sayısının yarısını (yuvarlanır) xçıkarırız. Bu normalde şaşırtıcı bir şekilde kısaca ifade edilebilir:

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

Açgözlülük nedeniyle, hatta x, grup 1 basamakların tam yarısı ile eşleşecek \1, diğer yarısı ve görmezden gelebiliriz w?. Bu yarıyı :(ki x/2) sonra ekliyoruz . Eşitse x, pozitif ve negatifleri ayırt etmeliyiz. Eğer xolumlu, daha sonra w?iki grup hala aynı sayıda basamak maç olacak, böylece maç asla. Birincisi satlanırsa sorun değil , bu yüzden aşağı yuvarlanıyoruz. Eğer xnegatif ve tek, daha sonra olası eşleşme ile \1(yarısından xyuvarlak aşağı) ve isteğe bağlı w. Her ikisi de gruba girdiğinden, büyüklük yuvarlanmış olarak 2yazacağız x/2(gerektiği gibi).

+`sw|ws

Şimdi sağ taraftaki rakamları daraltıyoruz. Bu kez sırasını bilmiyorum sve wbiz de çiftleri için hesaba gerek yüzden.

w+
-$0

Her iki parça da artık tekrarlanan tek bir basamağa (veya hiçbir şeye) indirgenmiştir. Bu rakam ise w, önüne bir eksi işareti ekleriz.

\w
1

Ve sonunda içine hem çevirmek wve stek makul tekli basamak içine. (Sanırım tek bayt kullanarak wveya stek rakam olarak bir bayt kaydedebilirim , ancak bu biraz gergin gibi görünüyor.)


10
(Am I pahalıya Bu cevap ana site sayfasında gelip gördüm ve tek o hexagony yazılmış ümit?)
Addison Crump

9
@FlagAsSpam Bu topluluğun talepleri, imzalı tam sayıları ve altıgen ızgaraları içeren bir sorunu yalnızca regexes aracılığıyla işleyebilecek bir dille çözerek 8 kişiyi hayal kırıklığına uğratmak (ve saymak) mümkün olduğunda ciddi şekilde artmaktadır. ;)
Martin Ender

1

Python (3.5) 193 185 182 bayt

Ben de eksenel koordinatlarda hesap ve sonunda dönüştürmek.

@Martin Büttner çözümüne göre bazı optimizasyonlar ekliyorum: R'yi r * 5 ile değiştiriyorum, bayt sayısını değiştirmiyor. Ancak bu değişiklikle ikinci testi elif j=='r'sadeceelse

Çözüm, girişte geçersiz karakterlere sahip olamayacağımızı varsayar.

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"

kullanım

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

0

Toplu, 708 636 586 569 bayt

İki katına y koordinatlarını kullandım çünkü matematiği basitleştirdi. Rotasyonu en ideal şekilde dikkate aldığımdan emin değilim, ancak rs sayısını saymayı atıyor .

Düzenleme: Rs kullanımı iyileştirilerek 72 bayt kaydedildi . set/aDeyimlerimi optimize ederek 60 bayt kaydedildi . Bazı küçük optimizasyonlarla 17 bayt kaydedildi.

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

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

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

Açıklama:

Genel açıklama:

Bir dize "qwedsa"ve bir koordinat ile başlıyoruz [0,0]ve girdinin karakterleri üzerinde döngü yapıyoruz .
"R" veya "R" ise, bu dizeyi sırasıyla sola veya sağa döndürürüz.
Değilse, bu dizede 0 tabanlı dizini alırız ve aşağıdaki gibi eşleştiririz:

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=mbenn(k,birbs(k-5))-1
y=(0k(şık3))+2(k>3)-1

Ve tüm döngüden sonra, y-ya dayalı koordinat x-koordinat, bunu beğendiğimiz (x aynı kalmak):

y=y+x-x(şık2)2

Kod açıklaması:

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

Bu 05AB1E madenin ucu bakın (bölüm kompres dizeleri sözlükte parçası olmayan nasıl? ) Anlamak için .•F?äM•olduğunu "qwedsa".


-1

Python 3, 227 bayt

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

Python 3.5.0b3MacOS'ta kullanıyorum ve 5 ve 6'da yuvarlama nedeniyle bir hata alırken, geri kalanı doğruydu. (Düzenleme ile düzeltildiğinden beri). Hangi Python sürümünü kullanıyorsunuz?
Austin Hastings

1
@AustinHastings Debian kararsız Python 3'deyim.
Kapı tokmağı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.