Code Golf: 6174 - La constante mítica de Kaprekar


24

¿Por qué es tan interesante el número 6174? Según lo definido por Wikipedia

  1. Tome cualquier número de cuatro dígitos, usando al menos dos dígitos diferentes. (Se permiten ceros a la izquierda).
  2. Organice los dígitos en orden ascendente y luego en orden descendente para obtener dos números de cuatro dígitos, agregando ceros a la izquierda si es necesario.
  3. Resta el número más pequeño del número más grande.
  4. Regrese al paso 2.

El proceso anterior, conocido como la rutina de Kaprekar, siempre alcanzará 6174 en un máximo de 7 iteraciones. Una vez que se alcanza 6174, el proceso continuará produciéndolo.

Escriba un programa que ejecute la rutina de Kaprekar contra un número de cuatro dígitos dado (vea la definición anterior) imprimiendo cada paso de la rutina.

Reglas:

  • Las presentaciones deben ser programas completos.
  • La entrada debe leerse de la entrada estándar. La tubería del eco está bien.
  • La entrada debe estar en forma numérica.
  • Se requiere imprimir ceros a la izquierda. (Ver ejemplos a continuación).
  • La última línea debería decir cuántas iteraciones fueron necesarias. Se requiere puntuación.

Ejemplos:

> 2607
7620 - 0267 = 7353
7533 - 3357 = 4176
7641 - 1467 = 6174
Iterations: 3.

> 1211
2111 - 1112 = 0999
9990 - 0999 = 8991
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174
Iterations: 5.

> 6174
7641 - 1467 = 6174
Iterations: 1.

Cualquier lenguaje de programación es bienvenido. Puntos extra para los esotéricos + una pequeña recompensa.

Actualización 1 : ya hay una pregunta similar .

Actualización 2 : ejemplo agregado para 6174 como entrada. Gracias a Peter Taylor por el aviso.


Esto es una noticia para mí. Alguien llame a un moderador ...

Uh ... ¿no hay un botón "migrar"?
Dr. Rebmu

He marcado esto para que un moderador migre. ¿Puedo sugerir alterar las reglas de entrada y salida para estar de acuerdo con la versión anterior de 3 dígitos? Y enlazando con la versión anterior en el cuerpo de la pregunta.
dmckee

@dmckee No sabía sobre este sitio y no podía saber que ya hay una pregunta similar (en stackoverflow no había ninguna). Sin embargo, dudaría en alterar las reglas para estar de acuerdo con la versión de 3 dígitos y hacer que las dos preguntas sean aún más similares. No tiene sentido publicar un duplicado o una ligera variación de una pregunta existente. Incluso cuando se hace sin querer.
lunohodov

3
Agregue 6174 como ejemplo para que podamos ver cómo se debe formatear la salida.
Peter Taylor

Respuestas:


9

Perl - 147 143 134 130 129 126 129 128 126

for($_=<>;$_-6174+!$c;$c++){$_=reverse$d=join'',sort split//,"$_"
|$|x4;printf"$_ - $d = %04d\n",$_-=$d}die"Iterations: $c.\n"

EDITAR: ahora cumple con el caso 6174, a costa de unos pocos caracteres ... ejecutar con echo -n <number> | perl kaprekar.pl

EDITAR: Finalmente de vuelta a donde estaba antes: D


10

Ruby 1.9, 122 caracteres

puts"Iterations: #{(1..7).find{s=$_.chars.sort*"";puts [r=s.reverse,?-,s,?=,$_="%04d"%(r.to_i-s.to_i)]*" ";~/6174/}}."

Ejemplo de invocación:

$ echo 1211 | ruby -ln kaprekar.rb

He contado la -lnbandera como 4 caracteres (diferencia entre la invocación normal ruby kaprekar.rby ruby -ln kaprekar.rb).


Guardé este script como kaprekar.rb y luego lo invoqué con ruby -lp kaprekar.rb. Ingresó un número y presionó <Enter> pero la salida es el número ingresado. Claramente me falta algo ... Por favor, aconseje cómo usar el script.
lunohodov

@lunohodov: agregué una invocación de ejemplo. Ahora también genera la salida correcta 6174como entrada, que desafortunadamente trae esta solución hasta 128 caracteres.
Ventero

El uso echo 1234 | ruby kaprekar.rbgenera una advertencia y termina con un error undefined method 'chars' for nil:NilClass (NoMethodError). La ejecución echo 1234 | ruby -lp kaprekar.rbsolo emite una advertencia y se comporta como se esperaba. La salida no es el esperado, ya que contiene un mensaje de advertenciakaprekar.rb:3: warning: regex literal in condition
lunohodov

@lunohodov: se corrigió la advertencia y la invocación de ejemplo.
Ventero

7

Python, 141 caracteres

n=input()
i=0
while n-6174:a=''.join(sorted("%04d"%n));b=a[::-1];n=int(b)-int(a);print"%s - %s = %04d"%(b,a,n);i+=1
print"Iterations: %d."%i

+1 para relleno liso con% 04d. ¡Aprendí algo hoy!
Arrdem

3
Algunas sugerencias: coloque todo el bucle en una línea usando ;s. while n-6174. No hay espacio entre printy la cita.
Keith Randall

@ keith-randall: gracias, ahora lo bajé a 141.
Martin Ueding

6

Golfscript, 74 caracteres

);:|;{0):0;|$:§-1%" - "§" = ""0"4$~§~-+-4>:|n|6174`=!}do"Iterations: "0"."

5

Haskell 197 192 182 181 caracteres

import List
p=putStrLn.unwords
"6174"%k|k>0=p["Iterations:",shows k"."]
n%k=p[b,"-",a,"=",c]>>c%(k+1)where a=sort n;b=reverse a;c=take 4$shows(read b-read a)"0"
main=getLine>>=(%0)

En línea ry sguarda 2 caracteres. Además, "000" es redundante. "0" es suficiente. Esto nos lleva a 188 caracteres. Me sorprende interactque no ayude aquí. Por lo general lo hace.
Rotsor

Reemplazar show x++scon shows x sganancias 2 bytes más. 186 ahora.
Rotsor

Al usar guardias de patrón ( |k>0) uno puede deshacerse de él f. Cambiarle el nombre ga %nos lleva a 182 caracteres.
Rotsor

4

> <> - 268 308

</&4pff1
v>i86*-:n&1-:&?!
>ao&        v
<v&0pff+1gff
 >&1+:4=   ?v&:a%:}-a,
 v&8[4r::0}~<
 >&1-:?!v&:@@:@(?$}&:&3%1=?}
 v      >~:}}:}@:}$:}
 \:n}:n}:n}:n}' - 'ooo:n}:n}:n}:n}' = 'ooo
 \a*+a*+a*+}a*+a*+a*+-:0&\
 v?       =4&:+1&,a-}:%a:<
/\&~~rnnnnao:29777****=   ?v
voooooooooooo"Iterations: "/
\ffgna'.'oo;

No es un gran contendiente para el golf, pero fue divertido escribirlo. :)

Ejecutar con./fish.py kaprekar.fish -v <number>
EDITAR: ahora toma la entrada de STDIN.


4

JavaScript 189 182 165 caracteres

Crédito a DocMax:

for(n=prompt(i=o=e='');!i--|n-6174;o+=n+' - '+a+' = '+(n=(p=n-a+e)[3]?p:0+p)+'\n')
  b=n.split(e).sort(),n=b.reverse(a=b.join(e)).join(e);
alert(o+"Iterations: "+~i+'.')

Original:

for(n=prompt(i=o=e='');n-6174;o+=(i++?n+"\n":e)+(n=(a=n.split(e).sort().join(e)).split(e).reverse().join(e))+' - '+a+' = ',n=n-a+e)while(!n[3])n=0+n
alert(o+n+"\nIterations: "+i+'.')

Sin golf:

var i = 0;
var n = prompt();
var out = '';
while (n != 6174) {
    while ((n=''+n).length<4) n='0'+n // pad number
    if(i)out+=n+"\n"

    a = n.split('').sort().join('');
    n = a.split('').reverse().join('');

    out += n + ' - ' + a + ' = '
    n-=a
    i++;
}
console.log(out + "6174\nIterations: " + i + '.');

1
Creo que puede cambiar n != 6174a n-6174ya que devolverá cero, que es falso (al menos en C y Python).
Martin Ueding

El crédito debe ir a keith-randall, quien lo sugirió para mi solución Python.
Martin Ueding

Puede guardar 5 caracteres más reemplazándolos while(n.length<4)por while(!n[3]).
DocMax

1
¡No puedo dejar de mirar a este! Lo siguiente a) corrige la salida cuando n = 6174, b) reorganiza cuando n+'\n'se agrega para evitar el condicional y un extra \n, c) usa una temperatura para evitar una secuencia de unión-división-unión, d) aprovecha el hecho de que solo tiene que agregar un solo '0' para el relleno: for(n=prompt(i=0,o=e='');n-6174;i++,o+=(n=(b=n.split(e).sort(),a=b.join(e),b).reverse().join(e))+' - '+a+' = '+(n=('0'+(n-a)).slice(-4))+'\n');alert(o+"Iterations: "+i+'.')que debe ser de 172 caracteres.
DocMax

1
¡Impresionante! Sin embargo, de acuerdo con la especificación anterior, cuando n = 6174, tiene que pasar por al menos una iteración, por lo que agregué una comprobación si ies 0 (+4) pero combiné eso con el i++. Desafortunadamente, eso da un error por un error, así que cambié el incremento a una disminución y luego usé un pequeño truco bit a bit al final (-1). Luego cambié i=0,o=e=''a i=o=e=''(-2), volví a formatear el forbucle para evitar paréntesis adicionales (-1), expandí el (b=...,a=...,b)bit (-2) y me escabullí a=b.joindentro de la reverse()llamada (-1). Entonces 169, no está mal!
Casey Chu

3

PowerShell, 125 128 130 131

for($a,$OFS=$input+'';$b-6174;++$i){$a=$b=+($c=''+($x="$a 000"[0..4]|sort)[4..0])-"$x"
"$c-$x = {0:d4}"-f$a}"Iterations: $i."

Pasa todos los casos de prueba de la pregunta.


2

JavaScript, 260 bytes

function z(c){for(u=c+y;u.length<4;)u=0+u;return u}for(p=prompt(i=0,r=y="");;)
if(s=(p+y).split(y).sort(),t=s.concat().reverse(),a=s.join(y),b=t.join(y),q=a<b?b:a,
w=a<b?a:b,p=z(q-w),i++,r+=z(q)+" - "+z(w)+" = "+p+"\n",p==6174)break;alert(r+
"Iterations: "+i+".")

2

Clojure, 256 caracteres

(let[i #(Integer/parseInt%)f #(format"%04d"%)a #(->>% f sort(apply str)i)d #(->>% f sort reverse(apply str)i)k #(let[u(d %)l(a %)n(- u l)](println(f u)"-"(f l)"="(f n))n)](while true(println"Iterations:"(count(take-while #(not=% 6174)(iterate k(read)))))))

2

Scala 2.9, 194 caracteres

object K extends App{var(c,s)=(0,args(0));do{var d=s.sorted;var e=d.reverse.toInt-d.toInt;s="%04d".format(e);println(d.reverse+" - "+d+" = "+s);c+=1}while(s!="6174");print("Iterations: "+c+".")}

Utiliza el rasgo de la aplicación de Scala 2.9.

Editar: proporciona la salida correcta para la entrada inicial de 6174.


2

PHP, 215 259 276 caracteres

<?php echo">";$n=str_split(str_pad(trim(fgets(STDIN)),4,0,0));for($k=0,$z=0;$k-6174;$z++){sort($n);$a=implode($n);$b=strrev($a);$k=str_pad($b-$a,4,0,0);echo"$b - $a = $k\n";$n=str_split($k);}echo"Iterations: $z\n";

Sin golf:

<?php
echo ">";
$n = str_split(str_pad(trim(fgets(STDIN)),4,0,0));
for($k=0, $z=0; $k-6174; $z++) {
    sort($n);
    $a = implode($n);
    $b = strrev($a);
    $k = str_pad($b-$a,4,0,0);
    echo "$b - $a = $k\n";
    $n = str_split($k);
}
echo "Iterations: $z\n";

No creo que necesite las funciones abs, maxy min, ya que el tipo siempre significará que $bes mayor que $a. Eso podría ahorrarte 20 personajes. Además, creo que poner el tipo dentro del bucle en la parte superior significará que solo necesita tenerlo en su código una vez, lo que le ahorrará otros 9.
Gareth

Wow, supongo que me distrajo la instrucción "restar el número más pequeño del número más grande". Gracias.
rintaun

<?function k($c){echo"> $c\n";$n=str_split(str_pad($c,4,0,0));for(;$k-6174;$z++){sort($n);$a=join($n);$b=strrev($a);$k=str_pad($b-$a,4,0,0);echo"$b - $a = $k\n";$n=str_split($k);}echo"Iterations: $z\n";} Puede guardar 12 caracteres cambiando su fordeclaración, llamando a esto como una función y usando en joinlugar de implode.
TwoScoopsofPig

Además, odio el mini-markdown.
TwoScoopsofPig

2

CoffeeScript, 233 225 caracteres

o=e='';i=0;n=prompt()
while n!=6174
  n=e+n;q=(n='0'+n if !n[3]) for x in [0..2];n?=q;o+=n+"\n" if i;a=n.split(e).sort().join(e);n=a.split(e).reverse().join(e);o+=n+' - '+a+' = ';n-=a;i++
alert(o+"6174\nIterations: "+i+'.')

Pruébalo aquí o con instrucciones aquí .


Mi navegador se congela: tuve que cancelar la ejecución del script.
lunohodov

¿Qué número ingresaste? Lo probé en Firefox y Chrome para 4711 y 1 y un par de otros.
Jonas Elfström

El uso 0(como lo sugiere la solicitud) o al hacer clic en el botón cancelar hace que Safari se congele.
lunohodov

No sé por qué sugirió eso. Debe ingresar un número entre 1 y 9998 cuyos dígitos no sean todos idénticos. 0 es lo mismo que 0000 y causará un bucle infinito. Parece que la mayoría de las soluciones aquí omitieron la entrada de validación para mantener baja la cantidad de caracteres.
Jonas Elfström

Consulte i56.tinypic.com/bhhoqe.png Su salida también termina con "Se necesitaron 5 iteraciones para alcanzar la constante de Kaprekar". que no se ajusta a los requisitos.
lunohodov

2

Scala 276

object o{var i=0;def a(v:String){val c=v.toList.sortWith(_>_).mkString;val b=c.reverse;val d=c.toInt-b.toInt;val e="0"*(4-(d+"").length)+d;val p=c+" - "+b+" = "+e;if(d!=6174){println(p);i=i+1;a(e)}else{println(p+"\nIterations: "+(i+1)+".")}};def main(s:Array[String])=a(s(0))}

Scala 283

object o{var i=0;def a(v:String){val c=v.toList.sortWith(_>_).mkString;val b=c.reverse;val d=c.toInt-b.toInt;val e="0"*(4-(d+"").length)+d;val p=c+" - "+b+" = "+e;if(d!=6174){println(p);i=i+1;a(e)}else{println(p);println("Iterations: "+(i+1)+".")}};def main(s:Array[String])=a(s(0))}

diff:

else{println(p);println("Iterations: "+(i+1)+".")}};
// to
else{println(p+"\nIterations: "+(i+1)+".")}};

2

GAWK - 152 caracteres

Esta es una versión awk de GNU. Es posible que no funcione con otras versiones que no sean GNU.

{for(z=$1;z-6174+!c;++k){split(z,a,"");asort(a);for(b=c=i=0;i<4;z=c-b){c+=a[i+1]*10^i;b=b*10+a[++i]}printf c" - %.4d = "z"\n",b}print"Iterations: "k"."}

$ awk -f k.awk <<< 9992
2999 - 9992 = 6993
3699 - 9963 = 6264
2466 - 6642 = 4176
1467 - 7641 = 6174
Iterations: 4

Recibo awk: calling undefined function asort. La versión Awk es 20070501 ejecutándose en OSX 10.6.7. No olvide el .después del número de iteraciones.
lunohodov

lunohodov @: Se agregó un punto perdido. Además, he usado gnu awk (gawk), y eso puede explicar la función que falta.
Dan Andreatta

Los números de resta son al revés: por ejemplo, debería ser9992 - 2999 = 6993
Chris Degnen

2

Ruby, 179 caracteres pero publicando de todos modos

s=gets.chomp
n=0
begin
  s=s.to_s.chars.sort.reduce{|s,c|s+c}.rjust(4,'0')
  a=s.reverse
  puts"#{a} - #{s} = #{'%04d'%(s=a.to_i-s.to_i)}"
  n+=1
end while s!=6174
puts"Iterations: #{n}."

Ruby es genial
Don brillante

1

PERL

chomp($n=<STDIN>);
    do{
       $t++;
       $desc=join('',reverse sort split(//,$n));
       $asc=join('', sort split(//,$n));
       $n=($desc - $asc);
       for($i=4;$i>length $n;$i--){
          $n="0".$n;
       }
       print $desc." - ".$asc." = ".$n."\n";
       $n="6174" if $n eq "0000";
    }while($n ne "6174");
    print "Iterations: $t.\n";

Eso es ~ 310 caracteres ...
Aman ZeeK Verma

1

K, 104

{b::();{b,:,k," = ",r:"0"^(-:4)$$. k:(x@>x)," - ",x@<x;r}\[$x];-1'c,,"Iterations: ",$#c:$[1=#b;b;-1_b];}

Casos de prueba

k){b::();{b,:,k," = ",r:"0"^(-:4)$$. k:(x@>x)," - ",x@<x;r}\[$x];-1'c,,"Iterations: ",$#c:$[1=#b;b;-1_b];}'2607 1211 6174;
7620 - 0267 = 7353
7533 - 3357 = 4176
7641 - 1467 = 6174
Iterations: 3
2111 - 1112 = 0999
9990 - 0999 = 8991
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174
Iterations: 5
7641 - 1467 = 6174
Iterations: 1

1

Mathematica 314 291 caracteres

Este es el programa, kaprekar.m: -

SetOptions[$Output,FormatType->OutputForm];
x=$ScriptCommandLine[[2]];
f[x_]:=(a=Characters@x;
b=Sort@ToExpression@a;
c=Sort[FromDigits/@{#,Reverse@#}&@b];
{c,{b,a}}=IntegerString[{#2-#&@@c,c},10,4];
Print[a," - ",b," = ",c];c)
x=f@x;
e=NestWhileList[f,x,#!="6174"&];
Print["Iterations: ",N@Length@e]

Configuración de la ruta antes de ejecutar: -

$ PATH=${PATH}:/Applications/Mathematica.app/Contents/MacOS ; export PATH

Ejecutando el programa: -

$ MathematicaScript -script kaprekar.m 2607
7620 - 0267 = 7353
7533 - 3357 = 4176
7641 - 1467 = 6174
Iterations: 3.
$ MathematicaScript -script kaprekar.m 1211
2111 - 1112 = 0999
9990 - 0999 = 8991
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174
Iterations: 5.
$ MathematicaScript -script kaprekar.m 6174
7641 - 1467 = 6174
Iterations: 1.

0

PHP , 160 bytes

function k($n,$d=1){$o=str_split($n);sort($o);echo$q=strrev($r=join($o))," - $r = ",$n=str_pad($q-$r,4,0,0),"
",$n==6174?"Iterations: $d.":k($n,++$d);}k($argn);

Pruébalo en línea!

Programa completo, entrada es STDIN, ejecutar con php -nF.

Salida

> echo 2607|php -nF kap.php
7620 - 0267 = 7353
7533 - 3357 = 4176
7641 - 1467 = 6174
Iterations: 3.

> echo 1211|php -nF kap.php
2111 - 1112 = 0999
9990 - 0999 = 8991
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174
Iterations: 5.

> echo 6174|php -nF kap.php
7641 - 1467 = 6174
Iterations: 1.

0

Óxido - 375 bytes

use std::io::{self,BufRead};fn main() {let mut x=io::stdin().lock().lines().next().unwrap().unwrap().parse::<i16>().unwrap();let mut n=0;println!("Iterations: {}.",loop {let mut v=[x/1000%10,x/100%10,x/10%10,x%10];v.sort();let j=v.iter().fold(0,|a,i|a*10+i);let k=v.iter().rev().fold(0,|a,i|a*10+i);x=k-j;n+=1;println!("{:04} - {:04} = {:04}",k,j,x);if x==6174{break n};});}

Presento esto como un posible "límite superior", desafío a cualquiera a encontrar un lenguaje donde una implementación razonable de esto sea más larga, ya que no hay nada superfluo, pero tampoco nada remotamente obvio que lo reduzca significativamente. Lo que pasa con Rust es que se necesitan unos 120 caracteres para leer de stdin y analizar en un entero. "Ah, pero solo usa la representación de cadena" ... pero estoy 99% seguro de que sería aún más largo


0

Perl 6 -n bandera, 105 bytes

say "Iterations: "~+.&{{{say $!=.flip~" - $_"," = ",($/=$!.EVAL.fmt("%04d"));$/}([~] .comb.sort)}...6174}

Pruébalo en línea!

Finalmente pude usar mi {}...*truco, ya que necesitamos tener al menos una iteración para 6174. Sin embargo, no estoy seguro de por qué necesito el ajuste adicional .&{ }alrededor de la secuencia, lo que apesta.

Explicación:

    .&{                         } # Call a function on the input
       {                }...6174  # Create a sequence that goes until 6174
        {           }([~] .comb.sort) # Get the sorted digits of the number
         say $!=.flip~" - $_"," = "~($/=$!.EVAL.fmt("%04d"))  # Print the iteration
                        ;$/  # Return the result
say "Iterations: "~+.&{      }     # Print the number of iterations
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.