Bir merdiven inşa


26

Giriş

Bir merdiven inşa etmek istiyorum. Bunun için hurdalıktan iki adet uzun tahtadan delikler açılmış ve adımları bu deliklere yerleştirmek istiyorum. Ancak, delikler düzgün bir şekilde yerleştirilmemiştir, bu nedenle adımlar biraz riskli olacaktır ve onlar için ihtiyaç duyduğum çubuk miktarını tahmin etmekte zorlanıyorum. Senin işin benim için hesaplamaları yapmak.

Giriş

Girişiniz, iki kartı temsil eden tamsayılar dizisi olarak verilen iki bitlik vektörlerdir. A , bir deliksiz 0bir aud parçasını ( isteğe bağlı bir mesafe birimi ) 1temsil eder ve a, tek bir delikli bir aud parçasını temsil eder. Diziler farklı uzunluklarda olabilir ve farklı sayıda 1s içerebilir , ancak boş olmayacaktır.

Merdivenimi şu şekilde inşa edeceğim. İlk önce, iki tahtayı tam olarak birer aralık ayırın ve sol uçlarını hizaladım. Her endeks için i, ibirinci panelin iinci deliği ile ikinci panelin delik deliği arasındaki mesafeyi ölçüyorum, bir parça çubuk kesiyorum ve iki deliğin arasına tutturuyorum. Bir keresinde tahtalardan birinde delikler bitince duruyorum.

Çıktı

Çıktınız, auds cinsinden ölçülen adımlar için ihtiyaç duyacağım toplam çubuk miktarıdır. Çıktı en az altı önemli hane için doğru olmalıdır.

Örnek

Girişleri [0,1,1,0,1,1,1,1,0,0]ve [1,0,0,1,1,1,0,0,1]. Ortaya çıkan merdiven şöyle görünür:

Gerçekten korkak bir merdiven.

Çubuğun bu merdiven içindeki toplam uzunluğu 7.06449510224598aud'dur.

kurallar

Bir işlev veya tam bir program yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklar izin verilmez.

Test Kılıfları

[0] [0] -> 0.0
[0] [1,0] -> 0.0
[1,0,0] [1,1,1,1,1] -> 1.0
[0,1,0,1] [1,0,0,1] -> 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] -> 7.06449510224598
[1,1,1,1,1] [0,0,1,1,0,1,0,0,1] -> 12.733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1] -> 20.38177416534678

32
Kendi güvenliğiniz için, buna benzeyen herhangi bir merdivene tırmanmanızı önermiyorum.
Alex A.

Yanıtlar:



10

J, 22 karakter

Randomranın cevabından ilham alınmadı. I.Bu delikler bulma hemen açık bir şekilde olduğu gibi parçası eşittir.

(4+/@:o.<.&#$-/@,:)&I.
  • I. y- Tüm indeksleri ykarşılık gelen madde kadar sık ​​tekrarlanır y. Arada, eğer yBoolean bir vektördür, I. yhangi endeksleri içeren ybir 1. Örneğin, I. 1 0 0 1 1 1 0 0 1verim 0 3 4 5 8.
  • x u&v y- aynı (v x) u (v y). Olarak uygulanan x u&I. y, biz olsun (I. x) u (I. y). Dönüştürülmüş girdi ile devam edelim.
  • x <.&# y- uzunluklarının daha küçük xve y.
  • x -/@,: y- ait öğelerin farkı xve y. Bir vektör daha uzunsa, sıfırlarla doldurulur.
  • x $ y - y tarafından belirtilen şekle yeniden şekillendirildi x. Spesifik olarak, eğer xbir skaler ise, xelemanlar alınır y. Bu kullanımda, x (<.&# $ -/@,:) ytakip deliklerinin göz ardı edilmesini sağlar.
  • 4 o. y- fonksiyon %: 1 + *: y, yani sqrt (1 + y ²). Bu arada, bu işlev delik mesafesinden çubukların uzunluğuna eşler.
  • +/ y- elemanlarının toplamı y.

10

Python, 85

lambda*A:sum(abs(x-y+1j)for x,y in zip(*[[i for i,x in enumerate(l)if x]for l in A]))

Bu Mac'in çözümüne benzer oldu . 0 ve 1'lerin listelerini bir dizinlerin sıralı listelerine dönüştürün ve ardından ilgili öğeler arasındaki mesafeyi toplayın.


2
Güzel bitti. Karmaşık hazır bilgi ile güzel hile!
Mac

Bunun , bence daha yaratıcı bir çözüm olduğunu düşündüğüm diğer cevabımdan bir bayt kısa olduğu için üzgünüm .
xnor

6

J, 32 28 bayt

Fiil s'nin I.pozisyonlarını 1büyük bir yardım olan ikili bir dizgede döndürür .

   +/@,@(=/&(#\)*[:>:&.*:-/)&I.

   0 1 0 1 (+/@,@(=/&(#\)*[:>:&.*:-/)&I.) 1 0 0 1
2.41421

Daha iyi bir J çözümü için FUZxxl'in cevabını kontrol edin .


5

R, 67

Dizinlenmiş delikler için bir fark yapmak için dış kullanır. Diag gerekli farkları verir. Ardından hesaplanan mesafeleri toplayın

function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5)

R Fiddle'da deneme çalıştırması . İadenin spec ile uyumlu olduğunu göstermek için bir baskıya sardım.

> print((function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5))(c(0,1,1,0,1,1,1,1,0,0),c(1,0,0,1,1,1,0,0,1)),digits=10)
[1] 7.064495102
> print((function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5))(c(1,1,1,1,1),c(0,0,1,1,0,1,0,0,1)),digits=10)
[1] 12.73343313
>

Güzel bir. a==1olabilir a>0veya !!a.
freekvd

5

Haskell, 77 73 bayt

r x=[a|(a,1)<-zip[1..]x]
i#j=sum$zipWith(\n m->sqrt((n-m)**2+1))(r i)$r j

Kullanım: [0,1,0,1] # [1,0,0,1]hangi çıktılar2.414213562373095

Nasıl çalışır: fonksiyon rbir tahtanın deliklerinin konumlarının bir listesini döndürür, örneğin r [0,1,0,1]-> [2,4]. #bu listelerden ikisini sıkıştırır ve karşılık gelen delikler arasındaki mesafeler listesine dönüştürür ve sonunda toplar.


4

CJam, 36 33 bayt

l~]{:L,{L=},}%z{,(},0\{~-_*)mq+}/

Çok saf bir yaklaşım ... girişi STDIN'de CJam tarzı diziler olarak bekliyor

[0 1 1 0 1 1 1 1 0 0] [1 0 0 1 1 1 0 0 1]

İşte bir test koşumTüm örnek girişler için . Giriş alanındaki sonuçlar gerçek kod çağrılmadan önce kullanılır. Bana güvenmiyorsan onları kaldırabilirsin. ;)

açıklama

l~]                               "Read and eval input, wrap in an array.";
   {        }%                    "Map this block onto both input arrays.";
    :L,                           "Store array in L, get its length N.";
       {L=},                      "In the range [0 .. N-1] get all elements where L is 1.";
                                  "At this point we've converted each array into a list of its
                                   non-zero indices.";
              z                   "Transpose the array, pairing up indices at the same position.";
               {,(},              "Filter the extraneous elements of the longer input.";
                    0\            "Put a 0 before the array.";
                      {        }/ "For each pair of holes...";
                       ~-         "Unwrap the pair, take the difference.";
                         _*)mq    "Square, increment, square root.";
                              +   "Add to the running total.";

4

Python, 86

f=lambda a,b,i=1j:a>[]<b and a[0]*b[0]*abs(i)+f(a[a[:1]<=b:],b[b[:1]<=a:],i+a[0]-b[0])

Herhangi bir liste araması yapmadan düşük seviyeli ve saf özyinelemeli bir çözüm.

Giriş listeleri ave b. İkisinden biri boşsa, geri dönün 0.

Aksi halde, ilk unsurları olsun xve olsun y(kod aslında bunları atamaz çünkü a lambda. Her ikisi de 1 ise, yani ürünleri 1 ise, çubuk mesafesine katkıda bulunurlar. Karmaşık sayıdaki mesafeyi takip ediyoruz i, böylece mesafe mutlak değerdir. Aslında, ne olursa olsun hesaplıyoruz, sonra çarpıyoruz.x*y .

Sonra tekrarlarız. Buradaki fikir, bir liste 0 ile diğeri bir diğeriyle başlamadıkça her iki listeyi de kaydırmaktır, bu durumda sadece 0 listesini değiştiririz. Bu şekilde, 1'ler her zaman çiftler halinde tüketilir. Bu koşulları x<yve ile kontrol edebiliriz y<x, ancak listenin karşılaştırılmasından yararlanmak daha kısadır a[:1]<=b. Son olarak, şu anki elemanlar arasındaki karmaşık yer değiştirmeyi ayarladık x-y.


Bunun, diğer çözümünüzden 1 byte daha fazla olduğu için üzüldüğünüzden, bir baytı kurtarmanın bir yolunu buldum. Değişim a>[]<biçin a>0<b. Her ikisinden de işe yarar []ve 0sahtedirler, bu yüzden eşdeğerdirler.
mbomb007

Ayrıca, nedir a:?
mbomb007

1
@ mbomb007. Herhangi bir test yaptınız mı? Python2'de: ([] > []) != ([] > 0)ve python3'te bir hatadır (düzeltilemez türler).
ekhumoro

@ mbomb007. Dilimin a:bir parçasıdır [b[:1]<=a:].
ekhumoro

4

Python, 105 102 100 bayt

i=lambda l:(i for i,h in enumerate(l)if h)
l=lambda*a:sum(((a-b)**2+1)**.5for a,b in zip(*map(i,a)))

Oldukça basit, sadece giriş listelerini delik indeks listelerine dönüştürür, ardından bu indekslerin her çifti arasındaki mesafeyi hesaplar.

Test durumu:

>>> print l([0,1,1,0,1,1,1,1,0,0], [1,0,0,1,1,1,0,0,1])
7.06449510225

Birkaç bayt tasarruf önerisi için @FryAmTheEggman'e teşekkür ederiz. Gösterildiği gibi bu dışarı Dönüşler, ayrıca golfed edilebilir XNOR cevabı .


Boşlukları ard arda kaldırabilirsiniz enumerate(l)ve 0.5(sadece 5 olabilir).
FryAmTheEggman

@FryAmTheEggman: kesinlikle doğru, teşekkürler! Önerildiği gibi değiştirildi.
Mac

Yıldızlı ödevi kullanan başka bir şey l=lambda*a:sum(((a-b)**2+1)**.5for a,b in zip(*map(i,a)))
buldum

@FryAmTheEggman: tekrar teşekkürler! Ne yazık ki xnor daha iyi bir şekilde gitti - görünüşe göre aynı, ancak ilk lambda listenin kavranması olarak ikinciye yuvarlandı ...
Mac

3

Pyth, 30 bayt

s+0m^h^-hded2 .5CmfTm*hb@kblkQ

Deneyin çevrimiçi girişli [0,1,1,0,1,1,1,1,0,0], [1,0,0,1,1,1,0,0,1].

Açıklama:

Ben endeksleri listeler halinde listeleri dönüştürmek [2, 3, 5, 6, 7, 8]ve [1, 4, 5, 6, 9]ve onları bir arada zip [(2,1), (3,4), (5,5), (6,6), (7,9)]. Sonra değerleri çıkarıp karelerim, 1 eklerim ve tüm kareköklerin üzerine toplarım.

CmfTm*hb@kblkQ
 m           Q     map each list k in input() to the following list:
    m      lk         map each value b of [0, 1, 2, ..., len(k)-1] to the value:
     *hb@kb              (b + 1) * k[b]
  fT                  filter the list for positive values
C                  zip these two resulting lists

s+0m^h^-hded2 .5...
   m            ...  map each pair of values d to: 
    ^h^-hded2 .5         ((d[0] - d[1])^2 + 1)^0.5
 +0                  insert 0 at the front of the list
s                    sum

sumBoş listeler için işe yaramazsa ayıp .


3

Python, 116 115 bayt

Bu özyinelemeli bir çözümdür.

index()Hiçbir değer bulunmadığında sadece bir hata attığını bulduğumda can sıkıcı bir hal aldı , ancak çalışmasını sağladım. Ne yazık ki, bir lambda kullanamam. Ayrıca list.remove()listeyi geri getirmeyen , aksine geri dönen beni rahatsız etti None.

def f(x,y,r=0):
    try:i,j=x.index(1),y.index(1)
    except:return r
    x.pop(i);y.pop(j);return f(x,y,r+((i-j)**2+1)**.5)

Burada çevrimiçi çalıştırın: http://repl.it/c5L/2


Sekmelerde bile, bu kod 112 bayt değil, 116.
ekhumoro

Ah, yeni hatları kaçırdım, teşekkürler.
mbomb007

3

Klips 3 , 55 47 38

[cr+`j[v[w#)#mvw2B}}(c)c]sl`{%ky1%kx1`

Daha az sayıda delik içeren liste için, program bunun içinde yinelenir ve her bir deliği diğer listenin karşılık gelen deliğine bağlar. Boyutlar hesaplanır ve toplanır.

>java -jar Clip3.jar ladder.clip
{0,1,1,0,1,1,1,1,0,0}
{1,0,0,1,1,1,0,0,1}
7.064495102245980096000721459859050810337066650390625

açıklama

[c          .- Assign c to the lists, in order of size    -.
  r+`       .- The sum of...                              -.
   j[v[w    .- Join the lists with a function on v, w     -.
     #      .- Square root                                -.
      )     .- 1 plus                                     -.
       #    .- The square of                              -.
        mvw .- The distance between v and w               -.
       2
     B      .- (one-half, so #...B means square root)     -.
   }}(c)c   .- Apply joining function to the lists        -.
  ]sl`{     .- c is the (sorted by size) list of...       -.
    %ky1    .- Indices of y (the second input) which are 1-.
    %kx1    .- Indices of x (the first input) which are 1 -.
  `

Girdi formatı konusunda çok özgürsek, her birini kaldırarak bunu 36 bayta indirebiliriz k. Bu, girişin kontrol karakterleri karakterlerinden oluşan bir dize olmasını gerektirir \0ve \1.


3

ECMAScript 6, 86 bayt

Bu başlangıçta indirgemeyle başladı (@ edc65 cevabının aksine tek bir döngüde yapılıp yapılamayacağını görmek istedim).

f=(c,b,a=[0,...c],j)=>a.reduce((c,v,i)=>c+=v&&(j=b.indexOf(1,j)+1,v=i-j,j)?Math.sqrt(1+v*v):0)

Ancak @ edc65 değerini kullanarak mapve &&tdeğerini döndürmek, onu biraz kısaltmayı başardı.

f=(a,b,j,c=0)=>a.map((v,i)=>c+=v&&(j=b.indexOf(1,j)+1,v=i+1-j,j)&&Math.sqrt(1+v*v))&&c

f=(a,b,j,c=0)        //variables note the j can be undefined
=>a.map((v,i)=>      //loop through the first array
c+=                  //add 
v&&                  //test to see if we have a hole
(j=b.indexOf(1,j)+1, //if so see if there is a whole on the other board
v=i+1-j,             //calculate index difference
j)                   //the last var gets evaluated so check to see if indexOf returned -1
&&Math.sqrt(1+v*v))  //calculate 
&&c                  //return sum

Bir kullanıcı tarafından yönetilen akümülatör ile atım haritasını düşürürken tek bir vaka bulmam gerekiyor.
edc65

@ edc65 muhtemelen doğrudur, reduceanlamsal olarak daha anlamlıdır, ancak bunun dışında kullanımı biraz gariptir. Tabii ki, kod golfçüler ne zamandan beri anlambilimden endişe ediyorlar.
qw3n

2

Java, 151

Bu sadece bir tane aarayarak yürür , sonra bbir tane bulursa yürür . Eğer floatdoğruluk kabul edilebilir bir kaç bayt kurtarabilecek ama gitti doubletesti çıktı maç.

double d(int[]a,int[]b){double z=0;for(int x=-1,y=0,d=b.length;x++<a.length&y<d;z+=a[x]>0?Math.sqrt((y-x)*(y++-x)+1):0)for(;y<d&&b[y]<1;y++);return z;}

Boşluk ile:

double d(int[]a,int[]b){
    double z=0;
    for(int x=-1,y=0,d=b.length;
            x++<a.length&y<d;
            z+=a[x]>0?Math.sqrt((y-x)*(y++-x)+1):0)
        for(;y<d&&b[y]<1;y++);
    return z;
}

Altı önemli basamak yeterli doğruluktur, bu yüzden yüzer size verir, onun için gidin.
Zgarb

@Zgarb Çoğu girdideki tekrarlanan eklemeler sadece bana 4-5 basamak verir, bu yüzden daha doğru versiyona sadık kalacağım. Açıklama için teşekkürler.
Geobits

2

JavaScript (ES6) 108

Ana nokta, 0..1 girişini delik konumlarındaki dizilerde eşleyen f işlevidir. Ardından diziler, pisagor teoremi kullanılarak toplam çubuk uzunluğu hesaplanarak taranır. |0Ucu yakınında sürücü dizi (ilk) ikinci daha uzun olduğunda meydana gelebilir dönüştürmek NaN'ler için gereklidir.

F=(a,b,f=a=>a.map(v=>++u*v,u=0).filter(x=>x))=>
  f(a,b=f(b)).map((v,i)=>t+=Math.sqrt((w=b[i]-v)*w+1|0),t=0)&&t

Firefox / FireBug konsolunda test edin

;[[[0],[0]]
 ,[[0],[1,0]]
 ,[[1,0,0],[1,1,1,1,1]]
 ,[[0,1,0,1],[1,0,0,1]]
 ,[[0,1,1,0,1,1,1,1,0,0],[1,0,0,1,1,1,0,0,1]]
 ,[[1,1,1,1,1],[0,0,1,1,0,1,0,0,1]]
 ,[[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0],[0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1]]]
.forEach(v=>console.log('['+v[0]+']','['+v[1]+']',F(...v)))

[0] [0] 0
[0] [1,0] 0
[1,0,0] [1,1,1,1,1] 1
[0,1,0,1] [1,0,0 , 1] 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] 7.06449510224598
[1,1, 1,1,1] [0,0,1,1,0,1,0,0,1] 12.733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1 , 1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0, 0,1,1,0,1,1,0,0,0,1] 20.38177416534678



0

Perl 98

sub l{$r=0;@a=grep$a->[$_],0..$#$a;@b=grep$b->[$_],0..$#$b;$r+=sqrt 1+(shift(@a)-shift@b)**2 while@a&&@b;$r}

Okunabilir:

sub l {
    $r = 0;
    @a = grep $a->[$_], 0 .. $#$a;
    @b = grep $b->[$_], 0 .. $#$b;
    $r += sqrt 1 + (shift(@a) - shift @b) ** 2 while @a && @b;
    $r
}

Test yapmak:

use Test::More;
for (<DATA>) {
    my ($A, $B, $r) = /\[ ([0-9,]+) \] \s \[ ([0-9,]+) \] \s -> \s ([0-9.]+) /x;
    $a = [split /,/, $A];
    $b = [split /,/, $B];
    cmp_ok l(), '==', $r, "test $_";
}
done_testing($.);
__DATA__
[0] [0] -> 0.0
[0] [1,0] -> 0.0
[1,0,0] [1,1,1,1,1] -> 1.0
[0,1,0,1] [1,0,0,1] -> 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] -> 7.06449510224598
[1,1,1,1,1] [0,0,1,1,0,1,0,0,1] -> 12.733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1] -> 20.38177416534678

0

APL, 35 28 bayt

J çözümüne benzer bir algoritma kullanır, ancak APL'nin daha az yerleşik yapısı vardır.

{+/4○⊃-/{⍵⍴¨⍨⌊/⍴¨⍵}⍵/¨⍳¨⍴¨⍵}

Örnek giriş:

      {+/4○⊃-/{⍵⍴¨⍨⌊/⍴¨⍵}⍵/¨⍳¨⍴¨⍵}(1 0 0 1)(0 1 0 1)
2.414213562
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.