Calcular la suma de diferencia de dígitos de un número


39

Considere tomar un número entero no negativo como 8675309 y calcular los valores absolutos de las diferencias entre todos los pares de dígitos vecinos.

Para 8675309que obtenemos |8-6| = 2, |6-7| = 1, |7-5| = 2, |5-3| = 2, |3-0| = 3, |0-9| = 9. Encadenación estos resultados juntos produce otro, entero no negativo más pequeño: 212239. La repetición del proceso da 11016, entonces 0115, que según la convención que los ceros iniciales no se escriben se simplifica como 115, que se convierte en , 04o 4que no se puede reducir más. Sumando todos estos valores, obtenemos 8675309 + 212239 + 11016 + 115 + 4 = 8898683.

Definamos la suma de diferencias de dígitos (o DDS) como esta operación de tomar repetidamente las diferencias de dígitos de un número para formar un nuevo número, y luego agregar todos los números resultantes al original.

Aquí están los primeros 20 valores en la secuencia DDS correspondiente:

N   DDS(N)
0   0
1   1
2   2
3   3
4   4
5   5
6   6
7   7
8   8
9   9
10  11
11  11
12  13
13  15
14  17
15  19
16  21
17  23
18  25
19  27

Aquí están los primeros 10000 valores , cuyo gráfico es bastante curioso:

Parcela DDS 10000

Especialmente porque se ve igual cuando lo trazas a 1000 o incluso a 100:

DDS 1000 plot

DDS 100 plot

(Yo lo llamaría la escalera del dentista ...)

Reto

Escriba un programa o función que tome un número entero no negativo e imprima o devuelva su valor DDS. Por ejemplo, si la entrada fue 8675309, la salida debería ser 8898683.

El código más corto en bytes gana.


escalera del dentista?
Martijn

12
@MartijnR Escalera del dentista.
Aficiones de Calvin

@ Calvin'sHobbies ¿La escalera del ortodoncista?
Beta Decay

1
@BetaDecay Escalera del dentista .
Alex A.

Respuestas:


11

Pyth, 17

s.ui.aM-VJjNTtJTQ

Pruébelo aquí o ejecute Test Suite

Explicación:

s.u            Q   # Cumulative reduce, i.e. getting the intermediate values of each reduce
                     step and returning them as a list, then sum the list
   i ... T         # Convert the resulting list of numbers into a base 10 number
   .aM             # Get the absolute value of each element of ...
      -VJjNTtJ     # Perform vector subtraction on the lists given by
        JjNT       # assign J the number we currently have converted to its base 10 digits
            tJ     # and J[1:]. e.x. for 123 we get J = [1,2,3] then we do
                   # zip(J,J[1:]) which gives [[1,2],[2,3]] then element wise subtract
                   # to get [-1, -1]

¿Qué lenguaje es este? ¡Tan críptico! T_T
pide el

1
@asgs Bienvenido a PPCG :) Se llama Pyth, puede encontrar un intérprete y documentación en su página de Github . La mayoría de los usuarios de este lenguaje son activos en este sitio, por lo que si tiene alguna pregunta al respecto no dude en preguntar en el chat o en la sala dedicada a ella :)
FryAmTheEggman

17

Pitón 2, 73

Afortunadamente, logré evitar cualquier operación de cadena.

t=lambda n:n>9and abs(n%10-n/10%10)+10*t(n/10)
g=lambda n:n and n+g(t(n))

g es la función que calcula la respuesta.


44
¿Qué es esta magia negra?
Beta Decay

77
@BetaDecay Creo que se llama "matemáticas".
lirtosiast

No conozco Python lo suficientemente bien como para saberlo, pero ¿puedes aplicar la operación restante a ambos términos de una sola vez? Es decir, ¿ (n-n/10)%10funcionaría igual que n%10-n/10%10? O tal vez incluso (9*n/10)%10?
Glen O

@GlenO En Python, %es un verdadero operador de módulo, no un resto, por lo que eso no funcionaría.
fiesta del

15

Matlab, 101105 bytes

Muchas gracias a @beaker por su sugerencia de usar polyvalen su lugar sibase2dec . Eso me permitió

  • guardar 4 bytes;
  • simplifique en gran medida la generalización a una base arbitraria (ver más abajo) y ahorre 22 bytes allí; y mas que todo,
  • me ayudó a darme cuenta de que el código para el caso general era incorrecto (no se eliminaban los ceros iniciales). El código y los gráficos son correctos ahora.

Código:

function y=f(y)
x=+num2str(y);while numel(x)>1
x=polyval(abs(diff(x)),10);y=y+x;x=+dec2base(x,10);end

Ejemplo:

>> f(8675309)
ans =
     8898683

Bonus: base arbitraria

Una pequeña generalización permite usar una base de números arbitraria, no necesariamente decimal:

  • Base arbitraria de 2 a 10, 108 104 bytes

    function y=f(y,b)
    x=+dec2base(y,b);while numel(x)>1
    x=polyval(abs(diff(x)),b);y=y+x;x=+dec2base(x,b);end
    

    La razón por la que esto funciona solamente para la base hasta 10es que de Matlab dec2baseutiliza la función dígitos 0, 1, ..., 9, A, B, ..., y hay un salto en los códigos de caracteres (ASCII) de 9a A.

  • Base arbitraria de 2 a 36, 124 146 bytes

    El salto de 9a lo Amencionado anteriormente necesita un tratamiento especial. La base máxima es 36según la dec2basefunción de Matlab .

    function y=f(y,b)
    x=+dec2base(y,b);x(x>57)=x(x>57)-7;while numel(x)>1
    x=abs(diff(x));x=x(find(x,1):end);y=y+polyval(x,b);end
    

Así es como las escaleras del dentista buscan diferentes bases:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí


1
Esto es lo que habría hecho ... hora de pensar en otra respuesta jajaja. +1.
rayryeng - Restablecer Monica

@rayryeng :-) Gracias
Luis Mendo

@BetaDecay ¡Gracias! :-) Son realmente bonitos
Luis Mendo

11

CJam, 22 21 bytes

ri_{\s2ew::-:zsi_@+}h

Tenga en cuenta que este programa sale con un error, que está permitido por defecto .

Con el intérprete de Java, los errores se pueden suprimir al cerrar STDERR. Si prueba este código en línea en el intérprete de CJam , ignore todos los resultados antes de la última línea.

Gracias a @ Sp3000 por señalar un error en la revisión original.

Gracias a @ MartinBüttner por jugar golf en 1 byte.

Ejecución de ejemplo

$ cjam digit-difference.cjam 2>&- <<< 8675309     
8898683

Cómo funciona

ri_   e# Read an integer (I) from STDIN and push a copy (A).
{     e# Do:
  \   e#   Swap I on top of A.
  s   e#   Cast I to string.
      e#   For example, 123 -> "123".
  2ew e#   Push the overlapping slices of length 2 (pair of adjacent digits).
  ::- e#   Replace each pair by its difference.
  :z  e#   Apply absolute value to each difference.
  si  e#   Cast to string, then to integer. This is the new I.
      e#   For example, [1 2 3] -> "123" -> 123.
  _   e#   Push a copy of I.
  @   e#   Rotate A on top of the copy of I.
  +   e#   Add I to A, updating A.
}h    e# While A is truthy, repeat the loop.

A siempre será sincero cuando sea verificado h. Sin embargo, una vez que soy un entero de un solo dígito, 2ewfallará con un error después de consumir la matriz en la que se invocó. Esto deja solo el resultado deseado en la pila, que se imprime antes de salir.


2
Publicado en 7 minutos planos: O
Hobbies de Calvin

10

Laberinto , 176 134 127 119 103 97 88 82 79 76 72 bytes

Gracias a Sp3000 por guardar 1 byte y allanar el camino para 2 más.

Esto probablemente aún podría acortarse, pero bueno, supera a Java Matlab Python ...

?
_
)/:}+{:`};!
9       "
_ :}-"" :_10
;;{: `" "  :
  {  (_:/=%}
  0+;`"

Pruébalo en línea.

Esto termina con un error, pero el mensaje de error se escribe en STDERR (por lo que no lo ve en TIO).

La implementación es bastante sencilla. Agregamos el valor actual a un total acumulado. Si el valor actual era mayor que 9, calculamos sus dígitos de base 10 (a través de la repetición div-mod) y formamos un nuevo número a partir de las diferencias absolutas. Si llegamos a9 o menos, imprimimos el total acumulado.

Los dígitos del número actual se recopilan en la pila auxiliar con el dígito más significativo en la parte superior.

Bueno, la implementación sofisticada abs(...)que había hecho aquí resultó ser ridículamente complicada en comparación con la nueva solución ... Agregaré una explicación actualizada cuando termine de jugar al golf.


5

Java: 300 bytes

Versión de golf

static Long t=new Scanner(System.in).nextLong();static char[]c=t.toString().toCharArray();public static void main(String[]z){while(c.length>1)s();System.out.print(t);}static void s(){String s="";for(int i=0;i<c.length-1;)s+=Math.abs(c[i]-c[++i]);Long a=new Long(s);t+=a;c=a.toString().toCharArray();}

Ungolfed / versión completa

import java.util.Scanner;

public class DigitDifference {

    static Long t = new Scanner(System.in).nextLong();
    static char[] c = t.toString().toCharArray();

    public static void main(String[] args){
        while( c.length > 1 )
            s();
        System.out.print(t);
    }

    static void s(){
        String s="";
        for(int i = 0; i < c.length-1;)
            s += Math.abs(c[i]-c[++i]);
        Long a = new Long(s);
        t += a;
        c = a.toString().toCharArray();
    }
}

@Loovjo, Cheers ..
The Coder

1
Bienvenido a PPCG! Esto todavía se puede jugar mucho al golf. No he mirado mucho la lógica, pero: 1) Ponga todo esto en una función, ya que realmente no necesita uno separado (o un programa / clase completo para el caso) 2) Deshágase de los statics después de tirar en 3) (a+"")es generalmente el mismo que a.toString(), pero más corto 4) No necesita un escáner si es solo una función, simplemente tome mucho tiempo como entrada.
Geobits

2
Por ejemplo, sin cambiar gran parte del trabajo, y solo quitando el cruft, es alrededor de 164:long f(long t){long a=t;char[]c;while((c=(a+"").toCharArray()).length>1){String s="";for(int i=0;i<c.length-1;)s+=Math.abs(c[i]-c[++i]);t+=a=new Long(s);}return t;}
Geobits

2
@Geobits, fue un amigo increíble. Soy nuevo en Code Golf, así que intentaré mejorar mi eficiencia de codign. Cherrs ..
The Coder

5

Julia, 81 60 bytes

n->(s=n;while n>9 s+=n=int(join(abs(diff(["$n"...]))))end;s)

Sin golf:

function f(n::Int)
    # Initialize a sum to the input
    s = n

    while n > 9
        # Get absolute values of the pairwise differences of the
        # digits of n, join as a string, convert it to an integer,
        # and reassign n
        n = int(join(abs(diff(["$n"...]))))

        # ["$n"...] actually splits n as a string into a vector
        # of its characters, but the difference between ASCII
        # codes is the same as the difference between the numbers
        # so it works as expected

        # Add the new n to the running sum
        s += n
    end

    # Return the sum
    return s
end

Pruébalo en línea

Guardado 21 bytes gracias a feersum y Glen O!


1
¿Hay alguna razón ndigits(n)>1diferente a la n>9?
Feersum

Sugerencia: int(join(abs(diff(["$n"...]))))ahorra 9 bytes. Cambie a n>9lo sugerido por feersum para otros 9 bytes guardados. Ahorre tres bytes más realizando ambas asignaciones en el ciclo while en un solo paso (y eliminando el punto y coma adicional, ahora innecesario):n->(s=n;while n>9 s+=n=int(join(abs(diff(["$n"...]))))end;s)
Glen O

@feersum Um, no. ¡Gracias!
Alex A.

@GlenO Impresionante, gracias!
Alex A.

5

Ok , 37 32 24 23 bytes

+/(10/{%x*x}1_-':.:'$)\

En acción:

  +/(10/{%x*x}1_-':.:'$)\8675309
8898683

  (+/(10/{%x*x}1_-':.:'$)\)'!20
0 1 2 3 4 5 6 7 8 9 11 11 13 15 17 19 21 23 25 27

K5 tiene algunas características que se adaptan bien a esto: "codificar" y "decodificar" pueden realizar una conversión de base, cada par ( ':) empareja elementos secuenciales en una lista y el escaneo de punto fijo ( \) puede producir la secuencia iterada hasta que se detenga cambiando. Sin embargo, la falta de una primitiva abs()conduce a un volumen desagradable en forma de {(x;-x)x<0}'.

Editar:

En lugar de eso {(x;-x)x<0}', puedo (un poco despilfarro) tomar la raíz cuadrada del cuadrado de la secuencia ( {%x*x}ahorrando 5 bytes.

Edición 2:

Inspirado por la solución APL de @maurinus, puedo reemplazar la "decodificación" ( ((#$x)#10)\x) con la evaluación de cada carácter de la representación de cadena del número- .:'$x! Esto también me permite usar una forma tácita de toda la expresión, guardando caracteres adicionales.


4

Python 2, 87 bytes

f=lambda n:n and n+f(int('0'+''.join(`abs(int(a)-int(b))`for a,b in zip(`n`,`n`[1:]))))

Agrega recursivamente el número actual y toma las diferencias de dígitos. Mucha conversión entre números y cadenas. Probablemente se puede mejorar.


4

Julia, 55 48 bytes

h=n->(n>9&&h(int(join(abs(diff(["$n"...]))))))+n

Sin golf:

function h(n)
  if n>9
    # If multiple digits, find the digit difference...
    digitdiff=int(join(abs(diff(["$n"...]))))
    # ... recurse the function...
    downsum=h(digitdiff)
    # ... and return the sum so far (working up from the bottom)
    return downsum+n
  else
    # If single digit, no further recursion, return the current number
    return n
  end
end

Esencialmente, esto se repite hasta el nivel de un solo dígito (donde no se puede realizar ninguna diferencia de dígitos), luego se vuelve a sumar a medida que sale de la recursión, nivel por nivel.


3

Haskell, 140 bytes

d hace el trabajo.

import Data.Char
d n=sum.m(read.m intToDigit).fst.span(/=[]).iterate s.m digitToInt.show$n
s l@(h:t)=snd$span(==0)$m abs$zipWith(-)l t
m=map

¿Alguien sabe cómo evitar importar las funciones de conversión largas?


intToDigites toEnum.(+48)y digitToIntes (\i->fromEnum i-48). También se puede activar sa una versión con pointfree =<<en el contexto de lista: s=snd.span(==0).m abs.(zipWith(-)=<<tail). Finalmente, (==0)es (<1)porque estamos trabajando con enteros no negativos.
nimi

... oh, y si no stiene puntos, no hay necesidad de ponerle un nombre. Llámalo directamente:iterate(snd.span ... tail))
nimi

... soy yo nuevamente para corregir un error en mi primer comentario: =<<se usa en el contexto de la función, no en el contexto de la lista, lo siento.
nimi

¡Brillante! Además, ¿es un procedimiento común aquí usar extensiones GHC? NoMonomorphismRestrictiontambién me dejará tener un punto dlibre.
Leif Willerts

1
chry ordestán ambos adentro Data.Char, así que no puedes omitir el import. Los indicadores del compilador también se cuentan como bytes, por lo que NoMonomorphismRestrictionaumenta su puntuación en 25.
nimi


3

APL (22)

{⍵≤9:⍵⋄⍵+∇10⊥|2-/⍎¨⍕⍵}

Explicación:

  • ⍵≤9:⍵: si ⍵ ≤ 9, devuelve ⍵ sin cambios.
  • ⍎¨⍕⍵: convierte ⍵ a una cadena, luego evalúa cada carácter
  • 2-/: resta cada dos números adyacentes
  • |: tomar los valores absolutos
  • 10⊥: convierte la matriz en un número base 10
  • ⍵+∇: llame a la función recursivamente con este nuevo valor y agregue el resultado a la entrada

3

Mathematica, 72 69 65 bytes

Tr@FixedPointList[FromDigits@*Abs@*Differences@*IntegerDigits,#]&

Estoy abierto a sugerencias aquí.


Tr@FixedPointList[FromDigits@*Abs@*Differences@*IntegerDigits,#]&
alephalpha

@alephalpha Concepto interesante, creando ceros adicionales ...
LegionMammal978

2

JavaScript ES6, 73 bytes

t=n=>(b=10,M=Math).ceil(n&&n+t((j=n=>n>9&&M.abs(n%b-n/b%b)+b*j(n/b))(n)))

Esto no se está acortando: / Intentaré más enfoques, pero este es el más corto hasta ahora


Si lo deja como una función anónima en lugar de asignarlo, tsigue siendo válido y le ahorra 2 bytes.
Patrick Roberts

@PatrickRoberts sí, pero estoy usando la recursión, así que necesito nombrarla
Downgoat

Oh, me perdí eso, bastante justo.
Patrick Roberts

2

JavaScript (ES6), 69

Pruebe a ejecutar el fragmento a continuación en un navegador compatible con EcmaScript 6 (pero no Chrome, ya que todavía no es compatible con el operador de propagación ...) ¿Quizás MS Edge?

f=n=>n&&(n+=r='',[...n].map(d=>(r+=d>p?d-p:p-d,p=d),p=n[0]),+n+f(+r))

function test()
{
  var i=+I.value
  O.innerHTML = i+' -> '+f(i) + '\n' + O.innerHTML 
}
<input id=I value=8675309><button onclick=test()>-></button>
<pre id=O></pre>

Alternativa, utilizando la comprensión de matriz que ahora está dirigida a EcmaScript 2016 (ES7), 67 bytes:

f=n=>n&&(n+=r='',p=n[0],[for(d of n)(r+=d>p?d-p:p-d,p=d)],+n+f(+r))

2

Python 3, 125 bytes

Me gustaba la brevedad de la expresión regular hasta que intenté usarlo para este desafío ... nore.findall('\d\d',s,overlapped=True) está activado ;)

s=input()
p=int
x=p(s)
while p(s)>9:g=str(s);s=p(''.join(str(abs(p(g[i])-p(g[i+1])))for i in range(len(g)-1)));x+=s 
print(x)

Saludos @Todd :)


1
Puede realizar la suma in situ en un número entero en lugar de una lista que eliminará la necesidad de corchetes y la suma final. 's = p (input ())' le permitirá eliminar la conversión int en el ciclo while y la asignación a x. También considere recorrer el zip de g y g [1:] que debería guardar algunos bytes.
Todd

1

J, 70 bytes

 +/([:10&#.[:(2|@:-/\])[:10&(]#:~[#~[:>.[^.])])`]@.(11&>)^:a:".(1!:1)3

0

C 162 bytes

golfizado:

main(int argc,char **argv){char *c=argv[1];int u=atoi(c),d;do{while(c[1]!=0){*c=abs(*c-*(c+1))+48;c++;}*c=0;c=argv[1];d=atoi(c);u+=d;}while(d>9);printf("%d",u);}

sin golf:

main(int argc, char **argv)
{
    char *c=argv[1];
    int u=atoi(c),d;

    do
    {
        while(c[1]!=0)
        {
            *c=abs(*c-*(c+1))+48;
            c++;
        }

        *c=0;
        c=argv[1];
        d=atoi(c);
        u+=d;
    }
    while(d>9);

    printf("%d\n",u);
}

0

R, 134 bytes

Código

f=function(x){z=x;while(z>9){n=seq(nchar(z));z=abs(diff(strtoi(substring(z,n,n))));z=sum(z*10**(rev(seq(length(z)))-1));x=x+z};cat(k)}

Pruébalo en línea .

Sin golf

f=function(x){
  z=x;
  while(z>9){
    n=seq(nchar(z));
    z=abs(diff(strtoi(substring(z,n,n))));
    z=sum(z*10**(rev(seq(length(z)))-1));
    x=x+z
  };
  cat(x)
}

Aquí está la gráfica de la diferencia de la serie "Suma de diferencia de dígitos de un número" de f (1) a f (1m). Solo porque me encanta diferir.

Código de trama

s <- seq(1,100000)
serie <- sapply(s,f)
plot(diff(ts(serie)),xlab="",ylab="")

0

MATLAB (141)(137)

EDITAR: 4 bytes menos, gracias a @Andras

function[s j]=n(T,b,c),if(T/b>9),u=fix(T/10);[x e]=n(T,b*10,0);y=n(u,b,0);[w z]=n(u,b,c);s=abs(x-y);j=s+e+10*c*z;else,s=mod(T,10);j=s;end
  • Esta respuesta superó la respuesta de @LuisMendo, pero al menos pude reducir el tiempo de ejecución, lo cual habría tratado de diversificar las formas de abordar este problema.
  • Podría reducirlo más, pero a medida que avanzo por menos tiempo, pierdo más bytes, así que aquí está el principio:

El programa está sumando dígitos de la misma fila antes de los dígitos en línea, significa que usó la división entera "n / 10" log_10 (n) veces solamente, la complejidad es O (N).

Si n= a b c d

a          b           c           d
   |a-b|       |b-c|       |c-d|
    ||a-b|-|b-c|| ||b-c|-|c-d||
   ....

Mi programa calcula:

a+|a-b| + | |a-b|-|b-c| |  +  |  | |a-b|-|b-c| | - | |b-c|-|c-d| |  |
+10*(
b+|b-c| + | |b-c|-|c-d| |
+10*(
c+|c-d|
+10*(
d
)
)
)

Uso:

  [a b]=n(13652,1,1)

a =

1

 b =

   16098

Puede ahorrar 4 bytes omitiendo el opcional ,endde la functiondeclaración.
Andras Deak

Considera revisar la gramática de tu publicación. No puedo entender lo que has dicho.
rayryeng - Restablecer Monica

0

Prólogo, 143 bytes

Código:

q(X,N):-X<9,N=0;A is abs(X mod 10-X//10 mod 10),Y is X//10,q(Y,M),N is A+M*10.
r(X,N):-X<9,N=X;q(X,Y),r(Y,M),N is X+M.
p(X):-r(X,N),write(N).

Explicado:

q(X,N):-X<9,N=0;                                                         % If only one digit, the difference is 0
        A is abs(X mod 10-X//10 mod 10),Y is X//10,q(Y,M),N is A+M*10.   % Else, the difference is the difference between the last 2 digits + the recursive difference of the number without the last digit
r(X,N):-X<9,N=X;                                                         % If we only have 1 digit the final answer is that digit
        q(X,Y),r(Y,M),N is X+M.                                          % Else, the final answer is the current number + the recursive difference of that number
p(X):-r(X,N),write(N).         

q realiza los cálculos que convierten un número en su diferencia de dígitos.
r llama recursivamente q y resume los resultados para encontrar la suma de diferencia de dígitos.
p es el punto de entrada. Toma un número, llama a r e imprime la respuesta.

Ejemplo:

>p(8675309).
8898683

Pruébelo en línea aquí .


0

PHP - 198 bytes

<?$x=$t=$_GET['V'];function z($x){global$t;for($i=0;$i<strlen($x)-1;$i++){$z=str_split($x);$r.=str_replace('-','',$z[$i]-$z[$i+1]);}$r=ltrim($r,'0');$t+=$r;return strlen($r)>1?z($r):0;}z($x);echo$t;

Sin golf

<?
$x=$t=$_GET['V']; // Gets the value from input
function z($x){
    global$t;
    for($i=0;$i<strlen($x)-1;$i++){
        $z=str_split($x); //Turns the string into an array
        $r.=str_replace('-','',$z[$i]-$z[$i+1]); // Sums the two values and removes the minus signal
    }
    $r=ltrim($r,'0'); // Remove trailing zeroes
    $t+=$r; // Adds to global var
    return strlen($r)>1?z($r):0; // Checks the size of the string. If >1, calls the function again
}

z($x);
echo$t;

0

Perl 6 , 56 bytes

{[+] $_,{+.comb.rotor(2=>-1)».map((*-*).abs).join}…0} # 56 bytes

uso:

my &code = {...} # insert code from above

(180..190).map: &code;
# (259 258 259 260 261 262 263 264 265 266 280)

say code 8675309; # 8898683
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.