삼각 맨해튼 거리


26

맨해튼 거리 정규 그리드 하나가 서로 하나의 셀에 도달하기 위해 수행해야하는 직교 단계의 수입니다. 직교 단계는 격자 셀의 가장자리를 통과하는 단계입니다 (모서리와 달리 Chebyshev 거리를 제공합니다 ).

삼각 격자와 같은 다른 격자에서도 비슷한 거리를 정의 할 수 있습니다. 각 셀에 x,y쌍이 포함 된 다음 색인 구성표를 사용하여 그리드의 개별 셀을 처리 할 수 ​​있습니다 .

    ____________________________________...
   /\      /\      /\      /\      /\
  /  \ 1,0/  \ 3,0/  \ 5,0/  \ 7,0/  \
 / 0,0\  / 2,0\  / 4,0\  / 6,0\  / 8,0\
/______\/______\/______\/______\/______\...
\      /\      /\      /\      /\      /
 \ 0,1/  \ 2,1/  \ 4,1/  \ 6,1/  \ 8,1/
  \  / 1,1\  / 3,1\  / 5,1\  / 7,1\  /
   \/______\/______\/______\/______\/___...
   /\      /\      /\      /\      /\
  /  \ 1,2/  \ 3,2/  \ 5,2/  \ 7,2/  \
 / 0,2\  / 2,2\  / 4,2\  / 6,2\  / 8,2\  
/______\/______\/______\/______\/______\...
\      /\      /\      /\      /\      /
 \ 0,3/  \ 2,3/  \ 4,3/  \ 6,3/  \ 8,3/
  \  / 1,3\  / 3,3\  / 5,3\  / 7,3\  /
   \/______\/______\/______\/______\/___...
   /\      /\      /\      /\      /\
  .  .    .  .    .  .    .  .    .  .
 .    .  .    .  .    .  .    .  .    .

이제이 그리드의 맨해튼 거리는 다시 한 셀에서 다른 셀로 이동하기 위해 가장자리를 가로 지르는 최소 단계 수입니다. 그래서 당신은 이동할 수 3,12,1, 4,1또는 3,2그 오히려 가장자리보다 포인트를 교차 할 것이기 때문에, 있지만 다른 삼각형.

예를 들어으로부터의 거리 2,1에가 5,2있다 4. 최단 경로는 일반적으로 고유하지 않지만 4 단계로 거리를 만드는 한 가지 방법은 다음과 같습니다.

2,1 --> 3,1 --> 3,2 --> 4,2 --> 5,2

도전

두 개의 좌표 쌍 과 위의 주소 지정 체계에서 맨해튼 거리를 반환하십시오.x1,y1x2,y2

4 개의 입력이 모두 128보다 작은 음이 아닌 정수라고 가정 할 수 있습니다. 임의의 순서로 임의로 그룹화 할 수 있습니다 (4 개의 개별 인수, 4 개의 정수 목록, 2 개의 정수 쌍, 2x2 행렬, .. ).

사용자가 쓸 수 프로그램이나 함수를 상기의 어떠한 사용도 표준 방법 의 입력을 수신하고 출력을 제공한다.

모든 프로그래밍 언어를 사용할 수 있지만 이러한 허점 은 기본적으로 금지되어 있습니다.

이것은 이므로 바이트 단위로 측정 된 가장 짧은 유효한 답변이 이깁니다.

테스트 사례

각 테스트 사례는로 제공됩니다 .x1,y1 x2,y2 => result

1,2 1,2 => 0
0,1 1,1 => 1
1,0 1,1 => 3
2,1 5,2 => 4
0,0 0,127 => 253
0,0 127,0 => 127
0,0 127,127 => 254
0,127 127,0 => 254
0,127 127,127 => 127
127,0 127,127 => 255
75,7 69,2 => 11
47,58 36,79 => 42
77,9 111,23 => 48
123,100 111,60 => 80
120,23 55,41 => 83
28,20 91,68 => 111
85,107 69,46 => 123
16,25 100,100 => 159
62,85 22,5 => 160
92,26 59,113 => 174
62,22 35,125 => 206

순 마이너스 등급을받은 허점이 공식 허점에 포함됩니까?
DavidC

@DavidC No. 허점 질문에서 : "[...] +5 이상이고 다운 보트가 커뮤니티에 허용되지 않는 것으로 간주 될 수있는 다운 보트 수의 두 배 이상인 응답에 설명 된 허점 "
Martin Ender

기본적으로 0에서 시작하는 다섯 번째 입력을받을 수 있습니까 (결과)? 그런 다음 내 대답에 ( 네 개의 인수와 다섯 번째 인수로 (a,b,x,y)->c(a,b,x,y,0)분리 된 메서드 호출) 를 추가 할 필요가 없습니다 . c0
Kevin Cruijssen

3
@KevinCruijssen 죄송합니다. 추가로, 고정 된 인수는 너무 쉽게 남용 될 수 있습니다 (특별한 경우 0 만 허용하는 것이 이상하게 보입니다).
Martin Ender

@MartinEnder 좋아, 그렇게 생각했지만 결코 아프지 않을 수 있습니다. 이 경우 190 바이트의 대답이 남아 있습니다. 1 년 전 반으로 대답했지만 한 가지 테스트 사례가 실패했습니다. 방금 질문을 다시 건너 왔고 내 대답에서 버그를 수정할 수있었습니다.
Kevin Cruijssen '10

답변:


7

자바 스크립트 (ES6), 84 78 바이트

Neil 덕분에 6 바이트 절약

(a,b,c,d,x=a>c?a-c:c-a,y=b>d?b-d:d-b,z=x>y?x:y)=>y+z+(x+z&1?a+b+(b>d)&1||-1:0)

테스트 사례

초기 재귀 솔루션, 100 88 81

ETH 프로덕션 덕분에 12 바이트
절약 Neil 덕분에 7 바이트 절약

f=(a,b,c,d,e=b==d|a+b+(b>d)&1)=>a-c|b-d&&f(e?a+1-2*(a>c):a,e?b:b+1-2*(b>d),c,d)+1

작동 원리

여전히 기본적으로 현재 버전에 적용되지만 다음 설명은 초기 버전에 대해보다 구체적으로 설명합니다.

f=(a,b,c,d)=>b-d?a+b+(b>d)&1?f(a+1-2*(a>c),b,c,d)+1:f(a,b+1-2*(b>d),c,d)+1:Math.abs(a-c)

에서가는 (X0, Y)(X1, Y 것은) 우리가 목표 한 원본 삼각형에서 측면 가장자리에 걸쳐 모든 길을 갈 수 있기 때문에 간단하다. 이 경우 맨해튼 거리는 | x0-x1 | .

까다로운 부분은 수직 단계입니다. y0 행에서 y1 행으로 이동하려면 다음 두 매개 변수를 고려해야합니다.

  • 현재 삼각형의 방향
  • y0y1 보다 작거나 큰지 여부

삼각형의 방향은 x + y 의 패리티로 제공됩니다 .

  • 짝수이면 삼각형이 위쪽을 가리키고 있습니다.
  • 홀수이면 삼각형이 아래쪽을 가리킴

위쪽을 가리키는 삼각형 ( y0 <y1 일 때 유용 )에서 아래쪽으로, 아래쪽을 가리키는 삼각형 ( y0> y1 일 때 유용)에서 위쪽으로 갈 수 있습니다 .

삼각형의 방향과 y0y1 의 비교를 결합하여 원하는 방향으로 갈 수 있고 그렇지 않은 경우 홀수 인 공식 x + y0 + (y0> y1? 1 : 0) 을 얻습니다 .

다음 행에 직접 도달 할 수 없으면 먼저 x 를 업데이트하여 올바른 정렬을 가져와야합니다 .

  • 경우 x는 아직 동일하지 않은 1 개 , 우리는 확실히 경우 우리가 증가하므로, 올바른 방향으로 이동하려는 x가 11보다 1 개 그리고 만약 우리가 그것을 감소 x는 보다 큰 1 개
  • 경우 x는 이미 동일 1 개를 , 우리는 하나 증가를 할 수 있습니다하거나 감소

테스트 사례


그것은 ... 매우 작은 수학 연산입니다 ... 그러나 n변수를 완전히 건너 뛰고 각 반복의 결과에 1을 더할 수 없었 습니까? ( 내가 생각하는 90 자 )
ETHproductions

@ETHproductions 솔직히 말해서, 나는 심각한 골프없이 게시했습니다. 그러나 이것이 가장 먼저해야 할 일입니다. 감사!
Arnauld

1
또한 연산자 우선 순위는 2 바이트를 절약 할 수 있다는 것을 의미 한다고 생각 합니다.&a+b+(b>d)&1
ETHproductions

81이라고 생각합니다.f=(a,b,c,d,e=b==d|a+b+(b>d)&1)=>a-c|b-d&&f(e?a+1-2*(a>c):a,e?b:b+1-2*(b>d),c,d)+1
Neil

나는 영리한 카레를 사용하여 다른 바이트를 절약 할 수 있다고 생각합니다.
Neil

5

파이썬 2, 74 바이트

lambda x,y,X,Y:abs(y-Y)+max(x-X,X-x,abs(y-Y)+((x+y+X+Y)%-2)**(x^y^(Y>=y)))

1
이 부분을 설명해 주 **(x^y^(Y>=y))시겠습니까?
Dead Possum

1
@DeadPossum 1 거리만큼 수직으로 이동하면 1 또는 3 이동이 가능합니다. 패리티를 보면 알 수있는 방법이 없으므로 y 값을 비교해야합니다.
feersum

2

배치, 99 바이트

@cmd/cset/a"x=%3-%1,x*=x>>31|1,y=%4-%2,w=y>>31,y*=w|1,z=x+(y+x&1)*(-(%1+%2+w&1)|1)-y,z*=z>>31,x+y+z

설명 : 수평 전용 모션은 단순히 절대 x 좌표 차이를 취합니다. 충분히 큰 x의 경우 수직 운동은 절대 y 좌표 차이 당 하나의 추가 단계 만 수행하지만 작은 x의 경우 두 y 좌표 차이 당 4 개의 추가 단계와 홀수 차이의 경우 1 ~ 3 단계가 필요합니다. 이것은 차이 당 두 단계와 보정 계수로 계산됩니다. 수정 된 두 단계 중 더 큰 값과 절대 차이의 합이 결과이지만, 그 자체는 수정 된 절대 y 좌표 차이와 수정되지 않은 절대 y 좌표 차이에 추가 된 절대 x 좌표 거리 중 더 큰 것으로 계산됩니다. .

  • @cmd/cset/a" -쉼표로 구분 된 표현식을 평가하고 마지막 표현식을 인쇄합니다.
  • x=%3-%1,x*=x>>31|1x=|x2x1|
  • y=%4-%2,w=y>>31,y*=w|1w=y1>y2y=|y2y1|
  • z=x+(y+x&1)*(-(%1+%2+w&1)|1)-yc=(y+(xmod2))(12((x1+y1+w)mod2)),z=x+cy
  • z*=z>>31,x+y+z계산하여max(x,yc)+y=x+ymin(0,x+cy)

2

젤리 , 24 바이트

⁴<³¬Ḋ;³S
SḂN*¢+ḊḤ$
ạµS»Ç

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

입력 호출 해 봅시다 . 나는 feersum의 공식에서 일했습니다.(x,y),(X,Y)

d=|yY|+max(|xX|,|yY|+((x+y+X+Y)mod2)xy(Yy))=|yY|+max(|xX|,|yY|+[(|xX|+|yY|mod2)]x+y+(Yy))=max(|xX|+|yY|,2|yY|+[(|xX|+|yY|mod2)](Yy)+x+y).

첫 번째 줄은 공식의 지수 인 를 계산합니다.¢=(Yy)+x+y

마지막 줄은 먼저 를 계산 한 다음 최대 및 을 계산합니다 . 여기서 는 중간 줄의 함수입니다.L=[|xX|,|yY|]sum(L)f(L)f

주어진 가운데 선 은 를 계산하고이를 '제곱으로 한 다음 를 더합니다 .L=[a,b]((a+b)mod2)¢2b


2

라켓 / 구성표, 214 바이트

(define(f x y X Y)(let m((p x)(q y)(c 0))
(let((k(+ c 1))(d(- Y q)))
(cond((= 0(- X p)d)c)
((and(> d 0)(even?(+ p q)))(m p(+ q 1)k))
((and(< d 0)(odd?(+ p q)))(m p(- q 1)k))
((< p X)(m(+ p 1)q k))
(else(m(- p 1)q k))))))

2

05AB1E , 24 바이트

Pyth 응답의 포트는 feersum의 Python 응답 과 거의 동일한 접근 방식을 사용합니다 . 좌표 쌍의 목록으로 입력을 . +1 바이트에 대한 버그를 수정 한 후 +1에 대한 또 다른 실수를 수정했지만 모든 테스트 사례에 대해 올바른 결과를 얻었습니다 ...(x1,x2),(y1,y2)

ÆÄ`©I˜OÉ(IøнOIθD{Q+m+M®+

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

고장

ÆÄ` © I ~ OÉ (IøнOIθD {Q + m + M® + Full program. I는 평가 된 입력을 나타냅니다.
Æ 뺄셈으로 쌍을 줄이고 절대 값을 취하십시오.
  `© 따로 따로 쌓아 두 번째 저장
                            하나, | y1-y2 | 레지스터 C에서
    I ~ O 평평한 입력의 합을 스택에 밀어 넣습니다.
       É (패리티를 가져 가서 무효화합니다.
         [x1, y1]을 누릅니다.
            ○ x1 + y1을 취하십시오 (요약).
             그런 다음 두 번째 쌍이 정렬되어 있는지 확인하십시오 (y1 ≤ y2).
                  + x1 + y1과 합산합니다.
                   m 지수. ** 결과 위에 패리티를 밀어 넣습니다.
                    + 두 번째 절대 차이를 추가하십시오.
                     M® + 결과적으로 스택에서 가장 큰 숫자를 밀어 넣습니다.
                            + 레지스터 C에 저장된 값

나는 확실하지 100 %를 해요,하지만 당신은 변경할 수 없습니다 ©D하고 제거 ®? 현재 TIO에서 사례에 효과가있는 것 같지만 모든 사례에서 동일한 경로를 따르는 지 확실하지 않습니다.
Kevin Cruijssen

1
@KevinCruijssen 편집 : 아니요, M의 행동은 이것의 영향을 받기 때문 입니다. 에 실패합니다 [[0, 127], [0, 0]].
Mr. Xcoder 2018 년

2

파이썬 2 , 74 72 71 바이트

lambda c,a,d,b:abs(a-b)+abs(a+(-c-a)/2-b-(-d-b)/2)+abs((c+a)/2-(d+b)/2)

온라인으로 사용해보십시오! 링크에는 테스트 사례가 포함됩니다. 편집 : @JoKing 덕분에 2 바이트가 절약되었습니다. @ Mr.Xcoder 덕분에 추가 바이트를 절약했습니다. 이 질문 에서 찾은 다음 공식을 기반으로합니다 .

|aibi|+|(aiaj2)(bibj2)|+|aj+12bj+12|

좌표계는 세 가지면에서 다릅니다. 좌표가 교환됩니다 (약간의 이상한 매개 변수 이름 순서를 설명합니다). 좌표는 아닌 (각 추가 사항을 설명합니다)가 아닌 각도로 연결되며 연결된 질문의 좌표는 열등한 1 인덱싱을 사용합니다. 우리는 차이를 겪고 있기 때문에 대부분의 시간이 취소되며 다음과 같이 남습니다.12090

|aibi|+|(aiaj+12)(bibj+12)|+|aj2bj2|

그런 다음 있습니다.aj+12=aj2


줄 바꿈을 제거하여 하나의 라이너로 만들 수 있습니다
Jo King

1
lambda c,a,d,b:abs(a-b)+abs(a+-(c+a)/2-b--(d+b)/2)+abs((c+a)/2-(d+b)/2)3 바이트를 저장해야합니다.
Mr. Xcoder

1

Pyth , 31 28 바이트

feersum의 Python answer 에서와 거의 동일한 접근 방식을 사용합니다 . 좌표 쌍의 목록으로 입력을 . -1 바이트의 버그를 수정했습니다.(x1,x2),(y1,y2)

+eKaMQg#hK+eK^%ssQ_2+shCQSIe

여기 사용해보십시오! 또는 테스트 스위트를 사용해보십시오!

고장

+ eKaMQg # hK + eK ^ % ssQ_2xxFhCQSIe 전체 프로그램. Q = eval (input ()).
  KaMQ 차이 [| x1-x2 |, | y1-y2 |]를 K에 저장하십시오.
 e 후자를 검색합니다 (| y1-y2 |).
+ g # 그리고 다음 사이에 가장 큰 값을 더하십시오 :
        hK-K의 머리 (| x1-x2 |)
          +-그리고 추가 결과 :
           eK K의 끝 (| y1-y2 |).
             ^-지수화 결과 :
              % ssQ_2 평탄화 된 Q의 합계, 모듈로 -2.
                                        x1 + x2 + y1 + y2가 홀수이면 -1을, 그렇지 않으면 0을 나타냅니다.
                    xxFhCQSIe-이 표현식의 결과 :
                       hCQ Q를 바꾸고 헤드 (x1, y1)를 얻습니다.
                     xF 비트 단위 XOR로 줄입니다.
                          SIe [y1, y2]리스트가 정렬되어 있는지 확인하십시오.
                    x 그 후, 부울 (0/1)로 결과를 xor합니다.

1

05AB1E , 16 바이트

05AB1E와 같은 스택 기반 언어에 최적화 된 수정 된 Neil 's answer 버전을 사용합니다 . STDIN에서 줄 바꿈으로 구분하여 두 개의 좌표 쌍 로 입력을받습니다. 처음에는 다른 05AB1E 답변 과 병합 했지만 매우 다르기 때문에 별도로 게시하기로 결정했습니다.(x1,x2),(y1,y2)

+D(‚2÷Æ`²Æ©+®)ÄO

온라인으로 사용해보십시오! 또는 테스트 스위트를 사용해보십시오! ( Kevin Cruijssen이 제공 한 약간 수정 된 코드 버전 ( ®대신 ) 사용)²


좋은 대답입니다! 아니 골프 뭔가,하지만 당신은 변경하는 경우 ©+®DŠ+는 테스트 스위트를 설정하는 것이 더 쉽습니다. ;) 여기에 테스트 스위트가 있으며 모든 테스트 사례가 실제로 성공했습니다 (지저분한 헤더는 무시하십시오; p).
Kevin Cruijssen

@KevinCruijssen 나는 그것을 대체 버전으로 가지고 있었지만 테스트 스위트를 작성할 수 있다는 것이 나에게 발생하지 않았다 ... 고마워요, 추가하겠습니다
Mr. Xcoder

1
@KevinCruijssen 나는 2 개 이상의 (매우 명백한 ...!) 바이트를 골라 내고 테스트 스위트 호환성을 더욱 깨뜨 렸습니다. 그래서 그대로 유지했습니다 : P 편집에 감사드립니다.
Mr. Xcoder 2016 년


1

자바 (8) 157 190 188 144 142 141 127 바이트

(a,b,x,y)->{int r=0,c=1,z=1;for(;(c|z)!=0;r--){c=x-a;z=y-b;if((z<0?-z:z)<(c<0?-c:c)|a%2!=b%2?z<0:z>0)b+=z<0?-1:1;else a+=c<0?-1:1;}return~r;}

버그 수정으로 인해 +33 바이트 (157 → 190).
재귀 메서드를 단일 루핑 메서드로 변환하는 -44 바이트 (188 → 144) @ceilingcat
덕분에 -14 바이트 .

설명:

여기에서 시도하십시오.

(a,b,x,y)->{          // Method with four integers as parameter and integer return-type
                      // (a=x1; b=y1; x=x2; y=y2)
  int r=0,            //  Result-integer `r`, starting at 0
      c=1,z=1;        //  Temp integers for the differences, starting at 1 for now
  for(;(c|z)!=0;      //  Loop until both differences are 0
      r--){           //    After every iteration: decrease the result `r` by 1
    c=x-a;            //   Set `c` to x2 minus x1
    z=y-b;            //   Set `z` to y2 minus y1
    if(z*Z            //   If the absolute difference between y2 and y1
       <c*c)          //   is smaller than the absolute difference between x2 and x1
       |a%2!=b%2?     //   OR if the triangle at the current location is facing downwards
         z<0          //       and we have to go upwards,
        :z>0)         //      or it's facing upwards and we have to go downwards
      b+=z<0?-1:1;    //    In/decrease y1 by 1 depending on where we have to go
    else              //   Else:
     a+=c<0?-1:1;}    //    In/decrease x1 by 1 depending on where we have to go
  return~r;           //  Return `-r-1` as result

1
z*z<c*c대신 추천(z<0?-z:z)<(c<0?-c:c)
천장 고양이

@ceilingcat 아, 좋아. 감사!
Kevin Cruijssen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.