Codice Golf: 6174 - La mitica costante di Kaprekar


24

Perché il numero 6174 è così interessante? Come definito da Wikipedia

  1. Prendi qualsiasi numero di quattro cifre, usando almeno due cifre diverse. (Sono consentiti zeri iniziali.)
  2. Disporre le cifre in ordine crescente e poi in ordine decrescente per ottenere due numeri di quattro cifre, aggiungendo zeri iniziali, se necessario.
  3. Sottrai il numero più piccolo dal numero più grande.
  4. Torna al passaggio 2.

Il processo sopra descritto, noto come routine di Kaprekar, raggiungerà sempre 6174 al massimo in 7 iterazioni. Una volta raggiunto 6174, il processo continuerà a produrlo.

Scrivi un programma che esegue la routine di Kaprekar su un dato numero di quattro cifre (vedi la definizione sopra) stampando ogni fase della routine.

Regole:

  • Gli invii devono essere programmi completi.
  • L'input deve essere letto dall'input standard. Il piping dall'eco è OK.
  • L'input deve essere in forma numerica.
  • È richiesta la stampa di zeri iniziali. (Vedi gli esempi di seguito.)
  • L'ultima riga dovrebbe indicare quante iterazioni erano necessarie. La punteggiatura è obbligatoria.

Esempi:

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

Qualsiasi linguaggio di programmazione è il benvenuto. Punti extra per quelli esoterici + una piccola taglia.

Aggiornamento 1 : esiste già una domanda simile .

Aggiornamento 2 : aggiunto esempio per 6174 come input. Grazie a Peter Taylor per l'avviso.


Questa è una novità per me. Qualcuno chiama un moderatore ...

Uh ... non c'è un pulsante "migra"?
Dr. Rebmu,

Ho segnalato questo per far migrare un moderatore. Posso suggerire di modificare le regole sull'output di input per concordare con la precedente versione a 3 cifre? E il collegamento alla versione precedente nel corpo della domanda.
dmckee,

@dmckee Non conoscevo questo sito e non sapevo che ci fosse già una domanda simile (su StackOverflow non ce n'era nessuna). Tuttavia esiterei a modificare le regole per concordare con la versione a 3 cifre e rendere le due domande ancora più simili. È inutile pubblicare un duplicato o una leggera variazione di una domanda esistente. Anche quando fatto involontariamente.
lunohodov,

3
Aggiungi 6174 come esempio in modo da poter vedere come deve essere formattato l'output.
Peter Taylor,

Risposte:


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: ora rispetta il caso 6174, al costo di alcuni caratteri ... corri con echo -n <number> | perl kaprekar.pl

EDIT: Finalmente tornando a dove ero prima: D


10

Ruby 1.9, 122 caratteri

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

Esempio di invocazione:

$ echo 1211 | ruby -ln kaprekar.rb

Ho contato la -lnbandiera come 4 caratteri (differenza tra l'invocazione normale ruby kaprekar.rbe ruby -ln kaprekar.rb).


Ho salvato questo script come kaprekar.rb e poi l'ho invocato ruby -lp kaprekar.rb. Inserito un numero e premuto <Invio> ma l'uscita è il numero inserito stesso. Chiaramente mi manca qualcosa ... Si prega di avvisare come utilizzare lo script.
lunohodov,

@lunohodov: ho aggiunto un invito di esempio. Ora genera anche l'output corretto 6174come input, che sfortunatamente porta questa soluzione a 128 caratteri.
Ventero,

L'utilizzo echo 1234 | ruby kaprekar.rbgenera un avviso e termina con un errore undefined method 'chars' for nil:NilClass (NoMethodError). L'esecuzione echo 1234 | ruby -lp kaprekar.rbemette solo un avviso e si comporta come previsto. L'output non è come previsto, poiché contiene un messaggio di avvisokaprekar.rb:3: warning: regex literal in condition
lunohodov,

@lunohodov: risolti l'avvertimento e l'invocazione di esempio.
Ventero,

7

Python, 141 caratteri

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 per l'imbottitura liscia con% 04d. Ho imparato qualcosa oggi!
arrdem

3
Alcuni suggerimenti: metti l'intero ciclo su una riga usando ;s. while n-6174. Nessuno spazio tra printe la citazione.
Keith Randall,

@ keith-randall: grazie, adesso sono sceso a 141.
Martin Ueding l'

6

Golfscript, 74 caratteri

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

5

Haskell, 197 192 182 181 caratteri

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)

Inline re ssalva 2 caratteri. Inoltre, "000" è ridondante. "0" è abbastanza. Questo ci porta a 188 caratteri. Sono sorpreso interactnon aiuta qui. Di solito lo fa.
Rotsor,

Sostituendo show x++scon shows x sguadagna altri 2 byte. 186 ora.
Rotsor,

Usando i pattern guards ( |k>0) è possibile sbarazzarsi di f. Ulteriori ridenominazione gdi %noi arriva a 182 caratteri.
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;

Non è un contendente per il golf, ma è stato divertente scrivere. :)

Esegui con./fish.py kaprekar.fish -v <number>
EDIT: ora accetta input da STDIN.


4

JavaScript, 189 182 165 caratteri

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

Originale:

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

1
Penso che puoi passare n != 6174a n-6174poiché restituirà zero, il che è falso (almeno in C e Python).
Martin Ueding,

Il merito dovrebbe essere quello di Keith-Randall che lo ha suggerito per la mia soluzione Python.
Martin Ueding,

Puoi salvare altri 5 personaggi sostituendoli while(n.length<4)con while(!n[3]).
DocMax,

1
Non riesco a smettere di fissarlo! Quanto segue a) corregge l'output quando n = 6174, b) riorganizza quando n+'\n'viene aggiunto per evitare il condizionale e un extra \n, c) utilizza una temperatura per evitare una sequenza join-split-join, d) sfrutta il fatto che noi 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+'.')devi solo aggiungere un solo '0' per il riempimento: che dovrebbe essere 172 caratteri.
DocMax,

1
Impressionante! Secondo la specifica sopra, tuttavia, quando n = 6174, deve passare almeno un'iterazione, quindi ho aggiunto un controllo se iè 0 (+4) ma combinato con quello i++. Sfortunatamente, questo dà un errore per un errore, quindi ho spostato l'incremento in un decremento e poi ho usato un po 'di inganno alla fine (-1). Quindi sono passato i=0,o=e=''a i=o=e=''(-2), ho riformattato il forloop per evitare parentesi extra (-1), (b=...,a=...,b)bit espanso (-2) e nascosto a=b.joinall'interno della reverse()chiamata (-1). Quindi 169, non male!
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 tutti i casi di test dalla domanda.


2

JavaScript, 260 byte

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 caratteri

(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 caratteri

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+".")}

Utilizza il tratto App di Scala 2.9.

Modifica: fornisce l'output corretto per l'input iniziale di 6174.


2

PHP, 215 259 276 personaggi

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

Non credo che avete bisogno di abs, maxe le minfunzioni, dal momento che l'ordinamento sempre significa che $bè superiore $a. Ciò potrebbe salvarti 20 personaggi. Inoltre, penso che mettere l'ordinamento all'interno del ciclo in alto significherà che devi solo averlo nel tuo codice una volta, il che ti farà risparmiare un altro 9.
Gareth

Wow, immagino di essermi distratto dall'istruzione "sottrarre il numero più piccolo dal numero più grande". Grazie.
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";} Puoi salvare 12 caratteri cambiando la tua fordichiarazione, chiamandola come una funzione e usando joininvece di implode.
TwoScoopsofPig

Inoltre, odio il mini-markdown.
TwoScoopsofPig

2

CoffeeScript, 233 225 caratteri

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

Provalo qui o con le istruzioni qui .


Il mio browser si blocca - ha dovuto annullare l'esecuzione dello script.
lunohodov,

Quale numero hai inserito? L'ho provato in Firefox e Chrome per 4711 e 1 e un paio di altri.
Jonas Elfström,

L'uso 0(come suggerito dal prompt) o facendo clic sul pulsante Annulla provoca il blocco di Safari.
lunohodov,

Non so perché lo abbia suggerito. Devi inserire un numero compreso tra 1 e 9998 le cui cifre non sono tutte identiche. 0 è uguale a 0000 e causerà un ciclo infinito. Sembra che la maggior parte delle soluzioni qui abbia saltato l'input di convalida per contenere il numero di caratteri.
Jonas Elfström,

Vedi i56.tinypic.com/bhhoqe.png L'output termina anche con "Sono state necessarie 5 iterazioni per raggiungere la costante di Kaprekar". che non è conforme ai requisiti.
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 caratteri

Questa è una versione GNU Awk. Potrebbe non funzionare con altre versioni non 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

Ricevo awk: calling undefined function asort. La versione Awk è 20070501 in esecuzione su OSX 10.6.7. Non dimenticare il .dopo il numero di iterazioni.
lunohodov,

lunohodov @: aggiunto punto mancante. Inoltre, ho usato gnu awk (gawk) e questo potrebbe spiegare la funzione mancante.
Dan Andreatta,

I numeri di sottrazione sono al contrario: es. Dovrebbe essere9992 - 2999 = 6993
Chris Degnen,

2

Ruby, 179 caratteri ma invio comunque

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 è piuttosto figo
don luminoso

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

Quello è ~ 310 caratteri ...
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];}

Casi test

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

Matematica, 314 291 caratteri

Questo è il programma, 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]

Impostazione del percorso prima dell'esecuzione: -

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

Esecuzione del programma: -

$ 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 byte

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

Provalo online!

Programma completo, input is STDIN, run with php -nF.

Produzione

> 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

Ruggine - 375 byte

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

Lo presento come un possibile "limite superiore", sfido chiunque a trovare un linguaggio in cui una ragionevole implementazione di questo è più lunga - poiché in esso non c'è nulla di superfluo, ma anche nulla di remotamente ovvio che lo ridurrebbe in modo significativo. La cosa su Rust è che ci vogliono circa 120 caratteri solo per leggere da stdin e analizzare in un numero intero. "Oh, ma usa solo la rappresentazione di stringhe" ... ma sono sicuro al 99% che sarebbe ancora più lungo


0

Bandiera Perl 6 -n, 105 byte

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

Provalo online!

Finalmente ho potuto usare il mio {}...*Alla trucco, dal momento che dobbiamo avere almeno un'iterazione per 6174. Non sono sicuro del motivo per cui ho bisogno di avvolgere .&{ }la sequenza in più, che fa schifo.

Spiegazione:

    .&{                         } # 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.