Recuento eficiente

35

Cuando era niño y quería contar los billetes de un dólar en mis ahorros de toda la vida, contaba en voz alta:

uno dos tres CUATRO CINCO SEIS SIETE OCHO NUEVE DIEZ;
once, doce, trece, catorce, quince, dieciseis, diecisiete, dieciocho, diecinueve, veinte;
veintiuno, veintidos, veintitres, veinticuatro, veinticinco ...

Finalmente me cansé de pronunciar cada uno de estos números de múltiples sílabas. Con una mentalidad matemática, creé un método mucho más eficiente de contar:

uno dos tres CUATRO CINCO SEIS SIETE OCHO NUEVE DIEZ;
uno, dos, tres, cuatro, cinco, seis, siete, ocho, nueve, veinte;
uno, dos, tres, cuatro, cinco, seis, siete, ocho, nueve, treinta ...

Como puede ver, solo pronunciaría los dígitos que han cambiado desde el número anterior. Esto tiene la ventaja adicional de que es considerablemente más repetitivo que los nombres en inglés para los números y, por lo tanto, requiere menos capacidad intelectual para calcular.

Reto

Escriba un programa / función que tome un número entero positivo y arroje / devuelva cómo lo contaría: es decir, el dígito más a la derecha que no sea cero y todos los ceros finales.

Ejemplos

   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

No debería ser necesaria una lista completa de casos de prueba. Este es A274206 en OEIS.

Reglas

  • Su entrada debe funcionar teóricamente para todos los enteros positivos, ignorando la precisión y los problemas de memoria.
  • La entrada y la salida deben estar en decimal.
  • Puede optar por tomar la entrada y / o salida como un número, una cadena o una matriz de dígitos.
  • Se garantiza que la entrada sea un número entero positivo. Su entrada puede hacer cualquier cosa por entrada no válida.

Este es el , por lo que gana el código más corto en bytes.

ETHproducciones
fuente
Entonces, ¿"en decimal" incluye una lista de dígitos decimales, como [1,0,2,0]-> [2,0]para el último caso de prueba? (No estoy claro en la frase "matriz de un solo elemento").
Jonathan Allan
1
@JonathanAllan Por "matriz de un solo elemento" me refería a una matriz que contiene un único número o cadena que representa el número entero. No pensé que permitir matrices de dígitos fuera una buena idea, pero ahora parece una restricción arbitraria ya que las cadenas están permitidas (y las cadenas son muy similares a las matrices en muchos idiomas). Así que permitiré una serie de dígitos a menos que haya una buena razón para no hacerlo.
ETHproductions
55
Maldita sea, robaste mi secreto: P
LegionMammal978
1
Creo que casi todos contaban así como un niño. ;) Al menos yo también. :)
Kevin Cruijssen
77
@KevinCruijssen "como un niño"?
Martin Ender

Respuestas:

19

Python 2 , 28 bytes

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

Pruébalo en línea!

Una fórmula recursiva funciona muy limpiamente. Si el último dígito no es cero, imprímalo. De lo contrario, elimine el cero final, calcule la salida para eso y multiplíquelo por 10.

xnor
fuente
11

Gelatina , 6 3 bytes

-3 bytes al tener E / S como una lista decimal de dígitos .

ṫTṪ

Conjunto de pruebas en Pruébelo en línea!

¿Cómo?

ṫ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]

Si no pudiéramos tomar listas decimales, un byte de 6 es:

DµṫTṪḌ

Que puedes ver aquí .

Esto hace lo mismo, pero convierte de antemano un número entero en una lista decimal y luego lo convierte nuevamente en un número entero.

Jonathan Allan
fuente
Mientras pasaba las primeras respuestas, me dije: "Apuesto a que hay una solución Jelly de 3 bytes ..."
DLosc
9

C, 30 29 27 bytes

Orgulloso de esto, ya que abuso de dos exploits C para jugar golf (descrito al final de la publicación); Esto es específicamente 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

Pruébelo en línea (versión de 27 bytes)


Primer intento (30 bytes): Abusa del hecho de que en GCC si no se declara ningún valor en ternario, se devolverá el valor condicional. Por eso mi operador ternario está en blanco para el valor de retorno de verdad.

Segundo intento (29 bytes): Abusa del error de memoria en GCC donde, por lo que entiendo, si una función no tiene valor de retorno, cuando más de dos variables se han utilizado de manera significativa en la función, el último valor establecido de la primera variable de argumento Será devuelto.
   (Editar: pero este "valor establecido" debe establecerse de ciertas maneras, por ejemplo, establecer una variable con =o +=funciona pero establecerlo con %=no funciona; extraño)

Tercer intento (27 bytes): como de todos modos debo utilizar significativamente la segunda variable (b) para abusar adecuadamente del error de memoria mencionado anteriormente, también puedo usarlo como una variable real para "10" para la sustitución.
   (Nota: yo debería ser capaz de cambiar a=a%bcon a%=bsalvar otro byte pero lamentablemente esto hace que el fallo de memoria por encima de explotar a la parada de "trabajo", por lo que no se puede)

Albert Renshaw
fuente
Es posible que desee agregar "GCC" al título de su respuesta, ya que es específico de GCC (no funciona en clang). Además, el "error de memoria" es probablemente un comportamiento indefinido que funciona debido al diseño específico del marco de pila que utiliza GCC. Probablemente no funcione en otras plataformas, incluso con GCC.
Simon
@gurka Hecho, gracias
Albert Renshaw
7

Retina , 7 6 bytes

!`.0*$

Pruébalo en línea (todos los casos de prueba)

Las coincidencias de salida de un dígito seguidas de ceros al final de la cadena de entrada. Aunque no es obligatorio, esto también funciona 0.

mbomb007
fuente
Huh, pensé que [1-9](o [^0]) sería necesario en lugar de \d. Supongo que la avaricia de *asegura la salida correcta cada vez.
ETHproductions
@ETHproductions Esto no tiene nada que ver con la codicia *sino con el hecho de que se buscan coincidencias de izquierda a derecha. \d0*?$También funcionaría.
Martin Ender
usar la expresión regular .0*$debería funcionar
12Me21
Si hay una forma (lo suficientemente corta) de generar solo la última coincidencia, puede usar.0*
12Me21
@ 12Me21 La única forma de hacerlo es hacer coincidir la última aparición, o usar un reemplazo o algo así. No será más corto
mbomb007
7

Cubix , 18 32 bytes

Creo que tendré que pasar algún tiempo más tarde para ver si puedo comprimirlo un poco. Pero por el momento aquí está.
Resulta que estaba pensando en esto totalmente al revés. Ahora el proceso aplica incrementalmente un mod (1,10,100,1000, ...) al entero de entrada e imprime el primero que no es cero. Un poco más aburrido, pero más corto.

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

Pruébalo aquí

    ! N
    % *
I 1 ^ \ . u ; u
@ O \ ; ; r . .
    . .
    . .
MickyT
fuente
Siempre es bueno ver una respuesta de Cubix :)
Oliver
@obarakon Tengo una mejorada para poner pronto. Realmente hice esto de la manera incorrecta
MickyT
5

JavaScript, 21 bytes

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

Casos de prueba

Oliver
fuente
5

Javascript 19 18 bytes

Gracias a ETHproductions por jugar golf en un byte y Patrick Roberts por jugar golf en dos bytes

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

Devuelve una matriz de cadenas que coinciden con la expresión regular de estar al final de la cadena de entrada con cualquier carácter seguido del mayor número posible de ceros.

Pruébalo en línea

fəˈnɛtɪk
fuente
55
No creo que necesites g, ya que solo hay una coincidencia para encontrar.
ETHproductions
Ahorre 2 bytes usandox=>x.match`.0*$`
Patrick Roberts
3

Mugre , 5 bytes

d\0*e

Pruébalo en línea!

Explicación

       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
fuente
3

Brachylog , 2 bytes

a₁

Pruébalo en línea!

El sufijo incorporado a₁, para enteros, se implementa 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]).

A Brachylog le gusta poder tratar los enteros como listas de dígitos, y para eso usa el predicado de utilidad personalizado integer_value/2. Lo interesante de integer_value/2esto es que, dado que tiene que ser capaz de traducir correctamente una lista de dígitos con ceros a la izquierda, también puede traducir un número entero a una lista de dígitos con ceros a la izquierda, por lo que predicados que no quieren que suceden (la mayoría de ellos, especialmente los que no son dedet. a) prohíben que los encabezados de sus listas de dígitos sean 0. Entonces, mientras a₁genera sufijos más cortos primero para listas y cadenas, omite cualquier sufijo de un entero con un 0 inicial, que en Además de eliminar duplicados, también significa que el primer sufijo generado es el dígito que no es cero a la derecha con todos los ceros finales.

Cadena no relacionada
fuente
2

Brain-Flak , 74 bytes

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

Pruébalo en línea!

Solo imprime los últimos 0 que no son 0 y todos los ceros finales.

Explicación:

{({}<>)<>}                    # 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
fuente
2

TI-Basic, 18 bytes

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

R, 33 bytes

Implementado como una función sin nombre

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

Esto aplica un mod de 10 ^ 0 a 10 ^ 99. rlese usa para reducir los resultados hacia abajo para que el segundo elemento sea siempre el resultado que queremos.
Pruébalo en línea!

MickyT
fuente
2

Zsh , 18 16 bytes

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

Pruébalo en línea! Pruébalo en línea!

Golpetazo , 25 bytes

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

Pruébalo en línea!


Los shells necesitan llamar a programas externos para usar regex, por lo que tenemos que conformarnos con globing.

los ${1%[^0]*} expansión coincide con el sufijo más corto que comienza con un carácter distinto de cero y lo elimina.

  • En Zsh, agregar la (M)bandera hace que el sufijo coincidente se mantenga en lugar de eliminarse.
  • En Bash, la ${1% }expansión elimina como prefijo lo que queda.
Función Gamma
fuente
1

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

Editar: 2 bytes menos gracias a Riley

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

Funciona eliminando todo hasta el dígito de la derecha que no sea cero, que luego se imprime junto con los ceros finales existentes. El script puede manejar múltiples pruebas en una ejecución, cada una en una línea separada.

Pruébalo en línea! (todos los ejemplos de prueba)

seshoumara
fuente
1

Mathematica, 26 bytes

Función pura que toma una lista de dígitos y genera una lista de dígitos:

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

Explicación

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

Esto funciona ya que encuentra la coincidencia más a la izquierda para x, que debe ser el elemento distinto de cero a la derecha de la lista, ya que es seguido por una secuencia de cero o más 0sy luego el final de la lista.

ngenisis
fuente
1

Java 8, 47 bytes

Esta es una expresión lambda asignable a IntUnaryOperator:

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

explicación: multiplique m por 10 hasta x%mque no sea 0. return x%m*m/10requiere la división porque m es un orden de magnitud mayor que el resultado deseado.

Jack munición
fuente
1

Perl 6 , 10 bytes

{+m/.0*$/}

Solución trivial de expresiones regulares. Introduce y emite un número.

smls
fuente
1

MATL , 10 7 bytes

3 bytes guardados gracias a @B. Mehta!

tfX>Jh)

La entrada y la salida son una matriz de dígitos.

Pruébalo en línea!

O verificar todos los casos de prueba .

Explicación

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
fuente
Como se nos permite tomar entradas y salidas como un vector de enteros, puede eliminarlos por 48-completo, ahorrando 3 bytes: ¡ Pruébelo en línea!
B. Mehta
1

C #, 30 28 bytes

Basado en esta respuesta de JavaScript , así que supongo que todos los créditos van a él.

Golfed

i=a=>a%10<1?10*i(a/10):a%10;
  • -2 bytes eliminando ()alrededor agracias a Emigna
Metoniem
fuente
1
Creo que debe nombrar explícitamente la función ipara que esto funcione mientras usa la recursividad.
Emigna
@Emigna tienes razón! Lo extrañé por completo :(
Metoniem
Lo
actualicé
1
No sé el consenso sobre esto en C #. Esa sintaxis es válida, pero solo funcionará si el delegado ya ha sido declarado (de lo contrario i, no se declarará para la llamada recursiva).
Emigna
1
Sin aembargo, el paréntesis no se requiere de ninguna manera.
Emigna
1

J, 27 bytes

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

Se basa en la fórmula de xnor, así que le damos crédito.

Bloques
fuente
1

Kotlin, 49 bytes

lambda, asignable a (List<Int>) -> List<Int>

{a->a.slice(a.indexOfLast{it in 1..9}..a.size-1)}
  • nombre de parámetro implícito itenindexOfLast
  • .. para construir gamas
succcubbus
fuente
1

Perl 5, 12 bytes

11, más 1 para en -nElugar de-e

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

05AB1E , 9 bytes

RD0Ê1k>£R

Pruébalo en línea! o como un conjunto de pruebas

Explicación

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
fuente
Pruébalo en línea! - 6 bytes
Urna de pulpo mágico
O 5 - ¡ Pruébelo en línea!
Urna mágica de pulpo
@MagicOctopusUrn: Eso solo verifica el último dígito. Debe ser el último dígito distinto de cero y todo posterior.
Emigna
1

Stax , 5 bytes

æΩ$3╚

Ejecutar y depurarlo

Procedimiento:

  1. Calcule "multiplicidad" por 10. (Esa es la cantidad de veces que 10 divide la entrada de manera uniforme)
  2. Añadir 1.
  3. Mantenga tantos caracteres a la derecha de (la entrada como una cadena).
recursivo
fuente
1

05AB1E , 4 bytes

ĀÅ¡θ

E / S como una lista de dígitos.

Pruébelo en línea o verifique todos los casos de prueba (el conjunto de pruebas contiene una combinación para una mejor legibilidad).

Explicación:

Ā     # 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
fuente
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
fuente