Üçgen Manhattan Mesafe


26

Manhattan mesafe düzenli bir ızgara üzerinde bir diğerinden bir hücre ulaşmak için gereken gereken ortogonal adımları sayısıdır. Ortogonal adımlar, ızgara hücrelerinin kenarlarından geçen köşelerdir (bize, Chebyshev mesafesini verecek olan köşelerin aksine ).

Üçgen ızgara gibi diğer ızgaralar üzerinde benzer bir mesafe tanımlayabiliriz. Her bir hücrenin bir x,yçift içerdiği aşağıdaki indeksleme şemasıyla ızgaradaki ayrı hücreleri ele alabiliriz :

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

Şimdi bu ızgaradaki Manhattan mesafesi, bir hücreden diğerine ulaşmak için yine kenarlardaki en az basamak sayısıdır. Yani gidebileceği 3,1için 2,1, 4,1ya 3,2bu yerine kenarlara göre daha geçiş noktalarında olacağından, fakat başka herhangi bir üçgeni.

Örneğin, mesafe 2,1için 5,2olan 4. En kısa yol genellikle benzersiz değildir ancak mesafeyi 4 adımda gerçekleştirmenin bir yolu:

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

Meydan okuma

İki koordinat çifti göz önüne alındığında ve yukarıdaki adresleme şemasından, aralarındaki Manhattan mesafesini döndürün.x1,y1x2,y2

Her dört girdinin de negatif olmayan tam sayı olduğunu, her birinin 128'den küçük olduğunu varsayabilirsiniz. Bunları istediğiniz sırada ve keyfi olarak gruplandırabilirsiniz (dört ayrı argüman, dört tamsayı listesi, iki tamsayı çifti, 2x2 matris, .. .).

Bir program veya fonksiyon yazabilir ve giriş alma ve çıkış sağlama standart yöntemlerinden herhangi birini kullanabilirsiniz .

Herhangi bir programlama dilini kullanabilirsiniz , ancak bu boşlukların varsayılan olarak yasak olduğunu unutmayın .

Bu , yani en kısa geçerli cevap - bayt cinsinden - kazanır.

Test Kılıfları

Her test durumu olarak verilmiştir .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

Net olumsuz puan alan boşluklar resmi boşluklara dahil edilecek mi?
DavidC

@DavidC Hayır. Loş deliği sorusundan: "[...] +5 veya daha yüksek olan ve cevapların en az iki katı kadar boşluk bulunan topluluğun kabul edilemez olduğu düşünülebilir. "
Martin Ender

Varsayılan olarak 0'dan başlayan beşinci bir girdi alabilir mi (sonuç)? O zaman cevabımı eklemeye gerek kalmayacak (a,b,x,y)->c(a,b,x,y,0)( cdört argüman ve 0beşinci argüman olarak ayrılmış yöntem çağırılarak).
Kevin Cruijssen

3
@KevinCruijssen Üzgünüm. Ek, sabit argümanlar biraz kolayca kötüye kullanılabilir (ve sadece 0 özel bir durum olarak izin vermek garip görünüyor).
Martin Ender,

@MartinEnder Tamam, öyle düşündüm, ama sormaktan asla zarar veremez. Bu durumda benim 190 baytlık cevabım kaldı. Bir yıl önce yarıya kadar cevap vermeme rağmen, bir test davası başarısız oldu. Hemen şimdi soruya rastladım ve cevabımdaki hatayı düzelttim.
Kevin Cruijssen

Yanıtlar:


7

JavaScript (ES6), 84 78 bayt

Neil sayesinde 6 bayt kaydedildi

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

Test durumları

İlk özyinelemeli çözüm, 100 88 81

ETHproductions sayesinde 12 bayt
kaydedildi Neil sayesinde 7 bayt kaydedildi

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

Nasıl çalışır

Her ne kadar esas olarak şu anki sürüm için geçerli olsa da, aşağıdaki açıklama daha spesifik olarak ilk versiyon için geçerlidir:

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)

Going (x0, y) ile (x1, y) , hedef bir kaynak üçgenden yanal kenarları tüm yol boyunca gidebilir, çünkü basittir. Bu durumda Manhattan mesafesi | x0 - x1 | .

Zor kısım dikey adımlar. Y0 satırından y1 satırına gitmek için bu iki parametreyi hesaba katmamız gerekir:

  • Geçerli üçgenin yönü
  • İster y0 az veya daha fazla olan y1

Bir üçgenin yönlendirmesi x + y'nin paritesi ile verilir :

  • eğer eşitse, üçgen yukarı dönük
  • garipse, üçgen aşağıya bakıyor

Yukarı dönük bir üçgenden aşağı doğru ( y0 <y1 olduğunda yararlı ) ve aşağı dönük bir üçgenden yukarı doğru ( y0> y1 olduğunda yararlı) gidebiliriz .

Üçgenin yönünü y0 ve y1 arasındaki karşılaştırmayla birleştirerek, istenen yöne gidebilirsek ve olmasa bile tuhaf bir sonucu olan x + y0 + (y0> y1? 1: 0) formülünü elde ederiz.

Bir sonraki satıra doğrudan erişemezsek, önce x'i güncelleyerek doğru bir hizalama yapmamız gerekir :

  • eğer x henüz x1'e eşit değilse , kesinlikle doğru yöne hareket etmek istiyoruz, bu nedenle x , x1'den küçükse onu artırırız ve x , x1'den büyükse onu azaltırız
  • eğer x zaten eşittir x1 , biz ya artışı olabilir veya eksiltme

Test durumları


Bu ... çok çok küçük matematiksel işlemler ... Fakat ndeğişkeni tamamen atlayıp her yinelemenin sonucuna 1 ekleyemez misiniz? ( 90 karakter sanırım)
ETHproductions

@ETHproductions Dürüst olmak gerekirse, herhangi bir ciddi golf olmadan yayınladım. Ama bu kesinlikle yapılacak ilk şey. Teşekkürler!
Arnauld,

1
Ayrıca, operatörün önceliğinin 2 bayttan tasarruf etmek için yapabileceğiniz anlamına geldiğini düşünüyorum&a+b+(b>d)&1
ETHproductions

81'e indirdim, sanırım: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

Akıllıca bir kurutma kullanarak başka bir baytı kurtarmanın mümkün olabileceğini düşünüyorum.
Neil

5

Python 2,74 bayt

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
Eğer, bu bölümü lütfen açıklayabilir: **(x^y^(Y>=y))?
Dead Possum

1
@DeadPossum 1 mesafeye dikey olarak hareket etmek 1 veya 3 hareket alabilir; sadece paritelere bakarak söylemenin bir yolu yok bu yüzden y değerlerini karşılaştırmanız gerekiyor.
feersum

2

Toplu, 99 bayt

@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

Açıklama: Sadece yatay bir hareket, mutlak x-koordinat farkını basitçe alır. Yeterince büyük x için, dikey hareket mutlak y-koordinat farkı başına yalnızca bir ekstra adım alır; Bu fark başına iki adım artı bir düzeltme faktörü olarak hesaplanır. Düzeltilmiş iki adımın büyüklüğü ve mutlak farkların toplamı daha sonra sonuçtur, ancak bu, düzeltilmiş mutlak y-koordinat farkının ve düzeltilmemiş mutlak y-koordinat farkına eklenen mutlak x-koordinat mesafesinin daha büyük olması olarak hesaplanır. .

  • @cmd/cset/a" - Virgülle ayrılmış ifadeleri değerlendirir ve sonuncuyu yazdırır
  • x=%3-%1,x*=x>>31|1x=|x2x1|
  • y=%4-%2,w=y>>31,y*=w|1w=y1>y2y=|y2-y1|
  • z=x+(y+x&1)*(-(%1+%2+w&1)|1)-yc=(y+(xşık2))(1-2((x1+y1+w)şık2)),z=x+c-y
  • z*=z>>31,x+y+z hesaplarmbirx(x,y-c)+y=x+y-mbenn(0,x+c-y)

2

Jöle , 24 bayt

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

Çevrimiçi deneyin!

(x,y),(X,Y)

d=|y-Y|+maksimum(|x-X|,|y-Y|+((x+y+X+Y)şık-2)xy(Yy))=|y-Y|+maksimum(|x-X|,|y-Y|+[-(|x-X|+|y-Y|şık2)]x+y+(Yy))=maksimum(|x-X|+|y-Y|,2|y-Y|+[-(|x-X|+|y-Y|şık2)](Yy)+x+y).

¢=(Yy)+x+y

L=[|x-X|,|y-Y|]toplam(L)f(L)f

L=[bir,b]-((bir+b)şık2)¢2b


2

raket / şema, 214 bayt

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

(x1,x2),(y1,y2)

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

Çevrimiçi deneyin!

Yıkmak

© İÖO (İYİ) {Q + m + M® + Tam program. Değerlendirilen girişi temsil ediyorum.
ÆÄ Çiftleri çıkartarak azaltın, mutlak değerleri alın.
  `© Onları ayrı ayrı istifin üzerine koyun ve ikinciyi saklayın
                            bir, | y1-y2 | C kaydında
    ÇOK Yassılaştırılmış girişin toplamını yığının üzerine itin.
       É (Eşliğini alın ve olumsuzlayın.
         Øн [x1, y1] düğmesine basın.
            O x1 + y1 al (toplamı).
             IθD {Q Sonra ikinci çiftin sıralanıp sıralanmadığını kontrol edin (y1 ≤ y2).
                  + Ve bunu x1 + y1 ile toplayın.
                   m Üstat. Eşliği sonucun üzerine ** getirin.
                    + Ve buna ikinci mutlak farkı ekleyin.
                     M® + Sonuç olarak, yığındaki en büyük sayıyı itin
                            artı C kaydında saklanan değer

Ben emin% 100 değilim ama değiştiremediğiniz ©için Dve kaldırmak ®? Halen TIO'nuzdaki dava için çalışıyor gibi görünüyor, ancak her dava için aynı yolu takip edip etmediğinden emin değilim.
Kevin Cruijssen

1
@KevinCruijssen EDIT : Hayır, çünkü Mdavranışları bundan etkilenir. İçin başarısız [[0, 127], [0, 0]].
Bay Xcoder

2

Python 2 , 74 72 71 bayt

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

Çevrimiçi deneyin! Link, test durumlarını içerir. Düzenleme: @JoKing sayesinde 2 bayt kaydedildi. @ Mr.Xcoder sayesinde başka bir bayt kaydedildi. Aşağıdaki formüle dayanarak bu soruda buldum :

|birben-bben|+|(birben-birj2)-(bben-bj2)|+|birj+12-bj+12|

12090

|birben-bben|+|(birben-birj+12)-(bben-bj+12)|+|birj2-bj2|

-birj+12=-birj2



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 bayt kaydetmelisiniz.
Bay Xcoder

1

Pyth , 31 28 bayt

(x1,x2),(y1,y2)

+eKaMQg#hK+eK^%ssQ_2+shCQSIe

Burada dene! veya Test takımını deneyin!

Yıkmak

+ eKaMQg # hK + eK ^% ssQ_2xxFhCQSIe Tam program. Q = eval (input ()).
  KaMQ K'daki [| x1-x2 |, | y1-y2 |] farklarını saklayın
 e İkincisini alın (| y1-y2 |).
+ g # Ve aşağıdakiler arasındaki en yüksek değere ekleyin:
        hK - K başkanı (| x1-x2 |)
          + - Ve ekleme sonucu:
           eK K'nın sonu (| y1-y2 |).
             ^ - üstelleştirmenin sonucu:
              % ssQ_2 Düzleştirilmiş Q'nun toplamı, modulo -2.
                                        X1 + x2 + y1 + y2'nin tek olması durumunda verim -1, aksi takdirde 0 olur.
                    xxFhCQSIe - bu ifadenin sonucu:
                       hCQ Q devri ve kafayı alın (x1, y1).
                     xF Bit yönünde XOR ile azaltın.
                          SIe Ve [y1, y2] listesinin sıralanıp sıralanmadığını kontrol edin.
                    x Bundan sonra, sonucu bool (0/1) ile ayarlayın.

1

05AB1E , 16 bayt

(x1,x2),(y1,y2)

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

Çevrimiçi deneyin! veya Test takımını deneyin! (Kodun biraz değiştirilmiş bir versiyonunu kullanır ( ®yerine ²), Kevin Cruijssen )


Güzel cevap! Değil golf şey, ancak değiştirme zaman ©+®için DŠ+bir test takımı kurmak daha kolaydır. ;) İşte test paketi ve tüm test durumları gerçekten başarılı oluyor (dağınık başlığı yok sayın; p).
Kevin Cruijssen

@KevinCruijssen Alternatif bir sürümü olarak kullandım, ancak bir test paketi yazabileceğim aklıma gelmedi ... Teşekkürler, ekleyeceğim
Bay Xcoder

1
@KevinCruijssen İki tane daha (çok açık ...!) Bayt kapalı kaldım ve test paketi uyumluluğunu daha da bozmayı başardım, bu yüzden olduğu gibi tuttum: P Bu arada, düzenleme için teşekkürler.
Bay Xcoder


1

Java 8, 157 190 188 144 142 141 127 bayt

(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;}

Hata düzeltme nedeniyle +33 bayt (157 → 190).
Özyinelemeli yöntemi tek bir döngü yöntemine dönüştüren -44 bayt (188 → 144). @Ceilingcat
sayesinde -14 bayt .

Açıklama:

Burada dene.

(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
Öner z*z<c*cyerine(z<0?-z:z)<(c<0?-c:c)
ceilingcat

@ceilingcat Ah, güzel olan. Teşekkürler!
Kevin Cruijssen
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.