Persistencia Aditiva


20

El código más corto para pasar todas las posibilidades gana.

En matemáticas, la persistencia de un número mide cuántas veces se debe aplicar una determinada operación a sus dígitos hasta que se alcanza cierta condición fija. Puede determinar la persistencia aditiva de un entero positivo sumando los dígitos del entero y repitiendo. Seguiría sumando los dígitos de la suma hasta que se encuentre un número de un solo dígito. El número de repeticiones que tomó para alcanzar ese número de un solo dígito es la persistencia aditiva de ese número.

Ejemplo usando 84523:

84523
8 + 4 + 5 + 2 + 3 = 22
2 + 2 = 4

It took two repetitions to find the single digit number.
So the additive persistence of 84523 is 2.

Se le dará una secuencia de enteros positivos de los que deberá calcular la persistencia aditiva. Cada línea contendrá un número entero diferente para procesar. La entrada puede estar en cualquier método de E / S estándar .

Para cada número entero, debe generar el número entero, seguido de un solo espacio, seguido de su persistencia aditiva. Cada entero procesado debe estar en su propia línea.

Casos de prueba


De entrada y salida

99999999999 3
10 1
8 0
19999999999999999999999 4
6234 2
74621 2
39 2
2677889 3
0 0

1
Sus casos de prueba incluyen algunos valores que están por encima de 2 ^ 64, y su especificación dice que el programa solo tiene que manejar valores de hasta 2 ^ 32. Puede valer la pena aclarar eso.
Peter Taylor

@ Peter Taylor, olvidé eliminar esos límites. Si un programa puede manejar la entrada que he proporcionado, no debería tener un problema con los límites.
Kevin Brown

55
¿No es la persistencia de 999999999999 2 en lugar de 3?
Eelvex

@Evelex, supongo que fue un cambio incorrecto de última hora. Fijo.
Kevin Brown

Varias respuestas aquí no están dando salida en stdout sino que usan la salida "interactiva" de J devolviendo resultados después de tomar la entrada de la línea de comandos. (Esto incluye otras 2 respuestas J y, supongo, la respuesta K). ¿Se considera esto legítimo? Porque puedo arrojar caracteres de 18 ish si es así.
Jesse Millikan

Respuestas:


6

K - 29 caracteres

La entrada es un nombre de archivo pasado como argumento, 29 caracteres sin incluir el nombre de archivo.

`0:{5:x,-1+#(+/10_vs)\x}'.:'0:"file"
  • 35 -> 31: Eliminar la función exterior.
  • 31 -> 29: Eliminar parens.

1
-1+#=>#1_
streetter

4

Python 84 Chars

while 1:
 m=n=int(raw_input());c=0
 while n>9:c+=1;n=sum(map(int,str(n)))
 print m,c

Caso de desafío: 06234.. resultado desafío exitoso :-)
Quixotic

@Debanjan Gracias. Corregido
fR0DDY


4

Python (93 bytes)

f=lambda n,c:n>9and f(sum(map(int,str(n))),c+1)or c
while 1:n=int(raw_input());print n,f(n,0)

Creo que puede eliminar el espacio entre 9y err ...and
st0le

@ st0le: Gracias :-)
Quixotic

y en input()lugar de int(raw_input())....
st0le

@ st0le: Pruebe esta entrada con esa modificación: 06234.
Quixotic

4

Casco , 10 15 bytes

+5 bytes para requisitos de E / S horribles

m(wΓ·,LU¡oΣdr)¶

Pruébalo en línea!

Explicación

Para admitir múltiples entradas, necesitamos usar m(₁r)¶(¿dónde está la función haciendo el cálculo interesante?):

m(₁r)¶  -- expects newline-separated inputs: "x₁␤x₂␤…␤xₙ"
     ¶  -- split on newlines: ["x₁","x₂",…,"xₙ"]
m(  )   -- map over each string
 ( r)   -- | read integer: [x₁,x₂,…,xₙ]
 (₁ )   -- | apply the function described below

La función hace lo siguiente:

wΓ·,LU¡(Σd)  -- input is an integer, eg: 1234
      ¡(  )  -- iterate the following forever and collect results in list:
       ( d)  -- | digits: [1,2,3,4]
       (Σ )  -- | sum: 10
             -- : [1234,10,1,1,1,…
     U       -- keep longest prefix until repetition: [1234,10,1]
 Γ           -- pattern match (x = first element (1234), xs = tail ([10,1])) with:
  · L        -- | length of xs: 2
   ,         -- | construct tuple: (1234,2)
w            -- join with space: "1234 2"

3

bash, 105 caracteres

while read x
do
for((i=0,z=x;x>9;i++))do
for((y=0;x>0;y+=x%10,x/=10))do :
done
x=$y
done
echo $z $i
done

Casi ningún golf realmente estuvo involucrado, pero no veo cómo mejorarlo.


3

Haskell - 114

s t n|n>9=s(t+1)$sum$map(read.(:[]))$show n|1>0=show t
f n=show n++" "++s 0n++"\n"
main=interact$(f.read=<<).lines

Puede guardar 4 bytes mediante el uso de puremás (:[])y la definición de un operador en lugar de s, probarlo en línea!
ბიმო

3

Ruby, 85 caracteres

puts $<.map{|n|v=n.chop!;c=0;[c+=1,n="#{n.sum-n.size*48}"] while n[1];[v,c]*' '}*"\n"

Tuve que tomar prestada la idea del "tamaño de la suma * 48" de Alex, porque es demasiado buena para perderla (al menos en Ruby).


3

Golfscript, 40 caracteres

n%{.:${;${48-}%{+}*`:$,}%.,1>\1?+' '\n}%

3

J - 45 caracteres

Lecturas de stdin

(,' ',[:":@<:@#+/&.:("."0)^:a:)&><;._2(1!:1)3

Estaba tratando de ^:a:usarme pero no pude encontrar la documentación adecuada ... ¿alguna pista?
Eelvex

1
La entrada del diccionario para u ^: n tiene información sobre su uso, pero es un poco densa. ^: a: es como cualquier otra llamada al poder, pero recopila los resultados y finaliza cuando el argumento de las llamadas consecutivas es el mismo (converge).
isawdrones

1
@Eelvex FWIW descubrí a a:través del ^:a:truco en la J Reference Card [PDF]
JB

@JB: Esa es la única referencia ^:a:que conocía: D
Eelvex

@Eelvex Oh. Tuve la experiencia opuesta entonces. Descubrí la funcionalidad en el diccionario, y la usé como una variante ^:(<'')al principio (probablemente para Kaprekar), hasta que la vi en la tarjeta y aprendí sobre a:la ocasión.
JB

3

c - 519

(o 137 si me acreditas por el marco ...)

En lugar de resolver solo esta operación, decidí producir un marco para resolver todos los problemas de persistencia .

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char*(*O)(char*);
char*b(char*s){long long int v=0,i,l=0;char*t=0;l=strlen(s);t=malloc(l+2);
for(i=0;i<l;i++)v+=s[i]-'0';snprintf(t,l+2,"%lld",v);return t;}
int a(char**s,O o){int r;char*n;n=o(*s);r=!strcmp(*s,n);free(*s);
*s=n;return r;}
int main(int c, char**v){size_t l, m=0;char *d,*n=0;O o=b;FILE*f=stdin;
while(((l=getline(&n,&m,f))>1)&&!feof(f)){int i=0;n=strsep(&n,"\n");
d=strdup(n);while(!a(&n,o))i++;printf("%s %d\n",d,i);free(d);free(n);n=0;m=0;}}

Solo las dos líneas que comienzan char*bson exclusivas de este problema.

Trata la entrada como cadenas, lo que significa que los "0" iniciales no son bandas antes de la etapa de salida.

Lo anterior ha tenido comentarios, verificación de errores e informes, y lectura de archivos (la entrada debe provenir de la entrada estándar) eliminada de:

/* persistence.c
 *
 * A general framework for finding the "persistence" of input strings
 * on opperations.
 *
 * Persistence is defined as the number of times we must apply
 *
 *    value_n+1 <-- Opperation(value_n)
 *
 * before we first reach a fixed point.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../getline.h"

/* A function pointer type for operations */
typedef char*(op_func)(char*);
typedef op_func* op_ptr;
/* Op functions must
 * + Accept the signature above
 * + return a point to a newly allocated buffer containing the updated str
 */

char* addop(char*s){
  int i,l=0;
  long long int v=0;
  char *t=NULL;
  /* protect against bad input */
  if (NULL==s) return s;
  /* allocate the new buffer */
  l = strlen(s);
  t = malloc(l+2);
  if (NULL==t) return t;
  /* walk the characters of the original adding as we go */
  for (i=0; i<l; i++) v += s[i]-'0';
  //fprintf(stderr,"   '%s' (%d) yields %lld\n",s,l,v);
  snprintf(t,l+2,"%lld",v);
  //fprintf(stderr,"   %lld is converted to '%s'\n",v,t);
  return t;
}

/* Apply op(str), return true if the argument is a fixed point fo
 * falsse otherwise,
 */ 
int apply(char**str, op_ptr op){ 
  int r;
  char*nstr;
  /* protect against bad input */
  if ( NULL==op ) exit(1); 
  if ( NULL==*str ) exit(4); 
  /* apply */
  nstr = op(*str); 
  /* test for bad output */
  if ( NULL==nstr ) exit(2); 
  r = !strcmp(*str,nstr); 
  /* free previous buffer, and reasign the new one */
  free(*str); 
  *str = nstr; 
  return r; 
}

int main(int argc, char**argv){
  size_t len, llen=0;
  char *c,*line=NULL;
  op_ptr op=addop;
  FILE *f=stdin;
  if (argc > 1) f = fopen(argv[1],"r");
  while( ((len=getline(&line,&llen,f))>1) && line!=NULL && !feof(f) ){
    int i=0;
    line=strsep(&line,"\n"); // Strip the ending newline
    /* keep a copy for later */
    c = strdup(line);
    /* count necessary applications */
    while(!apply(&line,op)) i++;
    printf("%s %d\n",c,i);
    /* memory management */
    free(c);
    free(line);
    line=NULL;
    llen=0;
  }
}

Se podría ahorrar un poco más si estuviéramos dispuestos a perder memoria como un tamiz. Del mismo modo, mediante el #defineretorno y similares, pero en este punto no me importa hacer que sea más feo.



2

J, 74 caracteres

i=:<;._2(1!:1)3
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i

Ediciones

  • (86 → 83) Algunos topes [:a Ats@
  • (83 → 79) Paréntesis innecesarios
  • (79 → 75) Cambiar 0".a ".simplifica las cosas
  • (75 → 74) Mejor corte

P.ej

i=:<;._2(1!:1)3
74621
39
2677889
0
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i
74621 2  
39 2     
2677889 3
0 0  

La salida tiene un formato incorrecto para múltiples entradas. Ver "espacio único"
Jesse Millikan

@Jesse: No veo nada malo. ¿Podría escribir un ejemplo por favor?
Eelvex

No tengo idea, estoy viendo cosas, supongo.
Jesse Millikan

1

Creo que esto es lo mejor que se me ocurre.

Ruby 101 Chars

f=->(n){n.sum-n.size*48}
$<.each{|l|i=0;i+=1 while(i+=1;n=f[(n||l.chop!).to_s])>10
puts "#{l} #{i}"}

En realidad, ¡picar! en lugar de chomp! Me da un ahorro de un personaje. 97 caracteres.
Alex Bartlow

Acabo de jugar un poco más al golf: 91 caracteres.
Alex Bartlow

1

Caracteres PARI / GP 101

s(n)=r=0;while(n>0,r+=n%10;n\=10);r
f(n)=c=0;while(n>9,c++;n=s(n));c
while(n=input(),print(n," ",f(n)))

Desafortunadamente, no hay una función de entrada para GP, así que supongo que esto carece de la parte IO. :( Corregido: ¡Gracias Eelvex! :)


Claro que lo hay: input():)
Eelvex

@Eelvex, hecho. :)
st0le

1

Javascript - 95

i=prompt();while(i>9){i=''+i;t=0;for(j=0;j<i.length;j++)t+=parseInt(i.charAt(j));i=t;}alert(t);

EDITAR: Whoops no hace las líneas múltiples


1
Acabo de notar que esto no lo genera correctamente.
Kevin Brown

1

J 78

f=:[:+/"."0&":
r=:>:@$:@f`0:@.(=f)
(4(1!:2)~LF,~[:":@([,r)".@,&'x');._2(1!:1)3

Solución recursiva. Lecturas de stdin. Escribe en stdout , así que déjame un poco de holgura: se necesitan 18 caracteres adicionales.


1

Perl - 77 caracteres

sub'_{split//,shift;@_<2?0:1+_(eval join'+',@_)}chop,print$_,$",(_$_),$/for<>

1

JavaScript , 57 47 bytes

-10 bytes gracias a @ l4m2!

f=(s,c=0)=>s>9?f(eval([...s+""].join`+`),++c):c

Pruébalo en línea!


f=(s,c=0)=>s>9?f([...s+""].reduce((x,y)=>x*1+y*1),++c):c
l4m2

f=(s,c=0)=>s>9?f([...s+""].reduce((x,y)=>x- -y),++c):c
l4m2

1
f=(s,c=0)=>s>9?f(eval([...s+""].join`+`)),++c):c
l4m2

@ l4m2 ¡Gracias! s>9y evalfueron grandes ideas. Creo que tenía un par extra allí, por lo que me salvó un total de 10 bytes :-)
Oliver

Tenga en cuenta la estricta E / S;)
Shaggy

1

05AB1E , 13 bytes

ε.µΔSO¼}¾}<ø»

Entrada como una lista de enteros.

Pruébalo en línea.

Explicación:

ε     # Map each integer in the (implicit) input to:
    #  Reset the counter variable to 0
 Δ    #  Loop until the integer no longer changes:
  S   #   Convert it to a list of digits
   O  #   And take the sum of those
  ¼   #   Increase the counter variable by 1
    #  After the inner loop: Push the counter variable
}<    # After the map: decrease each value by 1
  ø   # Zip/transpose it with the (implicit) input to create a paired list
   »  # Join each pair by a space, and then each string by newlines
      # (after which the result is output implicitly)

1

MathGolf , 11 bytes

hÅ_Σ]▀£(k ?

Pruébalo en línea!

Increíblemente ineficiente, pero eso no nos importa. Básicamente, usando el hecho de que la persistencia aditiva de un número es menor o igual que el número mismo.

Utiliza el hecho de que la persistencia aditiva es menor o igual que el número de dígitos del número. Pasa todos los casos de prueba con facilidad ahora.

El formato de entrada, aunque no es óptimo para algunos idiomas, es en realidad el método estándar de tomar múltiples casos de prueba como entrada en MathGolf. Cada línea de la entrada se procesa como su propia ejecución del programa, y ​​la salida está separada por una nueva línea nueva para cada ejecución.

Explicación (usando n = 6234)

h             push length of number without popping (6234, 4)
 Å            loop 4 times using next 2 operators
  _           duplicate TOS
   Σ          get the digit sum
    ]         wrap stack in array
              this gives the array [6234, 15, 6, 6, 6]
     ▀        unique elements of string/list ([6234, 15, 6])
      £       length of array/string with pop (3)
       (      decrement (2)
        k ?   push input, space, and rotate top 3 elements to produce output (6234 2)

1

K (ngn / k) , 16 bytes

Solución:

{x,#1_(+/10\)\x} 

Pruébalo en línea!

Explicación:

{x,#1_(+/10\)\x} / the solution
{              } / lambda taking implicit x
      (     )\x  / iterate until convergence
         10\     / split into base-10 (123 => 1 2 3)
       +/        / sum
    1_           / drop first result (iterate returns input as first result)
   #             / count length of result
 x,              / prepend x (original input)


0

scala 173:

def s(n:BigInt):BigInt=if(n<=9)n else n%10+s(n/10)
def d(n:BigInt):Int=if(n<10)0 else 1+d(s(n))
Iterator.continually(readInt).takeWhile(_>0).foreach(i=>println(i+" "+d(i)))



0

Python 3 , 82 bytes

while 1:f=lambda n:n//10and 1+f(sum(map(int,str(n))));i=input();print(i,f(int(i)))

0

Tcl , 95 bytes

proc P {v n\ 0} {set V $v
while \$v>9 {set v [expr [join [split $v ""] +]]
incr n}
puts $V\ $n}

Pruébalo en línea!


3
Porque la siguiente respuesta más reciente es un total de 6 años, que creo que es antes de que existiera TIO
fəˈnɛtɪk

0

Japt , 28 bytes

Ë+S+(@D=X©A<D©ì x ªD D<AÃa÷
Ë                            // Map over the inputs and return each, followed by
 +S+                         // a space, followed by the number's persistence.
      D=     ©ì x            // To find it, fold the number up
        X©A<D     ªD         // if we can (handles unfoldable cases),
    (@               D<AÃa   // until it can't be folded up any further.
                          ÷ // Then, join everything up with newlines.

Pruébalo en línea!


0

PHP, 72 + 1 bytes

+1 para -Rbandera.

for($i=0,$a=$argn;$a>9;$i++)$a=array_sum(str_split($a));echo"$argn $i
";

Corre como tubería con -R .

  • ejecutar PHP como pipe ejecutará el código una vez para cada línea de entrada
  • pero no desarma las variables intermedias; entonces $idebe ser inicializado.
    (Además, no imprimiría nada en lugar de 0dígitos únicos sin la inicialización).

0

Bash + coreutils, 83 bytes

[ $1 -le 9 ]&&exit $2
let x=$2+1
for z in `fold -w1<<<$1`
do let y+=$z
done
a $y $x

Pruébalo en línea!

Debe guardarse en un script llamado ay colocado en el sistemaPATH , como se llama a sí mismo de forma recursiva. Toma información de la línea de comando, como a 1999. Devoluciones por código de salida.

TIO tiene algunas limitaciones sobre lo que puede hacer con un script, por lo que hay un código repetitivo para que esto se ejecute en el encabezado.

Imprime un error para stderruna entrada más grande de lo que pueden manejar los enteros bash, pero dado que el cálculo real se realiza con cadenas, de todos modos sigue dando el resultado correcto.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.