6 각형 그리드에서 동작


15

6 각형 그리드에서 움직임을 나타내는 일련의 문자를 입력하면 "포인터"의 최종 좌표가 출력됩니다.

우리의 육각형은 다음과 같이 번호가 매겨 질 것입니다 (홀수 번째 열이 약간 아래로 이동 한 직사각형 격자를 상상해보십시오) :

  _____         _____         _____         _____
 /     \       /     \       /     \       /     \
/ -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) 후 명령이 다시 매핑됩니다 (전체 16 진 그리드를 회전하지만 "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

출력은 좌표를 나타내는 정수 목록입니다.

내 솔루션은 실제로 정말 지루합니다. 배열에서 입력 된 문자 ( qwedsa)를 찾은 다음 좌표의 각 변경 사항을 나타내는 두 배열에 액세스합니다. 예를 들어 입력이w 인 경우 배열의 두 번째 문자이므로 1을 얻습니다. 다음 우리는 추가 A[1]x(여기에서 A의 변화에 대한 배열 x및 다른 입력들에 관하여) B[1]y( B대해 변화가있다 y). rR단지 회전에 의해 달성된다 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

출력은 단항으로 콜론으로 구분됩니다. 즉, 출력에 실제로 0이 표시되지 않습니다 (콜론이 있으면 두 좌표 중 하나가있는 경우 0이 무엇인지 알려줍니다).

온라인으로 사용해보십시오!

이것은 정말로 재미 있었고 놀랍게도 짧았습니다. :)

설명

먼저 몇 가지 배경. 육각형 그리드를 설명하기위한 여러 좌표계가 있습니다.요청한 것은 오프셋 좌표를 사용합니다. 그것은 하나의 축이 조금 흔들리는 것을 제외하고는 본질적으로 직사각형 격자 좌표와 같습니다. 특히, 질문은 링크 된 페이지에 표시된 "odd-q"레이아웃을 요구합니다. 이 좌표계는 동작하기에 약간 성가시다. 왜냐하면 이동 중에 좌표가 변경되는 방식은 이동 방향뿐만 아니라 현재 위치에도 달려 있기 때문이다.

다른 좌표계는 축 좌표를 사용합니다. 그것은 본질적으로 육면체의 큐브를 통해 hexgrid를 대각선 슬라이스로 상상하고 두 개의 축 (예 : x 및 z)을 사용하여 2D 평면에서 위치를 찾습니다. 육각 격자에서 두 축은 60도 (또는 120도)의 각도를 형성합니다. 모든 방향이 고정 된 "델타"벡터에 해당하기 때문에이 시스템은 직관적이지 않지만 작업하기가 훨씬 쉽습니다. (이 좌표계에 도달하는 방법에 대한 자세한 설명은 링크와 멋진 다이어그램과 애니메이션을 확인하십시오.)

그래서 우리는 다음과 같이 할 것입니다 : 축 좌표로 운동을 계산하고 (명령의 의미를 다시 매핑함으로써 도전에서 제안 된 회전 관리), 완료되면 축을 홀수 -Q 오프셋으로 변환합니다 좌표.

6 개의 움직임은 (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양쪽에 추가한다. ws의 올바른면에 있기 때문에 :(앞으로 갈 것이므로) 각각을 숫자 -1+1숫자 로 사용합니다 .

코드를 살펴 봅시다.

R
5$*r

우리는 각각 R5 r초로 시작합니다 . 물론, 1 개의 좌회전은 16 진 그리드의 5 개의 우회전과 동일하며, 그렇게함으로써 리매핑 단계에서 많은 중복이 가능합니다.

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

이 명령은 첫 번째 명령 이후에 발견 될 경우 6 개의 명령을 회전시키는 음역 단계입니다 r(따라서 첫 번째 명령 처리 r). w그리고 d필요가 문자 클래스로 확장하는 것을 방지하기 위해 탈출한다. 는 o이러한 회전 작업을위한 바이트의 무리를 절약 목표 설정에 소스 세트를 삽입합니다. 따라서 문자 매핑은 다음과 같습니다.

aqweds
saqweds

s두 번째 행 의 마지막 부분 은 간단히 무시할 수 있습니다.

)`r(.*)
$1

이것은 r처리되었으므로 문자열 에서 첫 번째 를 제거합니다 (이미 대체 제한을 구현했으면합니다 ...). 는 )또한 문자열이 변경 멈출 때까지 루프에서이 일에 모든 단계를 실행하는 망막을 알려줍니다. 후속 반복에서는 Rs 가 더 이상 없기 때문에 첫 번째 단계는 작동하지 않으며 두 번째 단계는 r문자열에 s가 남아있는 한 다른 회전을 적용 합니다.

완료되면 모든 명령이 회전되지 않은 그리드에서 해당하는 방향으로 매핑되어 처리를 시작할 수 있습니다. 물론이 움직임은 그 델타 벡터의 합일 뿐이며 합은 정류 적이므로 회전이 제거 된 지금 어떤 순서로 처리하는지는 중요하지 않습니다.

^
:

좌표 구분 기호를 앞에 삽입하십시오.

이제 우리는 정말 처리 할 필요가 없습니다 sw. 그것들은 우리 +1-1숫자이며 이미 올바른쪽에 :있으므로 결국 필요에 따라 떨어질 것입니다. 우리는 또 다른 단순화를 만들 수 있습니다 : ais s + qand eis w + d. 그걸하자:

a
sq
e
wd

다시, 그 sw그냥 떨어질 것입니다. 우리가해야 할 일은 그 qs와 ds를 앞으로 이동 시키고 그것들을 ws와 ss 로 바꾸는 것 입니다. 우리는 두 개의 별도 루프로 그렇게합니다.

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

이제 끝났습니다. 축 좌표에서 오프셋 좌표로의 변환 시간. 이를 위해 우리는 숫자를 축소해야합니다. 그러나 현재로서는 왼쪽에만 관심이 있습니다. qs 및 ds를 처리하는 방식으로 인해 s왼쪽의 모든 ws 가 임의 의 s 앞에 표시 되므로 축소하기 위해 한 쌍만 확인하면됩니다.

+`sw

이제 실제 전환입니다. 위의 링크에서 가져온 의사 코드는 다음과 같습니다.

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

왼쪽이 이미 맞습니다. 오른쪽에는 수정 항이 필요합니다 (x - (x&1)) / 2. 취하는 &1것은 모듈로 2와 동일합니다. 이것은 기본적 x/2으로 마이너스 무한대로 반올림 된 정수 나누기 로 해석됩니다 . 따라서 positive x의 경우 자릿수의 반을 반올림하고 (반올림), negative x의 경우 자릿수의 반을 반올림합니다 (반올림). 이것은 정규식에서 놀랍도록 간결하게 표현 될 수 있습니다.

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

탐욕으로 인해 x그룹 1은 숫자의 정확히 절반과 일치 \1하고 나머지 절반은 무시할 수 있습니다 w?. 우리는 이후 절반 삽입 :(입니다 x/2). 경우 x도있다, 우리는 긍정과 부정을 구별 할 필요가있다. 경우 x긍정적, 다음 w?두 그룹이 여전히 동일한 자릿수의 수와 일치해야합니다, 그래서 일치하지 않습니다. 첫 번째 s를 건너 뛰더라도 아무런 문제가 없으므로 반올림합니다. 경우 x음극 및 홀수 후 가능한 매치는 함께 \1(반 x둥근 다운)하고 선택적 w. 두 그룹이 모두 그룹으로 들어가기 때문에 필요에 따라 크기를 반올림하여 2작성 x/2합니다.

+`sw|ws

이제 오른쪽의 숫자를 접습니다. 이번에는 sand 의 순서 w를 모르므로 두 쌍을 모두 고려해야합니다.

w+
-$0

두 부분은 이제 하나의 반복 된 숫자 (또는 아무것도 아님)로 축소됩니다. 해당 숫자가 w인 경우 앞에 빼기 부호를 삽입합니다.

\w
1

그리고 마지막으로 우리는에 모두 설정 w하고 s하나의 합리적인 단항 자리에. ( w또는 s단항 자릿수 를 사용하여 바이트를 절약 할 수 있다고 가정 하지만 약간의 스트레치 인 것 같습니다.)


10
(나는이 답변을 본 사람이 메인 사이트 페이지에 와서 육각형으로 작성된 것을 정말로 기대 했습니까?)
Addison Crump

9
@FlagAsSpam 정규식을 통해서만 입력을 처리 할 수있는 언어로 부호있는 정수 및 6 각형 그리드와 관련된 문제를 해결함으로써 8 명 (및 계산)을 실망시킬 수있을 때이 커뮤니티의 요구가 심각하게 증가하고 있습니다. ;)
Martin Ender

1

파이썬 (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 좌표를 사용했습니다. 가장 이상적인 방법으로 회전을 고려했는지 확실하지 않지만의 수를 세는 것보다 낫습니다 r.

편집 : 처리를 개선하여 72 바이트를 절약했습니다. R s . 내 set/a문장 을 최적화하여 60 바이트를 절약했습니다 . 약간의 최적화로 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

케이

엑스=미디엄나는(케이,에스(케이5))1
와이=(0케이(모드))+2(케이>)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.0b3맥 OS에, 나는 반올림으로 인해, 5, 6에서 오류가 발생했던 반면, 나머지는 정확했다. (편집을 통해 수정되었으므로). 어떤 버전의 Python을 사용하고 있습니까?
Austin Hastings

1
@AustinHastings Debian의 Python 3에서 불안정합니다.
Doorknob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.