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


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 .


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


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

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.


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
}

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

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.


"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

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




7

Mathematica, 25 24 bytes

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

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


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


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.


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

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.


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.



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


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]

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
)

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


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.



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

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!


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'

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

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.