Conta le verità finali


59

Ispirato e in ricordo del mio caro amico e collega,

Dan Baronet

Dan Baronet , 1956-2016. RIP

Ha trovato la soluzione APL più breve possibile per questo compito:

Compito

Dato un elenco booleano, conta il numero di valori di verità finali.

Casi di esempio

{}0

{0}0

{1}1

{0, 1, 1, 0, 0}0

{1, 1, 1, 0, 1}1

{1, 1, 0, 1, 1}2

{0, 0, 1, 1, 1}3

{1, 1, 1, 1, 1, 1}6


Possiamo prendere la lista come una stringa di zeri e uno? ad es 01100.
Adnan,

@Adnan solo se questo è il modo più normale per la tua lingua di rappresentare elenchi booleani.
Adám,

71
Mi dispiace per la tua perdita.
Martin Ender,

6
@MartinEnder Grazie. Sarà difficile andare avanti. Dan mi ha insegnato tutto quello che dovevo sapere per lavorare per Dyalog.
Adám,

5
Addio a Dan. RIP ...
Erik the Outgolfer

Risposte:


36

Dyalog APL, 6 2 byte

⊥⍨

Provalo su TryAPL .

Come funziona

(uptack, dyadic: decode) esegue la conversione di base. Se l'operando di sinistra è un vettore, esegue una conversione di base mista , il che è perfetto per questa attività.

Per un vettore di base b = b n , ⋯, b 0 e una cifra vettore a = a n , ⋯, a 0 , b ⊥ un converte un alla base mista b , cioè, calcola b 0 ⋯ b n-1 un n + ⋯ + b 0 b 1 a 2 + b 0 a 1 + a 0 .

Ora, (tilde dieresis, commute) modifica l'operatore a sinistra come segue. In un contesto monadico, chiama l'operatore con gli stessi argomenti sinistro e destro.

Ad esempio, ⊥⍨ a è definito come ⊥ a , che calcola uno 0 ⋯ a n + ⋯ + a 0 a 1 a 2 + a 0 a 1 + a 0 , la somma di tutti i prodotti cumulativi da destra a sinistra .

Per k trailing, i k prodotti più a destra sono 1 e tutti gli altri sono 0 , quindi la loro somma è uguale a k .


14
Suggerimento: Dan lo ha fatto in soli due byte.
Adám,

3
Conversione base mista! È intelligente.
Dennis,

1
Oh. Conversione base mista, come colpisce di nuovo.
Conor O'Brien,

Bravo! Infatti, a causa di Dan, abbiamo speciali carter b⊥be ⊥⍨brinunciando a infinite velocità-up.
Adám,

19

JavaScript (ES6), 21 byte

f=l=>l.pop()?f(l)+1:0

Casi test


Come funziona? Come f(l)+1restituisce un valore > 2?
Oliver

@Oliver Questo è un processo ricorsivo, valutato come l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0.
Arnauld,

Vedo. Grazie per la spiegazione.
Oliver,

11

Gelatina , 4 byte

ŒrṪP

Provalo online! oppure Verifica tutti i casi di test.

Nel caso in cui l'elenco sia vuoto, ci sono alcune curiose osservazioni. Innanzitutto, la codifica per lunghezza dell'elenco vuoto []restituisce un altro elenco vuoto []. Quindi riprendendo l'ultimo elemento da quello usando tail restituisce 0invece di una coppia [value, count]che sono gli elementi regolari di una matrice codificata di lunghezza. Quindi, quando richiesto, il prodotto Prestituisce il risultato atteso.00

Spiegazione

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together

In alternativa, ŒgṪSfunziona anche!
Lynn,

Fornisce l'output giusto per l'elenco vuoto come input, ma sono sorpreso vista la dissezione. Ti dispiacerebbe camminare attraverso quel caso speciale?
Peter Taylor,

@PeterTaylor Sono anche sorpreso che abbia funzionato. Inoltre, ho appena notato che il primo link ha il codice sbagliato.
miglia

@PeterTaylor in Jelly è implementato come: lambda z: iterable(z).pop() if iterable(z) else 0. iterablequando viene chiamato in un elenco restituisce semplicemente l'elenco e l'elenco vuoto è ovviamente errato.
FryAmTheEggman,

10

Brachylog , 7 6 5 byte

@]#=+

Provalo online!

Spiegazione

@]        A suffix of the Input...
  #=      ...whose elements are all equal
    +     Sum its elements

Dal momento che @] - Suffixinizia dal suffisso più grande fino al più piccolo, troverà prima la corsa più lunga.


10

CJam (8 byte)

{W%0+0#}

Suite di test online

Dissezione

{    e# begin a block
  W%  e# reverse the array
  0+  e# append 0 so there's something to find
  0#  e# find index of first 0, which is number of nonzeros before it
}

10

Haskell, 26 25 byte

a%b|b=1+a|0<3=0
foldl(%)0

Uso:

Prelude> foldl(%)0 [True,False,True,True]
2

Versione senza punti (26 byte):

length.fst.span id.reverse

Utilizzando un elenco intero anziché un elenco bool (21 byte, grazie a Christian Sievers):

a%b=b*(a+1)
foldl(%)0

Uso:

Prelude> foldl(%)0 [1,0,1,1]
2

Versione senza punti (25 byte)

sum.fst.span(==1).reverse

Per gli elenchi di numeri interi l' foldlidea funziona cona%b=b*(a+1)
Christian Sievers il

9

Retina , 7 5 byte

r`1\G

Provalo online! (La prima riga abilita una suite di test separata da avanzamento riga.)

La definizione del formato di input per Retina non è del tutto inequivocabile. Poiché Retina non ha alcun concetto di alcun tipo tranne le stringhe (e anche nessun valore che può essere usato per la nostra solita definizione di verità e falsità), di solito uso 0e 1(o qualcosa di positivo in generale) per corrispondere a verità e falsità, in quanto rappresentano zero o alcune corrispondenze, rispettivamente.

Con le rappresentazioni a carattere singolo, inoltre, non abbiamo bisogno di un separatore per l'elenco (che in un certo senso è più la rappresentazione dell'elenco più naturale per una lingua che ha solo stringhe). Adám ha confermato che si tratta di un formato di input accettabile.

Per quanto riguarda la regex stessa, si abbina da rdestra a sinistra e \Gancora ogni partita alla precedente. Quindi, questo conta quanti 1s possiamo abbinare dalla fine della stringa.


"Sì, per Retina, trattandosi solo di stringhe, penso che una stringa" 01 "o" FT "sia in ordine.
Adám,

9

05AB1E , 12 10 6 5 byte

Salvato 1 byte grazie al carusocomputing .

Î0¡¤g

Provalo online!

Spiegazione

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length

0¡¤gè di quattro byte.
Magic Octopus Urn

@carusocomputing: Nice! Non è stato ancora chiarito se l'input della stringa era ok quando ho scritto questo, ma vedo ora che lo è :)
Emigna,

J0¡¤gè anche ancora più breve;).
Magic Octopus Urn

@carusocomputing: purtroppo dobbiamo Îgestire l'input vuoto, ma è ancora un byte salvato grazie :)
Emigna,




7

Mathematica, 25 24 byte

Fold[If[#2,#+1,0]&,0,#]&

3
Sto solo registrando una porta della fantastica soluzione a base mista di Dan: FromDigits[b=Boole@#,MixedRadix@b]&(35 byte).
Greg Martin,

5

Pyth, 6 byte

x_+0Q0

Provalo qui!

Aggiunge uno 0, inverte e trova l'indice del primo 0


@Jakube risolto ora - algoritmo diverso
Blue

5

C90 (gcc), 46 byte

r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}

L'input avviene tramite argomenti della riga di comando (un numero intero per argomento), output tramite il codice di uscita .

Provalo online!

Come funziona

r è una variabile globale. Il suo tipo di default è int e, essendo globale, il suo valore predefinito è 0 .

Anche l'argomento funzione c viene impostato su int . Conterrà l'intero n + 1 per le matrici di n booleani; il primo argomento di main è sempre il percorso dell'eseguibile.

L'argomento della funzione v è dichiarato come int**. Il tipo effettivo di v sarà char**, ma poiché esamineremo solo il bit meno significativo di ogni argomento per distinguere i caratteri 0 (punto di codice 48 ) e 1 (punto di codice 49 ), questo non importerà su little-endian macchinari.

Il ciclo while decrementa c e lo confronta con 0 . Una volta che c raggiunge 0 , usciremo dal ciclo. Ciò è necessario solo se l'array non contiene 0 .

Finché 0<--ci rendimenti 1 , si prende la c ° argomento della riga di comando ( v[c]) ed estrarre il suo primo personaggio con dereferenziando il puntatore ( *). Prendiamo il bit bit AND del booleano 0<--ce il punto di codice del carattere (e tre byte di immondizia che lo seguono), quindi la condizione restituirà 0 una volta che si incontra uno 0 , uscendo dal ciclo.

Nel resto del caso, mentre gli argomenti della riga di comando sono 1 , r++incrementa r di 1 , contando così il numero di 1 finali .

Infine, c=rmemorizza il valore calcolato di r in c . Con le impostazioni predefinite, il compilatore ottimizza e rimuove l'assegnazione; in realtà genera l' movl %eax, -4(%rbp)istruzione. Poiché retrestituisce il valore del registro EAX, questo genera l'output desiderato.

Si noti che questo codice non funziona con C99, che restituisce 0 da main se viene raggiunta la fine di main .


Non è argcalmeno 1(con argv[0]contenere il nome del file)? È possibile salvare un byte con --c&&invece di 0<--c&. Il codice di uscita di gcc è preso da argc? Neat.
Tito

@Titus Non funzionerà. *v[c]è il punto di codice 1 o 0 , quindi è 49 o 48 e quindi sempre vero.
Dennis,

Con C89 e C90, gcc restituisce tutto ciò che è in RAX in quel momento. C99 restituisce sempre 0 dalla principale se viene raggiunta la fine.
Dennis,

4

k, 6 byte

+/&\|:

Questa composizione di funzioni si traduce in sum mins reversein q, il fratello più leggibile della lingua, dove min è un minimo continuo.


Il: può essere lasciato cadere?
streetster

4

J, 9 3 byte

#.~

Questa è una conversione di base mista riflessiva. Perché è uguale alla conversione di base mista. Ancora.

Casi test

   v =: #.~
   ]t =: '';0;1;0 1 1 0 0;1 1 1 0 1;1 1 0 1 1;0 0 1 1 1;1 1 1 1 1 1
++-+-+---------+---------+---------+---------+-----------+
||0|1|0 1 1 0 0|1 1 1 0 1|1 1 0 1 1|0 0 1 1 1|1 1 1 1 1 1|
++-+-+---------+---------+---------+---------+-----------+
   v&.> t
+-+-+-+-+-+-+-+-+
|0|0|1|0|1|2|3|6|
+-+-+-+-+-+-+-+-+
   (,. v&.>) t
+-----------+-+
|           |0|
+-----------+-+
|0          |0|
+-----------+-+
|1          |1|
+-----------+-+
|0 1 1 0 0  |0|
+-----------+-+
|1 1 1 0 1  |1|
+-----------+-+
|1 1 0 1 1  |2|
+-----------+-+
|0 0 1 1 1  |3|
+-----------+-+
|1 1 1 1 1 1|6|
+-----------+-+

2
Suggerimento: questo può essere fatto in soli 3 byte, usando la traduzione J della soluzione di Dan.
Adám,

1
@Adám Ho provato a cercare una soluzione. Non ho pensato alla conversione di base. È davvero abbastanza intelligente da parte sua!
Conor O'Brien,

1
Sì. Quello era Dan. :-(
Adám,

4

R, 40 39 25 byte

Soluzione completamente rielaborata grazie a @Dason

sum(cumprod(rev(scan())))

Leggi l'input da stdin, inverti il ​​vettore e se il primo elemento di viene !=0quindi emesso la prima lunghezza della codifica run-length ( rle), altrimenti 0.


1
È possibile salvare un byte modificando la seconda riga in ifelse(r$v,r$l,0)[1]. (Vettorializzare if, e quindi prendere il primo elemento.)
rturnbull,

1
non c'è bisogno di iflelse: basta moltiplicare r $ v e r $ l.
Dason,

Ma la route sum (cumprod (rev (.))) Dovrebbe comunque salvare molti byte
Dason

3

Haskell, 24 byte

foldl(\a b->sum[a+1|b])0

Scorre l'elenco, aggiungendone uno per ogni elemento, ripristinandolo 0dopo che ha colpito a False.

16 byte con input 0/1:

foldl((*).(+1))0

Se l'elenco fosse garantito non vuoto, potremmo ottenere 14 byte:

sum.scanr1(*)1

Questo calcola il prodotto cumulativo dal retro, quindi li somma. Il prodotto cumulativo rimane 1 fino a quando non viene colpito uno 0, quindi diventa 0. Quindi, 1 corrisponde a 1 finali.



3

C # 6, 103 72 byte

using System.Linq;
int a(bool[] l)=>l.Reverse().TakeWhile(x=>x).Count();

L'uso dell'elenco non generico batte l'elenco generico di 1 byte lol

-31 byte grazie a Scott


Se si utilizza una matrice di ints, è possibile ottenere via conint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott

@Scott Ovviamente, cosa stavo pensando ... Ma resterò fedele. La domanda specifica un elenco booleano e non è C.
Link

Compilare in a Func<bool[], int>per 57 byte, ovverousing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder

2

Python, 37 byte

f=lambda l:len(l)and-~f(l[:-1])*l[-1]

2

DASH , 16 byte

@len mstr"1+$"#0

Non è la soluzione DASH più breve possibile, ma la soluzione DASH più breve possibile mi sta prendendo in giro. Sto pubblicando questo nuovo approccio al suo posto.

Uso:

(@len mstr"1+$"#0)"100111"

Spiegazione

@(                 #. Lambda
  len (            #. Get the length of the array after...
    mstr "1+$" #0  #. ... matching the argument with regex /1+$/
  )                #. * mstr returns an empty array for no matches
)

2

Scala, 25 byte

l=>l.reverse:+0 indexOf 0

Ungolfed:

l=>(l.reverse :+ 0).indexOf(0)

Inverte l'elenco, aggiunge uno 0 e trova il primo indice di 0, che è il numero di elementi prima del primo 0


2

Lotto, 57 byte

@set n=0
@for %%n in (%*)do @set/an=n*%%n+%%n
@echo %n%

Accetta input come parametri della riga di comando. Funziona moltiplicando l'accumulatore per il valore corrente prima di aggiungerlo, in modo che eventuali zeri nella riga di comando ripristinino il conteggio. Si noti che %%nnon è uguale alla variabile no %n%.



2

Java 7, 62 byte

int c(boolean[]a){int r=0;for(boolean b:a)r=b?r+1:0;return r;}

Codice non testato e test:

Provalo qui.

class M{
  static int c(boolean[] a){
    int r = 0;
    for (boolean b : a){
      r = b ? r+1 : 0;
    }
    return r;
  }

  public static void main(String[] a){
    System.out.print(c(new boolean[]{}) + ", ");
    System.out.print(c(new boolean[]{ false }) + ", ");
    System.out.print(c(new boolean[]{ true }) + ", ");
    System.out.print(c(new boolean[]{ false, true, true, false, false }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, false, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, false, true, true }) + ", ");
    System.out.print(c(new boolean[]{ false, false, true, true, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, true, true, true }));
  }
}

Produzione:

0, 0, 1, 0, 1, 2, 3, 6

2

Perl 5,10, 22 byte

21 byte + 1 byte per -aflag. Poiché l'espressione basata su regex è stata eseguita ...: p

I valori di input per l'array devono essere separati da uno spazio.

$n++while pop@F;say$n

Provalo online!


1
Leggermente più breve se prendi argomenti tramite la riga di comando: perl -E '$_++while pop;say' 0 1 1 0 1 1 1ma questo non produce nulla per 0(non sono sicuro se questo è un problema!)
Dom Hastings

2

Perl, 22 byte

21 byte di codice + 1 byte per -pflag.

s/.(?=.*0)//g;$_=y;1;

Per eseguirlo:

perl -pE 's/.(?=.*0)//g;$_=y;1;' <<< "0 1 1 0 1 1 1"

(In realtà, il formato dell'ingresso non importa molto: 0110111, 0 1 1 0 1 1 1, [0,1,1,0,1,1,1]ecc sarebbe tutto il lavoro)


Versione di 18 byte da @Dom Hastings ma richiede di fornire l'input come una stringa di 0 e 1, che non è consentito:

perl -pE '/1*$/;$_=length$&' <<< '0110111'

Adoro quel ;trucco :) Se il formato è una stringa continua: perl -pE '/1*$/;$_=length$&' <<< '0110111'per 18, non sono sicuro se questo sta piegando le regole o no ...
Dom Hastings

@DomHastings sì, anche a me! (Grazie Ton per avermelo mostrato!) Il primo e il secondo commento della domanda non consentono il formato dell'input necessario per la tua soluzione ... Ma modificherò il mio post per suggerire la tua versione se il formato dell'input fosse più gratuito.
Dada,

2

PHP, 50 byte

<?=strlen(preg_filter('/.*[^1]/','',join($argv)));

Stranamente il mio primo tentativo con un regex si è rivelato più breve del mio tentativo con array ...
Usa come:

php tt.php 1 1 0 1 1

2

Ruby 37 32 byte

->n{n.size-1-(n.rindex(!0)||-1)}

Crea una funzione anonima che trova l'istanza più a destra di un valore falso e conta la dimensione del subarray a partire da quel valore.

Usa !0come falso, poiché 0 sono valori di verità in Ruby. rindextrova l'ultimo indice di un valore in un array.

Utilizzo :

boolean_list = [true, false, false, true]
->n{n.size-1-(n.rindex(!0)||-1)}[boolean_list]

Restituisce 1


Se mi fosse permesso di passare una stringa di 0 e 1 come parametri della riga di comando (che non è il modo in cui ruby ​​rappresenta elenchi di booleani), potrei arrivare a 24:

$*[0]=~/(1*)\z/;p$1.size

Questo utilizza espressioni regolari e stampa la lunghezza della stringa restituita dall'espressione regolare /(1*)\z/, dove si \ztrova la fine della stringa. $*[0]è il primo argomento passato ed è una stringa di 0 e 1 secondi.

Uso:

trailing_truths.rb 011101

Restituisce 1.


1
Dopo aver ottenuto l'indice dell'ultimo valore falso, perché è necessario recuperare nuovamente gli elementi dall'array?
Lee W,

Hai ragione, io no. Grazie. 5 byte di sconto!
IMP1
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.