Contar verdades finais

59

Inspirado e em memória de meu querido amigo e colega,

Dan Baronet

Dan Baronet , 1956 - 2016. RIP

Ele encontrou a solução de APL mais curta possível para esta tarefa:

Tarefa

Dada uma lista booleana, conte o número de valores de verdade à direita.

Casos de exemplo

{}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ão
fonte
Podemos considerar a lista como uma sequência de zeros e uns? por exemplo 01100?
Adnan #
@Adnan apenas se essa for a maneira mais normal para o seu idioma representar listas booleanas.
Adám 06/11/16
71
Meus pêsames.
Martin Ender
6
@MartinEnder Obrigado. Vai ser difícil daqui para frente. Dan me ensinou tudo o que eu precisava saber para trabalhar na Dyalog.
Adám 06/11/16
5
Adeus a Dan. RIP ...
Erik o Outgolfer

Respostas:

36

Dyalog APL, 6 2 bytes

⊥⍨

Teste-o no TryAPL .

Como funciona

(uptack, diádico: decodificação) realiza a conversão de base. Se o operando esquerdo for um vetor, ele realiza a conversão de base mista , o que é perfeito para esta tarefa.

Para um vector de base b = b n , ⋯, b 0 e um dígito de vector a = a n , ⋯, um 0 , b ⊥ um converte um para a base mista b , ou seja, ele calcula b 0 ⋯ b n-1 um n + ⋯ + b 0 b 1 a 2 + b 0 a 1 + a 0 .

Agora, (dieresis til , commute ) modifica o operador para a esquerda da seguinte maneira. Em um contexto monádico, ele chama o operador com argumentos iguais à esquerda e à direita.

Por exemplo, ⊥⍨ a é definido como ⊥ a , que calcula a 0 ⋯ a n + ⋯ + a 0 a 1 a 2 + a 0 a 1 + a 0 , a soma de todos os produtos cumulativos da direita para a esquerda .

Para os k à direita, os k produtos à direita são 1 e todos os outros são 0 , portanto, sua soma é igual a k .

Dennis
fonte
14
Dica: Dan fez isso em apenas dois bytes.
Adám 06/11/16
3
Conversão de base mista! Isso é esperto.
Dennis
11
Oh. Conversão de base mista, como ocorre novamente.
Conor O'Brien
Bravo! Na verdade, por causa do Dan, nós special-encaixotado b⊥be ⊥⍨bdando até infinito velocidade-up.
Adám 06/11/16
19

JavaScript (ES6), 21 bytes

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

Casos de teste

Arnauld
fonte
Como é que isso funciona? Como f(l)+1retorna um valor > 2?
Oliver
@ Oliver Este é um processo recursivo, avaliado como l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0.
Arnauld
Eu vejo. Obrigada pelo esclarecimento.
Oliver
11

Gelatina , 4 bytes

ŒrṪP

Experimente online! ou Verifique todos os casos de teste.

Para o caso em que a lista está vazia, existem algumas observações curiosas. Primeiro, o comprimento da execução que codifica a lista vazia []retorna outra lista vazia []. Em seguida, recupere o último elemento usando retornos finais em 0vez de um par, [value, count]que são os elementos regulares de uma matriz codificada no comprimento da execução. Em seguida, o produto Pretorna 0quando chamado, 0qual é o resultado esperado.

Explicação

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together
milhas
fonte
Como alternativa, também ŒgṪSfunciona!
Lynn
Ele fornece a saída correta para a lista vazia como entrada, mas estou surpreso com a dissecção. Você se importaria de percorrer esse caso especial?
Peter Taylor
@ PeterTaylor Também estou surpreso que funcionou. Além disso, acabei de perceber que o primeiro link tem o código errado.
milhas
@PeterTaylor in Jelly é implementado como: lambda z: iterable(z).pop() if iterable(z) else 0. iterablequando chamado em uma lista apenas retorna a lista, e a lista vazia é obviamente falsa.
FryAmTheEggman 6/11
10

Braquilog , 7 6 5 bytes

@]#=+

Experimente online!

Explicação

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

Desde que @] - Suffixcomeça do maior sufixo até o menor, ele encontrará o mais longo primeiro.

Fatalizar
fonte
10

CJam (8 bytes)

{W%0+0#}

Conjunto de testes online

Dissecação

{    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
fonte
10

Haskell, 26 25 bytes

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

Uso:

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

Versão sem ponto (26 bytes):

length.fst.span id.reverse

Usando uma lista inteira em vez de uma lista bool (21 bytes, graças a Christian Sievers):

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

Uso:

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

Versão sem ponto (25 bytes)

sum.fst.span(==1).reverse
Laikoni
fonte
Para listas inteiras, a foldlidéia trabalha coma%b=b*(a+1)
Christian Sievers
9

Retina , 7 5 bytes

r`1\G

Experimente online! (A primeira linha ativa um conjunto de testes separado por avanço de linha.)

Definir o formato de entrada para o Retina não é totalmente inequívoco. Como Retina não tem nenhum conceito de qualquer tipo, exceto strings (e também nenhum valor que possa ser usado para nossa definição usual de verdade e falsidade), eu geralmente uso 0e 1(ou algo positivo em geral) para corresponder a verdade e falsidade, pois elas representam zero ou algumas correspondências, respectivamente.

Com representações de caracteres únicos, também não precisamos de um separador para a lista (que, de certa forma, é mais a representação de lista mais natural para um idioma que possui apenas strings). Adám confirmou que este é um formato de entrada aceitável.

Quanto ao próprio regex, ele corresponde da rdireita para a esquerda e \Gancora cada partida à anterior. Portanto, isso conta quantos 1s podemos corresponder a partir do final da string.

Martin Ender
fonte
"Sim, para Retina, como ele lida apenas com seqüências de caracteres, acho que uma sequência" 01 "ou" FT "está em ordem.
Adám 06/11/16
9

05AB1E , 12 10 6 5 bytes

Economizou 1 byte graças à carusocomputação .

Î0¡¤g

Experimente online!

Explicação

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length
Emigna
fonte
0¡¤gé de quatro bytes.
Magic Octopus Urn
@carusocomputing: Nice! Ainda não foi esclarecido se a entrada corda estava bem quando eu escrevi isso, mas agora vejo que é :)
Emigna
J0¡¤gtambém é ainda mais curto;).
Magic Octopus Urn
@carusocomputing: Infelizmente precisamos Îpara lidar com a entrada vazia, mas ainda é um byte salvas graças :)
Emigna
8

Python, 31 bytes

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

Gelatina , 4 bytes

ṣ0ṪL

TryItOnline! ou todos os testes

Quão?

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

Mathematica, 25 24 bytes

Fold[If[#2,#+1,0]&,0,#]&
alefalpha
fonte
3
Apenas gravando uma porta da solução legal de base mista de Dan: FromDigits[b=Boole@#,MixedRadix@b]&(35 bytes).
9788 Gregory Martin
5

Pitão, 6 bytes

x_+0Q0

Experimente aqui!

Acrescenta um 0, reverte e encontra o índice do primeiro 0

Azul
fonte
@Jakube corrigido agora - algoritmo diferente
azul
5

C90 (gcc), 46 bytes

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

A entrada é via argumentos da linha de comando (um número inteiro por argumento), a saída é via código de saída .

Experimente online!

Como funciona

r é uma variável global. Seu tipo padrão é int e, sendo global, o valor padrão é 0 .

O argumento da função c também padroniza int . Ele manterá o número inteiro n + 1 para matrizes de n booleanos; o primeiro argumento de main é sempre o caminho do executável.

O argumento da função v é declarado como int**. O tipo real de v será char**, mas como examinaremos apenas o bit menos significativo de cada argumento para diferenciar os caracteres 0 (ponto de código 48 ) e 1 (ponto de código 49 ), isso não será importante para os pequenos endianistas. máquinas

O loop while diminui c e o compara a 0 . Uma vez que c atinge 0 , vamos sair do loop. Isso é necessário apenas se a matriz não contiver 0 .

Enquanto 0<--cretorna 1 , que leva o c th argumento de linha de comando ( v[c]) e extrair seu primeiro personagem com dereferenciando o ponteiro ( *). Tomamos o AND bit a bit do Booleano 0<--ce o ponto de código do caractere (e três bytes de lixo que o seguem), portanto a condição retornará 0 assim que um 0 for encontrado, interrompendo o loop.

No outro caso, enquanto os argumentos de linha de comando são 1 , r++incrementa r por 1 , tendo assim em conta o número de arrasto 1 's.

Por fim, c=rarmazena o valor calculado de r em c . Com as configurações padrão, o compilador otimiza e remove a atribuição; na verdade gera a movl %eax, -4(%rbp)instrução. Como retretorna o valor do registro EAX, isso gera a saída desejada.

Observe que esse código não funciona com C99, que retorna 0 do main se o final do main for atingido.

Dennis
fonte
Não é argcpelo menos 1(com argv[0]o nome do arquivo)? Você pode salvar um byte em --c&&vez de 0<--c&. o código de saída do gcc foi retirado argc? Arrumado.
Titus
@ Titus Isso não vai funcionar. *v[c]é o ponto de código de 1 ou 0 ; portanto, é 49 ou 48 e, portanto, sempre é verdade.
Dennis
Com C89 e C90, o gcc retorna o que estiver no RAX naquele momento. C99 sempre retorna 0 do principal se o fim for alcançado.
Dennis
4

k, 6 bytes

+/&\|:

Essa composição de função se traduz em sum mins reversein q, o irmão mais legível do idioma, em que mins é o mínimo contínuo.

skeevey
fonte
O: pode ser descartado?
Streetster 18/10
4

J, 9 3 bytes

#.~

Esta é a conversão de base mista reflexiva. Porque isso é o mesmo que conversão de base mista. Novamente.

Casos de teste

   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
fonte
2
Dica: Isso pode ser feito em apenas 3 bytes, usando a tradução J da solução de Dan.
Adám 06/11/16
11
@ Adám Tentei procurar uma solução. Não pensou em conversão de base. Isso é realmente muito inteligente da parte dele!
Conor O'Brien
11
Sim. Aquele era o Dan. :-(
Adám 06/11/16
4

R, 40 39 25 bytes

Solução completamente reformulada graças a @Dason

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

Leia a entrada de stdin, inverta o vetor e, se o primeiro elemento de, em !=0seguida, forneça o primeiro comprimento da codificação de comprimento de execução ( rle), caso contrário 0.

Billywob
fonte
11
Você pode salvar um byte alterando a segunda linha para ifelse(r$v,r$l,0)[1]. (Vectorized se, e, em seguida, tomar o primeiro elemento.)
rturnbull
11
não é necessário o iflelse - basta multiplicar r $ ve r $ l.
Dason 8/11
Mas a soma (. Cumprod (rev ())) rota deve guardar um monte de bytes de qualquer maneira
Dason
3

Haskell, 24 bytes

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

Repete a lista, adicionando um para cada elemento, redefinindo para 0depois que ele atinge a False.

16 bytes com entrada 0/1:

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

Se a lista fosse garantida como não vazia, poderíamos obter 14 bytes:

sum.scanr1(*)1

Isso calcula o produto cumulativo na parte de trás e depois os soma. O produto cumulativo permanece 1 até que um 0 seja atingido e depois se torne 0. Portanto, os 1s correspondem aos 1s finais.

xnor
fonte
3

C # 6, 103 72 bytes

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

Usar lista não genérica bate a lista genérica por 1 byte lol

-31 bytes graças a Scott

Ng do link
fonte
Se você usar uma matriz de ints, você pode sair comint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott
@ Scott É claro que eu estava pensando ... Mas vou ficar com o bool. Pergunta especifica lista boolean e não é C.
Fazer a ligação Ng
Compilar para um Func<bool[], int>para 57 bytes ieusing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder 8/16/16
2

Python, 37 bytes

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

DASH , 16 bytes

@len mstr"1+$"#0

Não é a solução DASH mais curta possível, mas a solução DASH mais curta possível está me incomodando. Estou postando essa nova abordagem em seu lugar.

Uso:

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

Explicação

@(                 #. 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
fonte
2

Scala, 25 bytes

l=>l.reverse:+0 indexOf 0

Ungolfed:

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

Inverte a lista, acrescenta um 0 e encontra o primeiro índice de 0, que é o número de elementos antes do primeiro 0

corvus_192
fonte
2

Lote, 57 bytes

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

Recebe a entrada como parâmetros da linha de comando. Funciona multiplicando o acumulador pelo valor atual antes de adicioná-lo, para que quaisquer zeros na linha de comando redefinam a contagem. Observe que %%nnão é o mesmo que nou %n%variável.

Neil
fonte
2

GolfSharp, 14 bytes

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

Java 7, 62 bytes

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

Ungolfed & código de teste:

Experimente aqui.

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

Resultado:

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

Perl 5.10, 22 bytes

21 bytes + 1 byte para -asinalizador. Desde que a expressão baseada em regex foi feita ...: p

Os valores de entrada para a matriz devem ser separados por um espaço.

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

Experimente online!

Paul Picard
fonte
11
Ligeiramente mais curto se você tomar argumentos via linha de comando: perl -E '$_++while pop;say' 0 1 1 0 1 1 1mas isto não faz nada saída para 0(não sei se isso é um problema embora!)
Dom Hastings
2

Perl, 22 bytes

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

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

Para executá-lo:

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

(Na verdade, o formato da entrada não importa muito: 0110111, 0 1 1 0 1 1 1, [0,1,1,0,1,1,1]etc. faria todo o trabalho)


Versão de 18 bytes do @Dom Hastings, mas é necessário fornecer a entrada como uma sequência de 0 e 1, o que não é permitido:

perl -pE '/1*$/;$_=length$&' <<< '0110111'
dada
fonte
Amor que ;truque :) Se format é uma seqüência contínua: perl -pE '/1*$/;$_=length$&' <<< '0110111'para 18, não tenho certeza se isso é quebrar as regras ou não embora ...
Dom Hastings
@DomHastings sim, eu também! (Obrigado Ton por me mostrar isso!) O primeiro e o segundo comentários da pergunta não permitem o formato de entrada necessário para sua solução ... Mas vou editar meu post para sugerir sua versão, se o formato da entrada for mais livre.
Dada
2

PHP, 50 bytes

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

Estranhamente, minha primeira tentativa com um regex acabou sendo mais curta do que minha tentativa com matrizes ...
Use como:

php tt.php 1 1 0 1 1
user59178
fonte
2

Ruby 37 32 bytes

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

Cria uma função anônima que encontra a instância mais à direita de um valor falso e conta o tamanho da sub-matriz iniciando nesse valor.

Ele usa !0como false, como 0 são valores verdadeiros no Ruby. rindexlocaliza o último índice de um valor em uma matriz.

Uso :

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

Retorna 1


Se me permitissem passar uma sequência de 0s e 1s como parâmetros de linha de comando (que não é como o ruby ​​representa listas de booleanos), eu poderia reduzi-lo para 24:

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

Isso usa expressões regulares e imprime o comprimento da string retornada pela expressão regular /(1*)\z/, onde \zé o final da string. $*[0]é o primeiro argumento passado e é uma sequência de 0s e 1s.

Uso:

trailing_truths.rb 011101

Retorna 1.

IMP1
fonte
11
Depois de ter o índice do último valor falso, por que você precisa recuperar elementos da matriz novamente?
Lee W
Você está certo, eu não. Obrigado. 5 bytes de desconto!
IMP1