Cuenta las verdades finales

59

Inspirado y en memoria de mi querido amigo y colega,

Dan Baronet

Dan Baronet , 1956 - 2016. RIP

Encontró la solución APL más corta posible para esta tarea:

Tarea

Dada una lista booleana, cuente el número de valores de verdad finales.

Casos de ejemplo

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

Adán
fuente
¿Podemos tomar la lista como una cadena de ceros y unos? por ejemplo 01100?
Adnan el
@Adnan solo si esa es la forma más normal para que su idioma represente listas booleanas.
Adám
71
Lo siento por su pérdida.
Martin Ender
66
@ MartinDender Gracias. Será difícil seguir adelante. Dan me enseñó todo lo que necesitaba saber para trabajar para Dyalog.
Adám el
55
Adiós a Dan. RIP ...
Erik the Outgolfer

Respuestas:

36

Dyalog APL, 6 2 bytes

⊥⍨

Pruébelo en TryAPL .

Cómo funciona

(uptack, dyadic: decode) realiza la conversión de base. Si el operando izquierdo es un vector, realiza una conversión de base mixta , lo cual es perfecto para esta tarea.

Para un vector base b = b n , ⋯, b 0 y un vector de dígitos a = a n , ⋯, un 0 , b ⊥ un convierte una a la base mixta b , es decir, calcula b 0 ⋯ b n-1 una n + ⋯ + b 0 b 1 a 2 + b 0 a 1 + a 0 .

Ahora, (tilde dieresis, conmutar) modifica el operador a la izquierda de la siguiente manera. En un contexto monádico, llama al operador con argumentos iguales de izquierda y derecha.

Por ejemplo, ⊥⍨ a se define como a ⊥ a , que calcula a 0 ⋯ a n + ⋯ + a 0 a 1 a 2 + a 0 a 1 + a 0 , la suma de todos los productos acumulativos de derecha a izquierda .

Para k finales, los k productos más a la derecha son 1 y todos los demás son 0 , por lo que su suma es igual a k .

Dennis
fuente
14
Sugerencia: Dan lo hizo en solo dos bytes.
Adám
3
Conversión de base mixta! Eso es inteligente.
Dennis
1
Oh. Conversión de base mixta, cómo ataca de nuevo.
Conor O'Brien el
¡Bravo! De hecho, a causa de Dan, que especial con carcasa b⊥by ⊥⍨brenunciar a infinita velocidad de marcha.
Adám
19

JavaScript (ES6), 21 bytes

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

Casos de prueba

Arnauld
fuente
¿Como funciona esto? ¿Cómo f(l)+1devuelve un valor > 2?
Oliver
@Oliver Este es un proceso recursivo, evaluado como l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0.
Arnauld
Veo. Gracias por la explicación.
Oliver
11

Jalea , 4 bytes

ŒrṪP

Pruébalo en línea! o Verificar todos los casos de prueba.

Para el caso donde la lista está vacía, hay algunas observaciones curiosas. Primero, la codificación de longitud de ejecución de la lista vacía []devuelve otra lista vacía []. Luego, recuperando el último elemento de ese uso de retornos de cola en 0lugar de un par [value, count]que son los elementos regulares de una matriz codificada de longitud de ejecución. Luego, el producto Pregresa 0cuando se le solicita 0cuál es el resultado esperado.

Explicación

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together
millas
fuente
Alternativamente, ŒgṪS¡también funciona!
Lynn el
Da la salida correcta para la lista vacía como entrada, pero me sorprende dada la disección. ¿Te importaría caminar por ese caso especial?
Peter Taylor
@ PeterTaylor También me sorprende que haya funcionado. Además, acabo de notar que el primer enlace tiene el código incorrecto.
millas
@PeterTaylor Jelly se implementa como: lambda z: iterable(z).pop() if iterable(z) else 0. iterablecuando se le llama en una lista solo devuelve la lista, y la lista vacía es, por supuesto, falsa.
FryAmTheEggman
10

Brachylog , 7 6 5 bytes

@]#=+

Pruébalo en línea!

Explicación

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

Dado que @] - Suffixcomienza desde el sufijo más grande hasta el más pequeño, primero encontrará la carrera más larga.

Fatalizar
fuente
10

CJam (8 bytes)

{W%0+0#}

Conjunto de pruebas en línea

Disección

{    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
}
Peter Taylor
fuente
10

Haskell, 26 25 bytes

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

Uso:

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

Versión sin puntos (26 bytes):

length.fst.span id.reverse

Usando una lista entera en lugar de una lista bool (21 bytes, gracias a Christian Sievers):

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

Uso:

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

Versión sin puntos (25 bytes)

sum.fst.span(==1).reverse
Laikoni
fuente
Para listas enteras con las que foldlfunciona la ideaa%b=b*(a+1)
Christian Sievers
9

Retina , 7 5 bytes

r`1\G

Pruébalo en línea! (La primera línea habilita un conjunto de pruebas separado por salto de línea).

Definir el formato de entrada para Retina no es del todo inequívoco. Dado que Retina no tiene ningún concepto de ningún tipo, excepto cadenas (y tampoco ningún valor que pueda usarse para nuestra definición habitual de verdad y falsedad), generalmente uso 0y 1(o algo positivo en general) para corresponder a verdad y falsedad, ya que representan cero o algunos partidos, respectivamente.

Con las representaciones de un solo carácter, tampoco necesitamos un separador para la lista (que, en cierto modo, es más la representación de la lista más natural para un lenguaje que solo tiene cadenas). Adám confirmó que este es un formato de entrada aceptable.

En cuanto a la expresión regular en sí, coincide de right a izquierda y \Gancla cada coincidencia a la anterior. Por lo tanto, esto cuenta cuántos 1s podemos igualar desde el final de la cadena.

Martin Ender
fuente
"Sí, para Retina, dado que maneja solo cadenas, creo que una cadena" 01 "o" FT "está en orden.
Adám
9

05AB1E , 12 10 6 5 bytes

Guardado 1 byte gracias a carusocomputing .

Î0¡¤g

Pruébalo en línea!

Explicación

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length
Emigna
fuente
0¡¤ges de cuatro bytes.
Urna mágica del pulpo
@carusocomputing: ¡Qué bueno! Todavía no se aclaró si la entrada de cadena estaba bien cuando escribí esto, pero ahora veo que es :)
Emigna
J0¡¤gtambién es aún más corto;).
Urna de pulpo mágico
@carusocomputing: Desafortunadamente, necesitamos Îmanejar la entrada vacía, pero aún es un byte guardado gracias :)
Emigna
8

Python, 31 bytes

lambda a:(a[::-1]+[0]).index(0)
Mitch Schwartz
fuente
7

Jalea , 4 bytes

ṣ0ṪL

TryItOnline! o todas las pruebas

¿Cómo?

ṣ0ṪL - Main link: booleanList
ṣ0   - split on occurrences of 0 ([] -> [[]]; [0] -> [[],[]]; [1] -> [[1]]; ...)
  Ṫ  - tail (rightmost entry)
   L - length
Jonathan Allan
fuente
7

Mathematica, 25 24 bytes

Fold[If[#2,#+1,0]&,0,#]&
alephalpha
fuente
3
Simplemente grabando un puerto de la genial solución de base mixta de Dan: FromDigits[b=Boole@#,MixedRadix@b]&(35 bytes).
Greg Martin
5

Pyth, 6 bytes

x_+0Q0

Pruébalo aquí!

Agrega un 0, invierte y encuentra el índice del primer 0

Azul
fuente
@Jakube solucionado ahora - algoritmo diferente
Azul
5

C90 (gcc), 46 bytes

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

La entrada es a través de argumentos de línea de comandos (un número entero por argumento), la salida a través del código de salida .

Pruébalo en línea!

Cómo funciona

r es una variable global. Su tipo predeterminado es int y, al ser global, su valor predeterminado es 0 .

El argumento de la función c por defecto también es int . Retendrá el número entero n + 1 para matrices de n booleanos; El primer argumento de main es siempre la ruta del ejecutable.

El argumento de la función v se declara como int**. El tipo real de v será char**, pero dado que solo examinaremos el bit menos significativo de cada argumento para distinguir los caracteres 0 (punto de código 48 ) y 1 (punto de código 49 ), esto no importará en little-endian maquinas.

El ciclo while disminuye c y lo compara con 0 . Una vez que c alcanza 0 , saldremos del bucle. Esto es necesario solo si la matriz no contiene 0 's.

Siempre que 0<--cdevuelva 1 , tomamos el argumento de línea de comando c th ( v[c]) y extraemos su primer carácter desreferenciando el puntero ( *). Tomamos el AND bit a bit del Booleano 0<--cy el punto de código del carácter (y los tres bytes de basura que lo siguen), por lo que la condición devolverá 0 una vez que se encuentre un 0 , rompiendo el bucle.

En el caso restante, mientras que los argumentos de la línea de comando son 1 , r++incrementa r en 1 , contando así el número de 1 's posteriores .

Finalmente, c=ralmacena el valor calculado de r en c . Con la configuración predeterminada, el compilador optimiza y elimina la asignación; En realidad genera la movl %eax, -4(%rbp)instrucción. Como retdevuelve el valor del registro EAX, esto genera la salida deseada.

Tenga en cuenta que este código no funciona con C99, que devuelve 0 desde main si se alcanza el final de main .

Dennis
fuente
¿No es argcal menos 1(con argv[0]contener el nombre del archivo)? Podría guardar un byte con en --c&&lugar de 0<--c&. ¿Se toma el código de salida de gcc argc? Ordenado.
Titus
@Titus Eso no funcionará. *v[c]es el punto de código de 1 o 0 , por lo que es 49 o 48 y, por lo tanto, siempre es verdadero.
Dennis
Con C89 y C90, gcc devuelve lo que esté en RAX en ese momento. C99 siempre devuelve 0 desde main si se alcanza el final.
Dennis
4

k, 6 bytes

+/&\|:

Esta composición de funciones se traduce en sum mins reversein q, el hermano más legible del lenguaje, donde min es un mínimo continuo.

skeevey
fuente
¿Se puede dejar caer el?
Callejero
4

J, 9 3 bytes

#.~

Esta es una conversión reflexiva de base mixta. Porque esto es lo mismo que la conversión de base mixta. De nuevo.

Casos de prueba

   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|
+-----------+-+
Conor O'Brien
fuente
2
Sugerencia: Esto se puede hacer en solo 3 bytes, utilizando la traducción J de la solución de Dan.
Adám
1
@ Adám Intenté buscar una solución. No pensé en la conversión de base. ¡Eso es muy inteligente de su parte!
Conor O'Brien el
1
Si. Ese fue Dan. :-(
Adám
4

R, 40 39 25 bytes

Solución completamente reelaborada gracias a @Dason

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

Lea la entrada de stdin, invierta el vector y, si el primer elemento de !=0, emite la primera longitud de la codificación de longitud de ejecución ( rle), de lo contrario 0.

Billywob
fuente
1
Puede guardar un byte cambiando la segunda línea a ifelse(r$v,r$l,0)[1]. (Vectorizado si, y luego tomar el primer elemento.)
rturnbull
1
no es necesario el iflelse: simplemente multiplique r $ v y r $ l.
Dason
Pero la ruta de la suma (cumprod (rev (.))) Debería ahorrar muchos bytes de todos modos
Dason
3

Haskell, 24 bytes

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

Itera sobre la lista, agregando uno para cada elemento, reiniciando 0después de que golpea a False.

16 bytes con entrada 0/1:

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

Si se garantizara que la lista no está vacía, podríamos obtener 14 bytes:

sum.scanr1(*)1

Esto calcula el producto acumulativo desde la parte posterior, luego los suma. El producto acumulativo permanece 1 hasta que se alcanza un 0, y luego se convierte en 0. Entonces, los 1 corresponden a los 1 finales.

xnor
fuente
3

C # 6, 103 72 bytes

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

El uso de la lista no genérica supera la lista genérica por 1 byte lol

-31 bytes gracias a Scott

Enlace Ng
fuente
Si usa una variedad de ints, puede salirse con la suyaint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott
@ Scott Por supuesto, ¿qué estaba pensando? Sin embargo, me quedaré con bool. La pregunta especifica una lista booleana y no es C.
Enlace del
Compilar a a Func<bool[], int>para 57 bytes, es decirusing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder
2

Python, 37 bytes

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

GUIÓN, CORRER PRECIPITADAMENTE, PRECIPITARSE, IR DE PRISA , 16 bytes

@len mstr"1+$"#0

No es la solución DASH más corta posible, pero la solución DASH más corta posible me está molestando. Estoy publicando este enfoque novedoso en su lugar.

Uso:

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

Explicación

@(                 #. 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
)
Mama Fun Roll
fuente
2

Scala, 25 bytes

l=>l.reverse:+0 indexOf 0

Sin golf:

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

Invierte la lista, agrega un 0 y encuentra el primer índice de 0, que es el número de elementos antes del primer 0

corvus_192
fuente
2

Lote, 57 bytes

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

Toma datos como parámetros de línea de comandos. Funciona multiplicando el acumulador por el valor actual antes de agregarlo, para que los ceros en la línea de comando restablezcan el conteo. Tenga en cuenta que %%nno es lo mismo que la variable no %n%.

Neil
fuente
2

GolfSharp, 14 bytes

n=>n.V().O(F);
downrep_nation
fuente
2

Java 7, 62 bytes

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

Ungolfed y código de prueba:

Pruébalo aquí.

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

Salida:

0, 0, 1, 0, 1, 2, 3, 6
Kevin Cruijssen
fuente
2

Perl 5.10, 22 bytes

21 bytes + 1 byte para -abandera. Dado que se realizó la expresión basada en expresiones regulares ...: p

Los valores de entrada para la matriz deben estar separados por un espacio.

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

Pruébalo en línea!

Paul Picard
fuente
1
Un poco más corto si toma argumentos a través de la línea de comando: perl -E '$_++while pop;say' 0 1 1 0 1 1 1pero esto no genera nada 0(¡aunque no estoy seguro si eso es un problema!)
Dom Hastings
2

Perl, 22 bytes

21 bytes de código + 1 byte para -pbandera.

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

Para ejecutarlo:

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

(En realidad, el formato de la entrada no importa mucho: 0110111, 0 1 1 0 1 1 1, [0,1,1,0,1,1,1]etc haría todo el trabajo)


Versión de 18 bytes de @Dom Hastings pero requiere suministrar la entrada como una cadena de 0 y 1, lo cual no está permitido:

perl -pE '/1*$/;$_=length$&' <<< '0110111'
Dada
fuente
Me encanta ese ;truco :) Si el formato es una cadena continua: perl -pE '/1*$/;$_=length$&' <<< '0110111'para 18, no estoy seguro de si eso está doblando las reglas o no ...
Dom Hastings
@DomHastings sí, yo también! (¡Gracias Ton por mostrarme eso!) El primer y el segundo comentario de la pregunta no permiten el formato de entrada que necesita para su solución ... Pero editaré mi publicación para sugerir su versión si el formato de entrada fue más gratis.
Dada
2

PHP, 50 bytes

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

Extrañamente, mi primer intento con una expresión regular resultó más corto que mi intento con matrices ...
Use como:

php tt.php 1 1 0 1 1
usuario59178
fuente
2

Ruby 37 32 bytes

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

Crea una función anónima que encuentra la instancia más a la derecha de un valor falso y cuenta el tamaño de la submatriz a partir de ese valor.

Se usa !0como falso, ya que 0 son valores verdaderos en Ruby. rindexencuentra el último índice de un valor en una matriz.

Uso :

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

Devuelve 1


Si se me permitiera pasar una cadena de 0 y 1 como parámetros de línea de comando (que no es cómo Ruby representa listas de booleanos), podría reducirlo a 24:

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

Esto usa expresiones regulares e imprime la longitud de la cadena devuelta por la expresión regular /(1*)\z/, donde \zes el final de la cadena. $*[0]es el primer argumento pasado y es una cadena de 0s y 1s.

Uso:

trailing_truths.rb 011101

Devuelve 1.

IMP1
fuente
1
Una vez que tenga el índice del último valor falso, ¿por qué necesita recuperar elementos de la matriz nuevamente?
Lee W
Tienes razón, yo no. Gracias. ¡5 bytes de descuento!
IMP1