Costruisci una scala


26

introduzione

Voglio costruire una scala. Per questo, ho scavato dalla discarica due lunghe assi con buchi e voglio mettere i gradini in questi buchi. Tuttavia, i fori non sono posizionati in modo uniforme, quindi i passaggi saranno un po 'traballanti e trovo difficile stimare la quantità di canna di cui ho bisogno per loro. Il tuo compito è fare i calcoli per me.

Ingresso

L'input è costituito da vettori a due bit, dati come matrici di numeri interi, che rappresentano le due schede. A 0rappresenta un segmento di un aud ( unità arbitraria di distanza ) senza un buco e a 1rappresenta un segmento di un aud con un singolo buco. Le matrici possono avere lunghezze diverse e contenere un numero diverso di 1s, ma non saranno vuote.

Costruirò la mia scala come segue. Innanzitutto, posiziono le due schede esattamente a un aud di distanza e allinea le loro estremità sinistre. Per ogni indice i, misuro la distanza tra il iforo della prima tavola con il iforo della seconda tavola, taglio un pezzo di asta e lo attacco tra i due fori. Mi fermo quando finisco i buchi in una delle assi.

Produzione

Il tuo output è la quantità totale di canna di cui avrò bisogno per i passi, misurata in auds. L'output deve essere corretto per almeno sei cifre significative.

Esempio

Considera gli input [0,1,1,0,1,1,1,1,0,0]e [1,0,0,1,1,1,0,0,1]. La scala risultante si presenta così:

Una scala davvero funky.

La lunghezza totale dell'asta in questa scala è 7.06449510224598auds.

Regole

È possibile scrivere una funzione o un programma completo. Vince il conteggio di byte più basso e non sono consentite scappatoie standard.

Casi test

[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
Per la tua sicurezza, non ti consiglio di salire su una scala simile.
Alex A.

Risposte:



10

J, 22 caratteri

Non ispirato alla risposta di randomra. La I.parte è uguale in quanto è il modo immediatamente ovvio di trovare i buchi.

(4+/@:o.<.&#$-/@,:)&I.
  • I. y- tutti gli indici di yripetuti tutte le volte che l'elemento corrispondente di y. Per inciso, se yè un vettore di booleani, I. ycontiene gli indici a cui si ytrova 1. Ad esempio, i I. 1 0 0 1 1 1 0 0 1rendimenti 0 3 4 5 8.
  • x u&v y- lo stesso di (v x) u (v y). Applicato come x u&I. y, otteniamo (I. x) u (I. y). Continuiamo con l'input trasformato.
  • x <.&# y- minore è la lunghezza di xe y.
  • x -/@,: y- la differenza degli elementi di xe y. Se un vettore è più lungo, viene riempito con zero.
  • x $ y- yrimodellato nella forma specificata da x. In particolare, se xè uno scalare, gli xelementi sono presi da y. In questo utilizzo, x (<.&# $ -/@,:) yassicurarsi che i fori finali siano ignorati.
  • 4 o. y- la funzione %: 1 + *: y, ovvero sqrt (1 + y ²). Per inciso, questa funzione mappa dalla distanza del foro alla lunghezza delle aste.
  • +/ y- la somma degli elementi di 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]))

Questo si è rivelato simile alla soluzione di Mac . Convertire gli elenchi di 0 e 1 in elenchi ordinati degli indici uno, quindi sommare la distanza tra i rispettivi elementi.


2
Ben fatto. Bel trucco con il complesso letterale!
Mac

Sono un po 'triste che questo sia un byte più corto dell'altra mia risposta , che penso sia una soluzione più creativa.
xnor

6

J, 32 28 byte

Il verbo I.restituisce le posizioni di 1s in una stringa binaria che è di grande aiuto.

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

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

Per una soluzione J migliore, controlla la risposta di FUZxxl .


5

R, 67

Usa l'esterno per fare la differenza per i fori indicizzati. Diag restituisce le differenze richieste. Quindi sommare le distanze calcolate

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

Test eseguito in R Fiddle. L'ho avvolto in una stampa per mostrare che il ritorno è conforme alle specifiche.

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

Ben fatto. a==1può essere a>0o !!a.
freekvd

5

Haskell, 77 73 byte

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

Utilizzo: [0,1,0,1] # [1,0,0,1]quali output2.414213562373095

Come funziona: la funzione rrestituisce un elenco delle posizioni dei fori di una scheda, ad es. r [0,1,0,1]-> [2,4]. #comprime due di tali elenchi e lo trasforma in un elenco di distanze tra i fori corrispondenti e infine lo somma.


4

CJam, 36 33 byte

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

Approccio molto ingenuo ... si aspetta l'input come array in stile CJam su STDIN

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

Ecco un cablaggio di prova per tutti gli input di esempio. I risultati nel campo di input vengono utilizzati prima che venga chiamato il codice effettivo. Puoi rimuoverli se non ti fidi di me. ;)

Spiegazione

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

Una soluzione ricorsiva di basso livello e ingenua senza alcuna ricerca nell'elenco.

Gli elenchi di input sono ae b. Se uno dei due è vuoto, ritorna 0.

Altrimenti, lascia xche ysiano i loro primi elementi (il codice in realtà non li assegna perché non puoi svolgere compiti in a lambda, ma renderà più semplice la spiegazione). Se entrambi sono 1, ovvero il loro prodotto è 1, allora contribuiscono alla distanza dell'asta. Teniamo traccia della distanza nel numero complesso i, in modo che la distanza sia il valore assoluto. In realtà, lo calcoliamo indipendentemente, quindi lo moltiplichiamo per x*y.

Quindi, ricerchiamo. L'idea è di spostare entrambe le liste di un passo, a meno che una lista non inizi con uno 0 e l'altra con uno, nel qual caso spostiamo solo la lista 0. In questo modo, gli 1 vengono sempre consumati in coppia. Potremmo verificare queste condizioni con x<ye y<x, ma è più breve sfruttare il confronto delle liste come a[:1]<=b. Infine, regoliamo lo spostamento complesso tra gli elementi correnti di x-y.


Dato che sei sconvolto dal fatto che fosse 1 byte in più rispetto alla tua altra soluzione, ho trovato il modo di salvare un byte. Cambia a>[]<bin a>0<b. Funziona da entrambi []e 0sono falsi, quindi sono equivalenti.
mbomb007,

Inoltre, cos'è a:?
mbomb007,

1
@ mbomb007. Hai fatto qualche test? In python2: ([] > []) != ([] > 0)e in python3 si tratta di un errore (tipi non ordinabili).
ekhumoro,

@ mbomb007. Fa a:parte della sezione [b[:1]<=a:].
ekhumoro,

4

Python, 105 102 100 byte

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

Abbastanza semplice, converte solo gli elenchi di input in elenchi di indici di buche, quindi calcola la distanza tra ogni coppia di tali indici.

Caso di prova:

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

Ringraziamo @FryAmTheEggman per un paio di suggerimenti per il risparmio di byte. Si scopre che questo può essere ulteriormente approfondito, come dimostrato nella risposta di xnor .


Puoi rimuovere gli spazi dopo enumerate(l)e il 0.5(che potrebbe essere solo .5).
FryAmTheEggman

@FryAmTheEggman: assolutamente giusto, grazie! Modificato come suggerito.
Mac

Ho trovato un'altra cosa usando un incarico l=lambda*a:sum(((a-b)**2+1)**.5for a,b in zip(*map(i,a)))
speciale

@FryAmTheEggman: grazie ancora! Sfortunatamente sembra che xnor sia andato ancora meglio - più o meno lo stesso, ma con il primo lambda inserito nel secondo come una comprensione della lista ...
Mac

3

Pyth, 30 byte

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

Provalo online con l'input [0,1,1,0,1,1,1,1,0,0], [1,0,0,1,1,1,0,0,1].

Spiegazione:

A convertire le liste in liste di indici [2, 3, 5, 6, 7, 8]e [1, 4, 5, 6, 9]e comprimili insieme [(2,1), (3,4), (5,5), (6,6), (7,9)]. Quindi sottraggo i valori, li quadrato, aggiungo 1 e somma su tutte le radici quadrate.

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

Peccato che sumnon funziona per liste vuote.


3

Python, 116 115 byte

Questa è una soluzione ricorsiva.

È diventato piuttosto fastidioso quando ho scoperto che index()genera un errore quando non viene trovato alcun valore, ma l'ho fatto funzionare. Sfortunatamente, non posso usare un lambda. Mi ha anche infastidito il fatto che list.remove()non restituisca l'elenco, ma invece ritorni 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)

Esegui online qui: http://repl.it/c5L/2


Anche con le schede, quel codice è 116 byte, non 112.
ekhumoro

Ah, mancavano le righe, grazie.
mbomb007,

3

Clip 3 , 55 47 38

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

Per l'elenco con il minor numero di fori, il programma scorre attraverso di esso e collega ciascun foro con il foro corrispondente dell'altro elenco. Le dimensioni sono calcolate e sommate.

>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

Spiegazione

[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 -.
  `

Se siamo molto liberali riguardo al formato di input, possiamo ridurlo a 36 byte rimuovendo ciascuno di essi k. Ciò richiede che l'input sia una stringa di caratteri caratteri di controllo \0e \1.


3

ECMAScript 6, 86 byte

Inizialmente questo è iniziato con il metodo di riduzione (volevo vedere se si potesse fare in un ciclo invece della risposta @ edc65).

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)

Ma usando @ edc65 per mape &&tper restituire il valore sono stato in grado di accorciarlo un po '.

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

Devo ancora trovare un singolo caso quando ridurre la mappa dei battiti con un accumulatore gestito dall'utente.
edc65,

@ edc65 probabilmente è vero, reduceha più senso semanticamente, ma a parte questo è in realtà un po 'scomodo da usare. Certo, da quando i golfisti del codice si sono preoccupati della semantica.
qw3n

2

Java, 151

Questo cammina semplicemente acercando quelli, poi cammina bquando ne trova uno. Se l' floataccuratezza è accettabile, potrei salvare un paio di byte, ma sono andato d'accordo con doublel'output del test.

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

Con spazi bianchi:

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

Sei cifre significative sono abbastanza accurate, quindi float te lo dà, provaci.
Zgarb,

@Zgarb Le ripetute aggiunte sulla maggior parte degli input mi danno solo cifre di 4-5 cifre, quindi mi atterrò alla versione più accurata. Grazie per il chiarimento, comunque.
Geobits

2

JavaScript (ES6) 108

Il punto principale è la funzione f che mappa gli input 0..1 array in array di posizioni di fori. Quindi le matrici vengono scansionate calcolando una lunghezza totale delle aste usando il teorema di Pitagora. Il |0quasi fine è necessario per convertire NaNs che può risultare quando l'array di driver (il primo) è più lungo del secondo.

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

Test nella console di Firefox / FireBug

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

Leggibile:

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:

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 byte

Utilizza un algoritmo simile alla soluzione J, ma APL ha meno builtin.

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

Esempio di input:

      {+/4○⊃-/{⍵⍴¨⍨⌊/⍴¨⍵}⍵/¨⍳¨⍴¨⍵}(1 0 0 1)(0 1 0 1)
2.414213562
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.