Khoảng cách tam giác Manhattan


26

Các khoảng cách Manhattan trên một mạng lưới thông thường là số lượng các bước trực giao ta cần phải làm để đạt được một tế bào từ khác. Các bước trực giao là những bước đi qua các cạnh của các ô lưới (trái ngược với các góc, sẽ cho chúng ta khoảng cách Ch Quashev ).

Chúng ta có thể định nghĩa một khoảng cách tương tự trên các lưới khác, ví dụ lưới tam giác. Chúng ta có thể giải quyết các ô riêng lẻ trong lưới bằng sơ đồ lập chỉ mục sau, trong đó mỗi ô chứa một x,ycặp:

    ____________________________________...
   /\      /\      /\      /\      /\
  /  \ 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\  /
   \/______\/______\/______\/______\/___...
   /\      /\      /\      /\      /\
  .  .    .  .    .  .    .  .    .  .
 .    .  .    .  .    .  .    .  .    .

Bây giờ khoảng cách Manhattan trên lưới này một lần nữa là số bước tối thiểu trên các cạnh để đi từ ô này sang ô khác. Vì vậy, bạn có thể di chuyển từ 3,1đến 2,1, 4,1hoặc 3,2, nhưng không phải bất kỳ tam giác nào khác, vì chúng sẽ là các điểm giao nhau chứ không phải là các cạnh.

Ví dụ, khoảng cách từ 2,1đến 5,24. Con đường ngắn nhất thường không phải là duy nhất, nhưng một cách để tạo khoảng cách trong 4 bước là:

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

Các thách thức

Cho hai cặp tọa độ và từ sơ đồ địa chỉ trên, trả về khoảng cách Manhattan giữa chúng.x1,y1x2,y2

Bạn có thể giả sử rằng tất cả bốn đầu vào là số nguyên không âm, mỗi số nhỏ hơn 128. Bạn có thể lấy chúng theo bất kỳ thứ tự nào và được nhóm tùy ý (bốn đối số riêng biệt, danh sách bốn số nguyên, hai cặp số nguyên, ma trận 2x2, .. .).

Bạn có thể viết một chương trình hoặc một chức năng và sử dụng bất kỳ phương pháp tiêu chuẩn nào để nhận đầu vào và cung cấp đầu ra.

Bạn có thể sử dụng bất kỳ ngôn ngữ lập trình nào , nhưng lưu ý rằng các lỗ hổng này bị cấm theo mặc định.

Đây là , vì vậy câu trả lời hợp lệ ngắn nhất - được đo bằng byte - thắng.

Các trường hợp thử nghiệm

Mỗi trường hợp thử nghiệm được đưa ra là .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

Là sơ hở nhận được xếp hạng tiêu cực ròng được bao gồm trong các lỗ hổng chính thức?
DavidC

@DavidC Không. Từ câu hỏi kẽ hở: "[...] lỗ hổng được mô tả trong bất kỳ câu trả lời nào ở mức +5 trở lên và có ít nhất hai lần số lượt upvote có thể được coi là không thể chấp nhận được đối với cộng đồng "
Martin Ender

Chúng tôi có được phép lấy đầu vào thứ năm, bắt đầu từ 0 theo mặc định (kết quả) không? Sau đó, tôi sẽ không cần thêm (a,b,x,y)->c(a,b,x,y,0)(gọi phương thức tách biệt cvới bốn đối số và 0là đối số thứ năm) vào câu trả lời của tôi.
Kevin Cruijssen

3
@KevinCruijssen Không xin lỗi. Bổ sung, các đối số cố định là một chút quá dễ dàng có thể sử dụng được (và chỉ cho phép 0 là trường hợp đặc biệt có vẻ kỳ lạ).
Martin Ender

@MartinEnder Ok, nghĩ vậy, nhưng không bao giờ có thể đau lòng hỏi. Trong trường hợp đó, câu trả lời 190 byte của tôi vẫn còn. Mặc dù tôi đã trả lời một nửa năm trước, một trường hợp thử nghiệm đã thất bại. Đã đến câu hỏi một lần nữa và đã có thể sửa lỗi trong câu trả lời của tôi.
Kevin Cruijssen

Câu trả lời:


7

JavaScript (ES6), 84 78 byte

Đã lưu 6 byte nhờ Neil

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

Các trường hợp thử nghiệm

Giải pháp đệ quy ban đầu, 100 88 81

Đã lưu 12 byte nhờ vào ETHproductions
Lưu 7 byte nhờ Neil

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

Làm thế nào nó hoạt động

Mặc dù về cơ bản nó vẫn áp dụng cho phiên bản hiện tại, nhưng lời giải thích sau đây cụ thể hơn đề cập đến phiên bản ban đầu:

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)

Đi từ (x0, y) đến (x1, y) là không đáng kể vì chúng ta có thể đi qua các cạnh bên suốt từ tam giác nguồn đến mục tiêu. Khoảng cách Manhattan trong trường hợp này là | x0 - x1 | .

Phần khó khăn là các bước dọc. Để đi từ hàng y0 đến hàng y1 , chúng ta phải đưa hai tham số này vào tài khoản:

  • Hướng của tam giác hiện tại
  • Cho dù y0 nhỏ hơn hay lớn hơn y1

Hướng của một tam giác được cho bởi tính chẵn lẻ của x + y :

  • nếu nó chẵn, hình tam giác hướng lên
  • nếu nó lẻ, hình tam giác hướng xuống

Chúng ta có thể đi xuống từ một tam giác hướng lên (hữu ích khi y0 <y1 ) và đi lên từ một tam giác hướng xuống (hữu ích khi y0> y1 ).

Bằng cách kết hợp hướng của tam giác với so sánh giữa y0y1 , chúng ta có được công thức x + y0 + (y0> y1? 1: 0) có kết quả là ngay cả khi chúng ta có thể đi theo hướng mong muốn và lẻ nếu không.

Nếu chúng tôi không thể trực tiếp đến hàng tiếp theo, trước tiên chúng tôi cần có được căn chỉnh chính xác bằng cách cập nhật x :

  • nếu x chưa bằng x1 , chúng tôi chắc chắn muốn di chuyển theo đúng hướng, vì vậy chúng tôi tăng nó nếu x nhỏ hơn x1 và chúng tôi giảm nó nếu x lớn hơn x1
  • nếu x đã bằng x1 , chúng ta có thể tăng hoặc giảm nó

Các trường hợp thử nghiệm


Đó là ... rất nhiều phép toán rất nhỏ ... Nhưng bạn không thể bỏ qua nbiến hoàn toàn và chỉ thêm 1 vào kết quả của mỗi lần lặp? ( 90 ký tự tôi nghĩ)
ETHproductions

@ETHproductions Thành thật mà nói, tôi đã đăng nó mà không cần chơi golf nghiêm túc. Nhưng đó chắc chắn là điều đầu tiên phải làm. Cảm ơn!
Arnauld

1
Ngoài ra, tôi nghĩ rằng quyền ưu tiên của toán tử &có nghĩa là bạn có thể làm a+b+(b>d)&1để lưu 2 byte
ETHproductions

Tôi đã giảm xuống còn 81, tôi nghĩ: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

Tôi nghĩ rằng có thể lưu một byte khác bằng cách sử dụng một số currying thông minh.
Neil

5

Python 2, 74 byte

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
Bạn có thể, xin vui lòng, giải thích phần này : **(x^y^(Y>=y))?
Dead Possum

1
@DeadPossum Di chuyển theo khoảng cách 1 theo chiều dọc có thể mất 1 hoặc 3 lần di chuyển; không có cách nào để nói bằng cách chỉ nhìn vào các chẵn lẻ để bạn phải so sánh các giá trị y.
frageum

2

Mẻ, 99 byte

@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

Giải thích: Một chuyển động chỉ đường chân trời chỉ đơn giản là có sự khác biệt tọa độ x tuyệt đối. Đối với x đủ lớn, chuyển động dọc chỉ mất thêm một bước cho chênh lệch tọa độ y tuyệt đối, nhưng đối với x nhỏ, phải mất bốn bước bổ sung cho hai chênh lệch tọa độ y, cộng thêm một hoặc ba bước cho chênh lệch lẻ. Điều này được xác định là hai bước cho mỗi chênh lệch cộng với hệ số hiệu chỉnh. Kết quả lớn hơn của hai bước đã sửa và tổng các chênh lệch tuyệt đối là kết quả, mặc dù điều này được tính là lớn hơn của chênh lệch tọa độ y tuyệt đối đã hiệu chỉnh và khoảng cách tọa độ x tuyệt đối được thêm vào chênh lệch tọa độ y tuyệt đối không được xử lý .

  • @cmd/cset/a" - Đánh giá các biểu thức được phân tách bằng dấu phẩy và in biểu thức cuối cùng
  • x=%3-%1,x*=x>>31|1Tính x=|x2x1|
  • y=%4-%2,w=y>>31,y*=w|1Tính y = | y 2 - y 1 |w=y1>y2y=|y2y1|
  • z=x+(y+x&1)*(-(%1+%2+w&1)|1)-yHệ số hiệu chỉnh c=(y+(xmod2))(12((x1+y1+w)mod2)),z=x+cy
  • z*=z>>31,x+y+zTính max(x,yc)+y=x+ymin(0,x+cy)

2

Thạch , 24 byte

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

Hãy thử trực tuyến!

Hãy gọi đầu vào . Tôi đã làm việc từ công thức của frageum:(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).

Dòng đầu tiên tính , số mũ trong công thức.¢=(Yy)+x+y

Dòng cuối cùng đầu tiên tính và sau đó tính tối đa của tổng ( L )f ( L ) , trong đó f là hàm trên đường giữa.L=[|xX|,|yY|]sum(L)f(L)f

Dòng trung bình, cho , tính - ( ( một + b ) mod 2 ) , mất đó đến ¢ 'thứ quyền lực, sau đó thêm 2 b .L=[a,b]((a+b)mod2)¢2b


2

vợt / sơ đồ, 214 byte

(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 byte

(x1,x2),(y1,y2)

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

Hãy thử trực tuyến!

Phá vỡ

ÆÄ` © I˜OÉ (IøнOIθD {Q + m + M® + Chương trình đầy đủ. Tôi đại diện cho đầu vào được đánh giá.
Giảm các cặp bằng phép trừ, lấy các giá trị tuyệt đối.
  `© Đổ chúng riêng rẽ vào ngăn xếp và lưu trữ thứ hai
                            một, | y1-y2 | trong sổ đăng ký C.
    I˜O Đẩy tổng đầu vào dẹt lên ngăn xếp.
       É (Lấy tính chẵn lẻ của nó và phủ nhận nó.
         Đẩy Iøн [x1, y1].
            O Lấy x1 + y1 (tính tổng chúng).
             IθD {Q Sau đó kiểm tra xem cặp thứ hai có được sắp xếp không (y1 y2).
                  + Và tổng hợp với x1 + y1.
                   m lũy thừa. Đẩy chẵn lẻ trên ** kết quả.
                    + Và thêm sự khác biệt tuyệt đối thứ hai vào đó.
                     M® + Kết quả là, đẩy số lượng lớn nhất trên ngăn xếp
                            cộng với giá trị được lưu trong thanh ghi C.

Tôi không chắc chắn 100%, nhưng bạn không thể thay đổi ©để Dvà loại bỏ các ®? Nó dường như hoạt động cho trường hợp hiện tại trong TIO của bạn, nhưng tôi không chắc liệu nó có đi theo cùng một đường dẫn cho mọi trường hợp không.
Kevin Cruijssen

1
@KevinCruijssen EDIT : Không, vì Mhành vi của họ sẽ bị ảnh hưởng bởi điều này. Thất bại cho [[0, 127], [0, 0]].
Ông Xcoder

2

Python 2 , 74 72 71 byte

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

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm. Chỉnh sửa: Đã lưu 2 byte nhờ @JoKing. Đã lưu thêm một byte nhờ @ Mr.Xcoder. Dựa trên công thức sau đây tôi tìm thấy trong câu hỏi này :

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

12090

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

aj+12=aj2


Bạn có thể biến nó thành một lớp lót bằng cách xóa dòng mới
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)nên tiết kiệm 3 byte.
Ông Xcoder

1

Bình thường , 31 28 byte

(x1,x2),(y1,y2)

+eKaMQg#hK+eK^%ssQ_2+shCQSIe

Hãy thử nó ở đây! hoặc Thử bộ kiểm tra!

Phá vỡ

+ eKaMQg # hK + eK ^% ssQ_2xxFhCQSIe Chương trình đầy đủ. Q = eval (đầu vào ()).
  KaMQ Lưu trữ sự khác biệt [| x1-x2 |, | y1-y2 |] trong K.
 e Lấy cái sau (| y1-y2 |).
+ g # Và thêm nó vào giá trị lớn nhất giữa:
        hK - Đầu của K (| x1-x2 |)
          + - Và kết quả của việc thêm:
           eK Kết thúc của K (| y1-y2 |).
             ^ - với kết quả lũy thừa:
              % ssQ_2 Tổng của Q phẳng, modulo -2.
                                        Hiệu suất -1 nếu x1 + x2 + y1 + y2 là số lẻ, 0 nếu không.
                    xxFhCQSIe - bằng kết quả của biểu thức này:
                       hCQ Chuyển Q và lấy đầu (x1, y1).
                     xF Giảm theo XOR bitwise.
                          SIe Và kiểm tra xem danh sách [y1, y2] đã được sắp xếp chưa.
                    x Sau đó, xor kết quả bằng bool (0/1).

1

05AB1E , 16 byte

(x1,x2),(y1,y2)

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

Hãy thử trực tuyến! hoặc Thử bộ kiểm tra! (Sử dụng một phiên bản sửa đổi một chút của mã ( ®thay vì ²), lịch sự của Kevin Cruijssen )


Câu trả lời tốt đẹp! Không phải cái gì để chơi golf, nhưng khi bạn thay đổi ©+®để DŠ+nó dễ dàng hơn để thiết lập một bộ kiểm tra. ;) Đây là bộ thử nghiệm và tất cả các trường hợp thử nghiệm thực sự đang thành công (bỏ qua tiêu đề lộn xộn; p).
Kevin Cruijssen

@KevinCruijssen Tôi đã có phiên bản thay thế, nhưng tôi không thể viết một bộ thử nghiệm ... Cảm ơn, tôi sẽ thêm nó
Ông Xcoder

1
@KevinCruijssen Tôi đã chơi thêm hai byte (rất rõ ràng ...!) Và đã thành công phá vỡ tính tương thích của bộ kiểm tra hơn nữa, vì vậy tôi đã giữ nguyên như vậy: P Cảm ơn vì đã chỉnh sửa.
Ông Xcoder


1

Java 8, 157 190 188 144 142 141 127 byte

(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 byte (157 → 190) do sửa lỗi.
-44 byte (188 → 144) chuyển đổi phương thức đệ quy thành phương thức lặp đơn.
-14 byte nhờ @ceilingcat .

Giải trình:

Hãy thử nó ở đây.

(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
Đề xuất z*z<c*cthay vì(z<0?-z:z)<(c<0?-c:c)
trần

@ceilingcat À, đẹp quá. Cảm ơn!
Kevin Cruijssen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.