Рух по шестикутній сітці


15

З огляду на введення серії символів, що представляють рухи по шестикутній сітці, виведіть кінцеві координати "вказівника".

Наші шестикутники будуть пронумеровані так (уявіть прямокутну сітку з кожним стовпчиком з непарними номерами, трохи зміщеним вниз):

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

Вказівник починається з (0, 0).

Інструкції, які ви повинні підтримувати, наступні:

  • q: рух вгору-вліво
  • w: рухатися вгору
  • e: рухатися вгору-вправо
  • a: рухатися вниз-вліво
  • s: рухатися вниз
  • d: рухатися вниз-вправо
  • r: обертати сітку за годинниковою стрілкою
  • R: обертати сітку проти годинникової стрілки

Команди обертання обертають всю сітку, зберігаючи покажчик на однакових координатах. (Чому qweasdвони добре узгоджуються з напрямками на клавіатурі QWERTY.)

Щоб візуалізувати це, ось що робитимуть команди руху, якщо припустити, що вказівник починається посередині:

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

Після обертання за годинниковою стрілкою ( r) команди перестановляються на (уявіть це як обертання всієї шістнадцяткової сітки, але все одно зберігаючи "w" як вгору тощо, що еквівалентно наступному):

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

Аналогічно, обертання проти годинникової стрілки ( R) після цього поверне сітку до норми, а обертання проти годинникової стрілки знову "переставить" qwedsaна aqweds.

Введення повинно бути подано як один рядок, а вихід може бути або як один рядок, з'єднаний будь-якими нечисловими символами (наприклад, 1 2чи 3,4), або масив цілих чисел.

Оскільки це , найкоротший код у байтах виграє.

Тестові приклади:

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

Відповіді:


2

Pyth, 81 байт

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

Вихід - це список цілих чисел, що представляють координати.

Моє рішення насправді насправді нудне; він просто шукає введений символ у масиві (the qwedsa), а потім отримує доступ до двох масивів, які представляють відповідні зміни координат. Наприклад, якщо вхід є w, то отримуємо 1 (оскільки це другий символ у масиві). Тоді ми додаємо A[1]до x(де Aмасив для змін у xвідношенні різних входів) та B[1]до y(де Bзміни для y). rі Rдосягаються просто обертанням qwedsaмасиву.

Я впевнений, що хтось може зробити набагато краще, використовуючи Pyth. Я продовжую намагатися, як відповісти на мою відповідь!

Ви можете спробувати тут .


12

Сітківка , 353 339 178 175 150 130 129 117 байт

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

Вихід є одинарним, розділеним двокрапкою. Це означає, що ви насправді не побачите нулі у виході (хоча наявність двокрапки скаже вам, яка з двох координат дорівнює нулю, якщо є лише одна).

Спробуйте в Інтернеті!

Це було дійсно весело та закінчилось напрочуд коротко. :)

Пояснення

Перший фон спочатку. Існує кілька систем координат для опису шестикутних сіток. Той, хто запитує, використовує координати зміщення. Це по суті як прямокутні координати сітки, за винятком того, що одна вісь трохи «коливається». Зокрема, питання задає макет "непарний-q", який відображається на пов'язаній сторінці. Ця система координат трохи прикро працювати, адже те, як змінюються координати під час руху, залежить не тільки від напрямку руху, але і від поточного положення.

Інша система координат використовує осьові координати. Це, по суті, уявляє собою гексрідж як діагональний зріз через об'єм кубів, використовуючи дві осі (наприклад, x і z), щоб знайти положення на площині 2D. На шестигранній сітці це означає, що дві осі утворюють кут 60 (або 120) градусів. Ця система трохи менш інтуїтивно зрозуміла, але набагато простіше працювати, оскільки кожен напрямок відповідає фіксованому вектору "дельта". (Для кращого пояснення того, як досягти цієї системи координат, перегляньте посилання та прекрасні діаграми та анімації там.)

Отже, ось що ми зробимо: обчислимо рух в осьових координатах (піклуючись про обертання, як пропонується в виклику, шляхом перестановки значення команд), і коли ми закінчимо, ми перетворимо осьовий на зміщення непарного q координати.

Шість переміщень відображаються до наступних дельта-векторів в (xz) осьових координатах:

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

Зачекайте, це Retina, нам доведеться працювати з одинарними номерами. Як ми працюємо з негативними одинарними числами? Ідея полягає у використанні двох різних цифр. Один представляє, +1а інший представляє -1. Це означає, що незалежно від того, хочемо ми додати чи відняти 1з поточної позиції, ми завжди можемо це зробити, додавши цифру. Коли ми закінчимо, ми згортаємо результат на його величину (відповідної цифри), скасовуючи збалансовані цифри. Потім ми розбираємо знак на основі цифри, що залишилася, і замінюємо всі цифри на 1.

План полягає в тому, щоб наростити осьові компоненти x і z ліворуч та праворуч :(як роздільник), перед входом. wі sдодасть до правої частини. qі dдодасть до сторони лівої руки, а eй aдодасть до обох сторін. Оскільки wі sвже знаходяться на правильній стороні :(що піде попереду), ми будемо використовувати такі, як -1і +1цифри відповідно.

Перейдемо до коду.

R
5$*r

Почнемо, перетворюючи кожен Rна п’ять rс. Звичайно, один поворот ліворуч такий же, як п’ять праворуч на шестигранній сітці, і, зробивши це, ми можемо багато дублювати на кроці перестановки.

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

Це етап транслітерації, який обертає шість команд, якщо вони знайдені після першої r(тим самим обробляючи першу r). wі їх dпотрібно уникати, щоб не перерости їх у класи персонажів. oВставляє набір джерела в цільовий набір , який економить купу байтів для виконання цих завдань обертання. Отже, відображення символів:

aqweds
saqweds

де останній sу другому ряді можна просто ігнорувати.

)`r(.*)
$1

Це видаляє перший rз рядка, тому що він був оброблений (я б хотів, щоб я вже реалізував обмеження заміни ...). )Також говорить Retina , щоб запустити всі етапи до цього один в циклі , поки рядок не перестає змінюватися. При наступних ітераціях перший етап не працює, тому що більше немає Rs, а другий етап застосує інше обертання до тих пір, поки rв рядку залишилось s.

Коли ми закінчимо, ми нанесли на команду всі невідомі сітки всі команди в напрямку, яким вони відповідають, і ми можемо почати їх обробку. Звичайно, цей рух є лише сумою цих дельта-векторів, і суми є комутативними, тому не має значення, в якому порядку ми їх обробляємо зараз, коли ротації були усунені.

^
:

Вставте роздільник координат спереду.

Зараз нам насправді не потрібно обробляти sі w. Вони є нашими +1та -1цифрами, і вони вже на правильній стороні, :тому вони просто випадуть, як потрібно, врешті-решт. Ми можемо зробити ще одне спрощення: aпросто s + qі eє w + d. Зробимо так:

a
sq
e
wd

Знову ж , ті sі wбудуть просто випадати. Все, що нам потрібно зробити, - це перемістити ці qs і ds на фронт і перетворити їх на ws і ss. Робимо це за допомогою двох окремих петель:

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

Отже, це зроблено. Час перетворення від осьової до зміщеної координат. Для цього нам потрібно згортати цифри. Однак поки що ми дбаємо лише про лівий бік. Завдяки тому, як ми обробили qs і ds, ми знаємо, що всі ss в лівій частині з’являться перед будь-якими ws, тому нам потрібно лише перевірити одну пару для їх згортання:

+`sw

Тепер фактична конверсія. Ось псевдокод, узятий за посиланням вище:

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

Право, значить, лівий бік вже правильний. Праворуч потрібен термін корекції (x - (x&1)) / 2. Беручи &1те саме, що і модуль 2. Це в основному розбирається як x/2ціле ділення, округлене до мінус нескінченності. Отже для позитиву xдодаємо половину кількості цифр (округлюємо вниз), а для від’ємника xвіднімаємо половину кількості цифр (округлимо вгору). Це може бути висловлено напрочуд стисло в регексе:

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

Через жадібність для x1- ї групи 1 відповідатиме рівно половині цифр, \1інша половина, і ми можемо проігнорувати w?. Вставляємо цю половину після :(що є x/2). Якщо xпарне, то нам потрібно розрізняти позитивне та негативне. Якщо xпозитивний, то w?він ніколи не збігатиметься, тому дві групи все одно повинні відповідати однаковій кількості цифр. Це не проблема, якщо перший sпросто пропустити, тому ми округляємо. Якщо xнегативний і непарний, то можлива відповідність \1(половина xокруглення вниз), а це необов'язково w. Оскільки обидва з них входять у групу 2, ми будемо писати x/2із закругленою величиною (як потрібно).

+`sw|ws

Тепер ми згортаємо цифри праворуч. На цей раз ми не знаємо порядок sі w, тому нам потрібно враховувати обидві пари.

w+
-$0

Обидві частини тепер зведені до однієї повторної цифри (або нічого). Якщо ця цифра є w, ми вставляємо знак мінус спереду.

\w
1

І нарешті ми перетворюємо і в, wі sв єдину розумну одинарну цифру. (Я вважаю, що я міг би зберегти байт, використовуючи wабо sяк одинарну цифру, але це здається трохи розтяжкою.)


10
(Чи я єдиний, хто побачив цю відповідь на головній сторінці сайту і дуже сподівався, що її написано шестикутницею?)
Аддісон Кримп

9
@FlagAsSpam Вимоги цієї спільноти серйозно зростають, коли можна розчарувати 8 людей (і рахувати), вирішивши завдання, пов’язане з підписаними цілими чи шестикутними сітками з мовою, яка може обробляти вхід лише через регулярні вирази. ;)
Мартін Ендер

1

Python (3.5) 193 185 182 байт

Я також обчислюю в осьових координатах і конвертую в кінці.

Я додаю деяку оптимізацію відповідно до рішення @Martin Büttner: Я замінюю R на r * 5, це не змінює кількість байтів. Але з цією зміною ми можемо замінити другий тест elif j=='r'простоelse

Рішення припускає, що у нас не може бути недійсних символів.

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)

Безумовно

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"

Використання

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

0

Пакетна, 708 636 586 569 байт

Я використав подвоєні y-координати, оскільки це зробило математику простішою. Я не впевнений, що врахував обертання найбільш ідеальним способом, але це перемогу підраховуючи кількість rs.

Редагувати: збережено 72 байти, покращивши обробку Rs. Збережено 60 байт, оптимізуючи мої set/aзаяви. Збережено 17 байт з деякими незначними оптимізаціями.

@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 байт

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

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

Загальне пояснення:

Починаємо з рядка "qwedsa"та координати [0,0]та петлі над символами введення.
Якщо це "r" або "R", ми повертаємо цю рядок відповідно до лівої або правої.
Якщо ні, то ми отримуємо в цьому рядку 0-заснований індекс і відображаємо його так:

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

ху

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

к

х=мiн(к,абс(к-5))-1
у=(0к(мод3))+2(к>3)-1

І після всієї петлі ми повинні виправити зміщення у-координат на основі х-координат, який ми робимо так (х залишається таким же):

у=у+х-х(мод2)2

Пояснення коду:

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

Дивіться цей 05AB1E наконечник шахти (розділ Як стиснути рядки не частина словника? ) , Щоб зрозуміти , чому .•F?äM•це "qwedsa".


-1

Пітон 3, 227 байт

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, і, хоча я отримав помилку в 5 і 6, через округлення, решта були правильними. (Так зафіксовано через "Правка"). Яку версію Python ви використовуєте?
Остін Гастінгс

1
@AustinHastings Я на Python 3 на Debian нестабільний.
Дверна ручка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.