Contagem eficiente

35

Quando eu era criança, e queria contar as notas de dólar em minhas economias, eu contava em voz alta:

um dois três quatro cinco seis sete oito nove dez;
onze, doze, treze, quatorze, quinze, dezesseis, dezessete, dezoito, dezenove, vinte;
vinte e um, vinte e dois, vinte e três, vinte e quatro, vinte e cinco ...

Por fim, cansei de pronunciar cada um desses números com várias sílabas. Sendo matemático, criei um método muito mais eficiente de contar:

um dois três quatro cinco seis sete oito nove dez;
um, dois, três, quatro, cinco, seis, sete, oito, nove, vinte;
um, dois, três, quatro, cinco, seis, sete, oito, nove, trinta ...

Como você pode ver, eu pronunciaria apenas os dígitos que foram alterados em relação ao número anterior. Isso tem a vantagem adicional de ser consideravelmente mais repetitivo do que os nomes em inglês para números e, portanto, requer menos inteligência para ser computado.

Desafio

Escreva um programa / função que receba um número inteiro positivo e produza / retorne como eu contaria: ou seja, o dígito diferente de zero e o zero à direita.

Exemplos

   1    1
   2    2
  10   10
  11    1
  29    9
  30   30
  99    9
 100  100
 119    9
 120   20
 200  200
 409    9
1020   20

Uma lista completa de casos de teste não deve ser necessária. Este é o A274206 no OEIS.

Regras

  • Teoricamente, sua entrada deve funcionar para todos os números inteiros positivos, ignorando problemas de precisão e memória.
  • A entrada e a saída devem estar em decimal.
  • Você pode optar por receber entrada e / ou saída como um número, uma sequência ou uma matriz de dígitos.
  • A entrada é garantida como um número inteiro positivo. Sua entrada pode fazer qualquer coisa para entrada inválida.

Isso é , então o código mais curto em bytes vence.

ETHproductions
fonte
Então "in decimal" inclui uma lista de dígitos decimais, como [1,0,2,0]-> [2,0]para o último caso de teste? (Não estou claro na frase "matriz de item único").
Jonathan Allan
11
@ JonathanAllan Por "matriz de item único", eu quis dizer uma matriz que contém um único número ou string que representa o número inteiro. Eu não achei que permitir matrizes de dígitos fosse uma boa idéia, mas agora parece uma restrição arbitrária, pois as strings são permitidas (e as strings são muito semelhantes às matrizes em vários idiomas). Portanto, permitirei uma matriz de dígitos, a menos que haja um bom motivo para não fazê-lo.
ETHproductions
5
Caramba, você roubou meu segredo: P
LegionMammal978 22/02
11
Eu acho que quase todo mundo contava assim quando criança. ;) Pelo menos eu fiz também. :)
Kevin Cruijssen 22/02
7
@KevinCruijssen "quando criança"?
Martin Ender

Respostas:

19

Python 2 , 28 bytes

f=lambda n:n%10or 10*f(n/10)

Experimente online!

Uma fórmula recursiva funciona muito bem. Se o último dígito for diferente de zero, faça a saída. Caso contrário, remova o zero final, calcule a saída para isso e multiplique por 10.

xnor
fonte
11

Gelatina , 6 3 bytes

-3 bytes, tendo E / S como uma lista decimal de dígitos .

ṫTṪ

Conjunto de testes em Experimente online!

Quão?

ṫTṪ - Main link: listOfDigits  e.g.  [1,    0,    2,    0]  or [1,      1,    9  ]
 T  - truthy indexes                 [1,          3      ]     [1,      2,    3  ]
ṫ   - tail (vectorises)              [[1,0,2,0],  [2,0]  ]     [[1,1,9],[1,9],[9]]
  Ṫ - tail pop                                    [2,0]                       [9]

Se não pudéssemos obter listas decimais, um byter de 6 é:

DµṫTṪḌ

Que você pode ver aqui .

Isso faz a mesma coisa, mas converte um número inteiro em uma lista decimal anteriormente e depois converte novamente em um número inteiro.

Jonathan Allan
fonte
Enquanto passava pelas primeiras respostas, perguntei a mim mesmo: "Aposto que há uma solução de geléia de 3 bytes ..."
DLosc 23/02/17
9

C, 30 29 27 bytes

Orgulhoso disso, porque eu abusei de dois exploits C para melhorar isso (descrito no final do post); Isto é especificamente para C (GCC)


3) b=10;f(a){a=a%b?:b*f(a/b);}// 27 bytes

2) b;f(a){b=a=a%10?:10*f(a/10);}// 29 bytes

1) f(i){return i%10?:10*f(i/10);}// 30 bytes

Experimente online (versão de 27 bytes)


Primeira tentativa (30 bytes): Abusa do fato de que, no GCC, se nenhum valor for declarado em nível ternário, o valor condicional será retornado. Por isso, meu operador ternário está em branco para o valor de retorno da verdade.

Segunda tentativa (29 bytes): Abusa do bug de memória no GCC, onde, até onde eu entendi, se uma função não tem valor de retorno, quando mais de duas variáveis ​​foram utilizadas significativamente na função, o último valor definido da primeira variável de argumento será retornado.
   (Editar: mas esse "valor definido" deve ser definido de determinadas maneiras, por exemplo, definir uma variável com =ou +=funciona, mas configurá-la com %=não funciona; estranho)

Terceira tentativa (27 bytes): Como devo utilizar de maneira significativa a segunda variável (b) para abusar adequadamente do erro de memória mencionado acima, também posso usá-lo como uma variável real para "10" para substituição.
   (Nota: Eu deveria ser capaz de trocar a=a%bcom a%=bpara salvar outro byte mas infelizmente isso faz com que o bug de memória explorar acima para stop "de trabalho", então eu não posso)

Albert Renshaw
fonte
Convém adicionar "GCC" ao título da sua resposta, pois é específico do GCC (não funciona no clang). Além disso, o "erro de memória" provavelmente é apenas um comportamento indefinido que funciona devido ao layout específico do quadro de pilha usado pelo GCC. Provavelmente não funciona em outras plataformas, mesmo com o GCC.
simon
@gurka Feito, obrigado
Albert Renshaw
7

Retina , 7 6 bytes

!`.0*$

Experimente online (todos os casos de teste)

Correspondências de saída de um dígito seguidas por zeros no final da sequência de entrada. Embora não seja obrigatório, isso também funciona 0.

mbomb007
fonte
Huh, eu imaginei [1-9](ou [^0]) seria necessário em vez de \d. Eu acho que a ganância *garante sempre a saída correta.
ETHproductions
@ETHproductions Isso não tem nada a ver com a ganância, *mas com o fato de que as correspondências são pesquisadas da esquerda para a direita. \d0*?$também funcionaria.
Martin Ender
usando o regex .0*$deve funcionar # 12
21/21
Se houver uma maneira (curta o suficiente) de produzir apenas a última correspondência, você poderá usar.0*
12Me21 21/21/17 /
@ 12Me21 A única maneira de fazer isso é corresponder apenas à última ocorrência ou usar uma substituição ou algo assim. Não será mais curto.
mbomb007
7

Cubix , 18 32 bytes

Acho que vou ter que gastar algum tempo nisso mais tarde e ver se consigo comprimir um pouco. Mas, por enquanto, aqui está.
Acontece que eu estava pensando sobre isso totalmente da maneira errada. Agora, o processo aplica incrementalmente um mod (1,10,100,1000, ...) ao número inteiro de entrada e imprime o primeiro que não é zero. Um pouco mais chato, mas mais curto.

!N%*I1^\.u;u@O\;;r

Experimente aqui

    ! N
    % *
I 1 ^ \ . u ; u
@ O \ ; ; r . .
    . .
    . .
MickyT
fonte
Sempre bom ver uma resposta Cubix :)
Oliver
@obarakon Conseguiu um melhorado para colocar em breve. Realmente este o caminho errado
MickyT
5

JavaScript, 21 bytes

f=n=>n%10||10*f(n/10)

Casos de teste

Oliver
fonte
5

Javascript 19 18 bytes

Graças à ETHproductions por jogar fora um byte e Patrick Roberts por jogar fora dois bytes

x=>x.match`.0*$`

Retorna uma matriz de cadeias que corresponde ao regex de estar no final da cadeia de entrada com qualquer caractere seguido pelo maior número possível de zeros.

Experimente Online

fəˈnɛtɪk
fonte
5
Acho que você não precisa g, pois há apenas uma partida para encontrar.
ETHproductions
Salve 2 bytes usandox=>x.match`.0*$`
Patrick Roberts
3

Bash + coreutils, 12

grep -o .0*$

Experimente online .

Trauma Digital
fonte
3

Grime , 5 bytes

d\0*e

Experimente online!

Explicação

       Find the longest substring of the input matching this pattern:
d      a digit, then
 \0*   zero or more 0s, then
    e  edge of input (which is handled as an Nx1 rectangle of characters).
Zgarb
fonte
3

Braquilog , 2 bytes

a₁

Experimente online!

O sufixo interno a₁, para números inteiros, é implementado como:

brachylog_adfix('integer':1, 'integer':0, 'integer':0).
brachylog_adfix('integer':1, 'integer':I, 'integer':P) :-
    H #\= 0,
    H2 #\= 0,
    abs(P) #=< abs(I),
    integer_value('integer':Sign:[H|T], I),
    integer_value('integer':Sign:[H2|T2], P),
    brachylog_adfix('integer':1, [H|T], [H2|T2]).

O Brachylog gosta de poder tratar números inteiros como listas de dígitos e, para isso, usa o predicado de utilitário personalizado integer_value/2. O interessante integer_value/2aqui é que, como ele deve ser capaz de traduzir corretamente uma lista de dígitos com zeros à esquerda, ele também pode traduzir um número inteiro para uma lista de dígitos com zeros à frente, portanto predicados que não querem que isso acontecem (a maioria deles, especialmente os que não são do tipo eterno a) proíbem que as cabeças de suas listas de dígitos sejam 0. Portanto, embora a₁gere os sufixos mais curtos primeiro para listas e seqüências de caracteres, ignora qualquer sufixo de um número inteiro com um 0 inicial, que em Além de remover duplicatas, também significa que o primeiro sufixo gerado é o dígito diferente de zero à direita com todos os zeros à direita.

String não relacionada
fonte
2

Flacidez Cerebral , 74 bytes

{({}<>)<>}(()){{}<>(({}<>)[((((()()()){}){}){}){}]<(())>){((<{}{}>))}{}}{}

Experimente online!

Imprime apenas o último não-0 e todos os 0s à direita.

Explicação:

{({}<>)<>}                    # Move everything to the other stack (reverse the input)
(())                          # Push a 1 to get started
{                             # do...
  {}<>                        #   pop the result of the equals check (or initial 1)
  (                           #   push...
    ({}<>)                    #     the top value from the other stack (also put this on the stack)
    [((((()()()){}){}){}){}]  #     minus the ASCII value of 0
    <(())>                    #     on top of a 1
  )                           #   close the push   
  {                           #   if not zero (ie. if not equal)
    ((<{}{}>))                #     replace the 1 from 3 lines back with a 0
  }{}                         #   end if and pop the extra 0
}                             # while the copied value != "0"
{}                            # pop the result of the equals check
Riley
fonte
2

Vim, 19 bytes

Duas versões, ambas com 19 bytes:

:s/\v.*([^0]0*)/\1
:s/.*\([^0]0*\)/\1

Além de um retorno de carro à direita em cada um.

Verifique todos os casos de teste online! (Um byte adicionado para testar em várias linhas)

DJMcMayhem
fonte
2

TI-Basic, 18 bytes

If fPart(.1Ans
Return
Ans.1
prgmA
10Ans
Timtech
fonte
2

R, 33 bytes

Implementado como uma função sem nome

function(x)rle(x%%10^(0:99))$v[2]

Isso aplica um mod de 10 ^ 0 a 10 ^ 99. rleé usado para reduzir os resultados, para que o segundo item seja sempre o resultado que queremos.
Experimente online!

MickyT
fonte
2

Zsh , 18 16 bytes

<<<${(M)1%[^0]*}

Experimente online! Experimente online!

Bash , 25 bytes

r=${1%[^0]*}
echo ${1#$r}

Experimente online!


Os shells precisam chamar programas externos para usar o regex, então temos que nos contentar com globbing.

A ${1%[^0]*}expansão corresponde ao sufixo mais curto, começando com um caractere diferente de zero, e o remove.

  • No Zsh, adicionar o (M)sinalizador faz com que o sufixo correspondente seja mantido em vez de removido.
  • No Bash, a ${1% }expansão remove como prefixo o que resta.
GammaFunction
fonte
1

GNU sed , 17 14 + 1 (sinalizador r) = 15 bytes

Edit: 2 bytes a menos, graças a Riley

s:.*([^0]):\1:

Ele funciona excluindo tudo até o dígito diferente de zero, à direita, que é impresso juntamente com os zeros à direita existentes. O script pode manipular vários testes em uma execução, cada um em uma linha separada.

Experimente online! (todos os exemplos de teste)

seshoumara
fonte
1

Mathematica, 26 bytes

Função pura que pega uma lista de dígitos e gera uma lista de dígitos:

#/.{___,x_,y:0...}:>{x,y}&

Explicação

#                           First argument
 /.                           Replace
   {                              start of list followed by
    ___,                          zero or more elements followed by
        x_,                       an element (referred to later as x) followed by
           y:0...                 a sequence of zero or more 0s (referred to later as y) followed by
                 }                end of list
                  :>            with
                    {x,y}         {x,y}
                         &   End of function.

Isso funciona, pois encontra a correspondência mais à esquerda para x, que deve ser o elemento diferente de zero à direita da lista, pois é seguida por uma sequência de zero ou mais 0se o final da lista.

ngenisis
fonte
1

Java 8, 47 bytes

esta é uma expressão lambda atribuível a IntUnaryOperator:

x->{int m=1;for(;x%m<1;m*=10);return x%m*m/10;}

explicação: multiplique m por 10 até que x%mnão seja 0. return x%m*m/10requer a divisão porque m é uma ordem de magnitude maior que o resultado desejado.

Jack Munição
fonte
1

Perl 6 , 10 bytes

{+m/.0*$/}

Solução regex trivial. Insere e gera um número.

smls
fonte
1

MATL , 10 7 bytes

3 bytes salvos graças a @B. Mehta!

tfX>Jh)

Entrada e saída são uma matriz de dígitos.

Experimente online!

Ou verifique todos os casos de teste .

Explicação

t     % Input string implicitly. Duplicate
f     % Push indices of non-zero digits
X>    % Keep maximum, say k
Jh    % Attach 1j to give [k, 1j]. This is interpreted as an index "k:end"
)     % Index into original string. Display implcitly
Luis Mendo
fonte
Como podemos receber entrada e saída como um vetor de números inteiros, você pode remover os 48-3 bytes inteiros, economizando: Experimente online!
B. Mehta
1

C #, 30 28 bytes

Com base nesta resposta JavaScript , suponho que todos os créditos sejam para ele.

Golfe

i=a=>a%10<1?10*i(a/10):a%10;
  • -2 bytes removendo ()ao redor agraças a Emigna
Metoniem
fonte
11
Eu acho que você precisa nomear explicitamente a função ipara que isso funcione enquanto você está usando a recursão.
Emigna
@Emigna, você está certo! Eu
realmente
Atualizei-o, mas não tenho 100% de certeza se está correto dessa maneira.
Metoniem 22/02
11
Eu não sei o consenso sobre isso em c #. Essa sintaxe é válida, mas só funcionará se o delegado já tiver sido declarado (caso contrário i, não será declarado para a chamada recursiva).
Emigna
11
Os parênteses ao redor anão são necessários de qualquer maneira.
Emigna
1

J, 27 bytes

10&|`(10*(p%&10))@.(0=10&|)

É baseado na fórmula do xnor, então credita a ele.

Blocos
fonte
1

Kotlin, 49 bytes

lambda, atribuível a (List<Int>) -> List<Int>

{a->a.slice(a.indexOfLast{it in 1..9}..a.size-1)}
  • nome implícito do parâmetro itemindexOfLast
  • .. para construção de faixas
succcubbus
fonte
1

Perl 5, 12 bytes

11, mais 1 para em -nEvez de-e

say/(.0*$)/
msh210
fonte
1

05AB1E , 9 bytes

RD0Ê1k>£R

Experimente online! ou como um conjunto de testes

Explicação

R          # reverse input
 D         # duplicate
  0Ê       # check each for inequality with 0
    1k     # get the index of the first 1
      >    # increment
       £   # take that many digits from the input
        R  # reverse
Emigna
fonte
Experimente online! - 6 bytes
Magic Octopus Urn
Ou 5 - Experimente online!
Magia Octopus Urna
@MagicOctopusUrn: Isso está apenas checando o último dígito. Deve ser o último dígito diferente de zero e depois de tudo.
Emigna
1

Stax , 5 bytes

æΩ$3╚

Execute e depure

Procedimento:

  1. Calcule "multiplicidade" por 10. (Esse é o número de vezes que 10 divide a entrada igualmente)
  2. Adicione 1.
  3. Mantenha tantos caracteres à direita de (a entrada como uma sequência).
recursivo
fonte
1

05AB1E , 4 bytes

ĀÅ¡θ

E / S como uma lista de dígitos.

Experimente online ou verifique todos os casos de teste (o conjunto de testes contém uma junção para melhor legibilidade).

Explicação:

Ā     # Python-style truthify each digit in the (implicit) input-list (0 if 0; 1 if [1-9])
      #  i.e. [9,0,4,0,3,0,0] → [1,0,1,0,1,0,0]
 Å¡   # Split the (implicit) input-list on truthy values (1s)
      #  i.e. [9,0,4,0,3,0,0] and [1,0,1,0,1,0,0] → [[],[9,0],[4,0],[3,0,0]]
   θ  # And only leave the last inner list
      #  i.e. [[],[9,0],[4,0],[3,0,0]] → [3,0,0]
      # (after which it is output implicitly as result)
Kevin Cruijssen
fonte
0

Haskell 57 Bytes

f(x:s)a|x=='0'=f s$'0':a|1>0=x:a
t x=f(reverse.show$x)[]

Input    -> Output
t 120    -> "20"
t 30200  -> "200"
brander
fonte