Código Golf: 6174 - a constante mítica de Kaprekar


24

Por que o número 6174 é tão interessante? Conforme definido pela Wikipedia

  1. Pegue qualquer número de quatro dígitos, usando pelo menos dois dígitos diferentes. (Zeros à esquerda são permitidos.)
  2. Organize os dígitos em ordem crescente e depois em ordem decrescente para obter dois números de quatro dígitos, adicionando zeros à esquerda, se necessário.
  3. Subtraia o número menor do número maior.
  4. Volte para a etapa 2.

O processo acima, conhecido como rotina de Kaprekar, sempre alcançará 6174 em no máximo 7 iterações. Quando 6174 for alcançado, o processo continuará produzindo-o.

Escreva um programa que execute a rotina do Kaprekar em relação a um determinado número de quatro dígitos (veja a definição acima) imprimindo cada etapa da rotina.

Regras:

  • As inscrições devem ser programas completos.
  • A entrada deve ser lida a partir da entrada padrão. A tubulação do eco está OK.
  • A entrada deve estar na forma numérica.
  • É necessário imprimir zeros à esquerda. (Veja exemplos abaixo.)
  • A última linha deve dizer quantas iterações foram necessárias. A pontuação é necessária.

Exemplos:

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

Qualquer linguagem de programação é bem vinda. Pontos extras para os esotéricos + uma pequena recompensa.

Atualização 1 : já existe uma pergunta semelhante .

Atualização 2 : Exemplo adicionado para 6174 como entrada. Obrigado a Peter Taylor pelo aviso.


Isso é novidade para mim. Chamar alguém um moderador ...

Uh ... não existe um botão "migrar"?
perfil completo de Rebmu

Sinalizei isso para um moderador migrar. Posso sugerir alterar as regras na saída de entrada para concordar com a versão anterior de 3 dígitos? E ligando para a versão anterior no corpo da pergunta.
precisa

@dmckee Eu não sabia sobre este site e não sabia que já existe uma pergunta semelhante (no stackoverflow não havia nenhuma). No entanto, hesitaria em alterar as regras para concordar com a versão de 3 dígitos e, assim, tornar as duas perguntas ainda mais semelhantes. Não faz sentido postar uma duplicata ou uma ligeira variação de uma pergunta existente. Mesmo quando feito sem intenção.
Lunohodov

3
Por favor, adicione 6174 como exemplo, para que possamos ver como a saída deve ser formatada.
Peter Taylor

Respostas:


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"

EDIT: agora está em conformidade com 6174 caso, ao custo de alguns caracteres ... executado com echo -n <number> | perl kaprekar.pl

EDIT: Finalmente de volta para onde eu estava 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/}}."

Exemplo de invocação:

$ echo 1211 | ruby -ln kaprekar.rb

Eu contei a -lnbandeira como 4 caracteres (diferença entre a invocação normal ruby kaprekar.rbe ruby -ln kaprekar.rb).


Salvei esse script como kaprekar.rb e o invoquei ruby -lp kaprekar.rb. Digite um número e pressione <Enter>, mas a saída é o próprio número digitado. Claramente estou perdendo alguma coisa ... Por favor, informe como usar o script.
Lunohodov

@lunohodov: adicionei um exemplo de invocação. Agora também gera a saída correta para 6174entrada, o que infelizmente traz essa solução para até 128 caracteres.
Ventero

Usar echo 1234 | ruby kaprekar.rbgera um aviso e termina com um erro undefined method 'chars' for nil:NilClass (NoMethodError). A execução echo 1234 | ruby -lp kaprekar.rbemite apenas um aviso e se comporta conforme o esperado. A saída não é o esperado, uma vez que contém uma mensagem de avisokaprekar.rb:3: warning: regex literal in condition
lunohodov

@lunohodov: corrigido o aviso e o exemplo de invocação.
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 preenchimento liso com% 04d. Eu aprendi algo hoje!
58613 arrdem

3
Algumas sugestões: coloque o loop inteiro em uma linha usando ;s. while n-6174. Não há espaço entre printe a cotação.
perfil completo de Keith Randall

@ keith-randall: obrigado, diminuiu para 141 agora.
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)

Inclinar re ssalvar 2 caracteres. Além disso, "000" é redundante. "0" é suficiente. Isso nos leva a 188 caracteres. Estou surpreso interactnão ajuda aqui. Geralmente faz.
Rotsor

Substituindo show x++spor shows x sganha mais 2 bytes. 186 agora.
Rotsor

Usando guardas de padrões ( |k>0), é possível se livrar f. Além disso renomeação gpara %nós chega 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;

Não é um grande candidato ao golfe, mas foi divertido escrever. :)

Execute com./fish.py kaprekar.fish -v <number>
EDIT: agora recebe entrada do STDIN.


4

JavaScript, 189 182 165 caracteres

Crédito para 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+'.')

Ungolfed:

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 + '.');

11
Eu acho que você pode mudar n != 6174para, n-6174pois retornará zero, o que é falso (pelo menos em C e Python).
Martin Ueding 10/06

O crédito deve ser dado a keith-randall, que o sugeriu para minha solução Python.
Martin Ueding 10/06

Você pode salvar mais 5 caracteres substituindo while(n.length<4)por while(!n[3]).
DocMax

11
Não consigo parar de encarar esse aqui! A seguir, a) corrige a saída quando n = 6174, b) reorganiza quando n+'\n'é adicionado para evitar o condicional e um extra \n, c) usa um temp para evitar uma sequência de junção-divisão-junção, d) tira proveito do fato de que sempre é necessário adicionar um único '0' para preenchimento: 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 deve ser 172 caracteres.
DocMax

11
Impressionante! Porém, de acordo com a especificação acima, quando n = 6174, ele deve passar por pelo menos uma iteração, então eu adicionei uma verificação se ié 0 (+4), mas combinada com a i++. Infelizmente, isso resulta em um erro, por isso mudei o incremento para um decréscimo e depois usei um pouco de truque bit a bit no final (-1). Então mudei i=0,o=e=''para i=o=e=''(-2), reformatei o forloop para evitar parênteses extras (-1), (b=...,a=...,b)bit expandido (-2) e entrei furtivamente a=b.joinna reverse()chamada (-1). Então, 169, nada 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."

Passa todos os casos de teste da pergunta.


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 o recurso App do Scala 2.9.

Editar: fornece a saída correta para a entrada inicial de 6174.


2

PHP, 215 259 276 personagens

<?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";

Ungolfed:

<?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";

Eu não acho que você precise das funções abs, maxe min, pois o tipo sempre significa que $bé maior que $a. Isso pode economizar 20 caracteres. Além disso, acho que colocar o tipo dentro do loop no topo significará que você só precisa inseri-lo em seu código uma vez, o que lhe poupará mais nove.
Gareth

Uau, acho que me distraí com a instrução "subtraia o número menor do número maior". Obrigado.
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";} Você pode salvar 12 caracteres alterando sua forinstrução, chamando isso de função e usando em joinvez de implode.
TwoScoopsofPig

Além disso, eu odeio mini-markdown.
TwoScoopsofPig 17/10/12

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+'.')

Experimente aqui ou com instruções aqui .


Meu navegador congela - tive que cancelar a execução do script.
Lunohodov

Em que número você entrou? Eu tentei no Firefox e Chrome para 4711 e 1 e mais alguns.
Jonas Elfström

Usar 0(conforme sugerido pelo prompt) ou clicar no botão Cancelar faz com que o Safari congele.
Lunohodov

Não sei por que isso sugeriu isso. Você deve inserir um número entre 1 e 9998 cujos dígitos não sejam todos idênticos. 0 é igual a 0000 e causará um loop infinito. Parece que a maioria das soluções ignorou a validação de entrada para manter o número de caracteres baixo.
Jonas Elfström

Consulte i56.tinypic.com/bhhoqe.png Sua saída também termina com "Foram necessárias 5 iterações para alcançar a constante de Kaprekar". que não está em conformidade com os 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 é uma versão do GNU awk. Pode não funcionar com outras versões que não sejam 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

Eu recebo awk: calling undefined function asort. A versão do awk é 20070501 em execução no OSX 10.6.7. Não esqueça o .depois do número de iterações.
Lunohodov

lunohodov @: ponto faltante adicionado. Além disso, usei o gnu awk (gawk) e isso pode explicar a função que está faltando.
Dan Andreatta

Os números da subtração estão ao contrário: por exemplo, deveria ser9992 - 2999 = 6993
Chris Degnen

2

Ruby, 179 caracteres, mas postando assim mesmo

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 é muito legal
don bright

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";

Thats ~ 310 caracteres ...
Aman Verma Zeek

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 teste

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 é o 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]

Configurando o caminho antes da execução: -

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

Executando o 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);

Experimente online!

Programa completo, a entrada é STDIN, execute com php -nF.

Saída

> 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

Ferrugem - 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};});}

Apresento isso como um possível "limite superior", desafio qualquer pessoa a encontrar uma linguagem em que uma implementação razoável disso seja mais longa - como não há nada supérfluo, mas também nada remotamente óbvio que a reduza significativamente. O problema do Rust é que são necessários cerca de 120 caracteres para serem lidos no stdin e analisados ​​em um número inteiro. "Ah, mas apenas use a representação de string" ... mas estou 99% confiante de que seria ainda mais longo


0

Sinalizador Perl 6 -n, 105 bytes

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

Experimente online!

Eu finalmente consegui usar meu {}...* truque, já que precisamos ter pelo menos uma iteração para o 6174. Não sei por que preciso do envolvimento adicional em .&{ }torno da sequência, o que é meio ruim.

Explicação:

    .&{                         } # 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.