Code Golf: 6174 - Kaprekars mythische Konstante


24

Warum ist die Nummer 6174 so interessant? Wie von Wikipedia definiert

  1. Nehmen Sie eine beliebige vierstellige Nummer mit mindestens zwei verschiedenen Ziffern. (Führende Nullen sind erlaubt.)
  2. Ordnen Sie die Ziffern in aufsteigender und absteigender Reihenfolge an, um zwei vierstellige Zahlen zu erhalten, und fügen Sie gegebenenfalls führende Nullen hinzu.
  3. Subtrahieren Sie die kleinere Zahl von der größeren Zahl.
  4. Fahren Sie mit Schritt 2 fort.

Der obige Prozess, bekannt als Kaprekars Routine, erreicht immer 6174 in höchstens 7 Iterationen. Sobald 6174 erreicht ist, wird der Prozess fortgesetzt, um es zu ergeben.

Schreiben Sie ein Programm, das die Kaprekar-Routine anhand einer bestimmten vierstelligen Zahl (siehe Definition oben) ausführt und jeden Schritt der Routine druckt.

Regeln:

  • Einsendungen müssen vollständige Programme sein.
  • Die Eingabe muss von der Standardeingabe gelesen werden. Das Leiten von Echo ist in Ordnung.
  • Die Eingabe sollte in numerischer Form erfolgen.
  • Es ist erforderlich, führende Nullen auszudrucken. (Siehe Beispiele unten.)
  • In der letzten Zeile sollte angegeben werden, wie viele Iterationen benötigt wurden. Interpunktion ist erforderlich.

Beispiele:

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

Jede Programmiersprache ist willkommen. Extra Punkte für Esoteriker + ein kleines Kopfgeld.

Update 1 : Es gibt bereits eine ähnliche Frage .

Update 2 : Beispiel für 6174 als Eingabe hinzugefügt. Vielen Dank an Peter Taylor für den Hinweis.


Das sind Neuigkeiten für mich. Jemand nennt einen Moderator ...

Äh ... gibt es nicht einen "Migrieren" -Button?
Dr. Rebmu

Ich habe dies markiert, damit ein Moderator migrieren kann. Darf ich vorschlagen, die Regeln für die Eingabe und Ausgabe zu ändern, um mit der früheren dreistelligen Version übereinzustimmen? Und auf die frühere Version im Hauptteil der Frage verlinken.
dmckee

@dmckee Ich wusste nichts über diese Site und konnte nicht wissen, dass es bereits eine ähnliche Frage gibt (zu stackoverflow gab es keine). Ich würde jedoch zögern, die Regeln zu ändern, um mit der dreistelligen Version übereinzustimmen und so die beiden Fragen noch ähnlicher zu machen. Es ist sinnlos, ein Duplikat oder eine geringfügige Änderung einer vorhandenen Frage zu posten. Auch wenn es ungewollt gemacht wird.
Lunohodov

3
Fügen Sie als Beispiel 6174 hinzu, damit wir sehen können, wie die Ausgabe formatiert werden soll.
Peter Taylor

Antworten:


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"

BEARBEITEN: Entspricht jetzt dem 6174-Fall, kostet ein paar Zeichen ... läuft mit echo -n <number> | perl kaprekar.pl

EDIT: Endlich wieder da, wo ich vorher war: D


10

Ruby 1.9, 122 Zeichen

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

Beispielaufruf:

$ echo 1211 | ruby -ln kaprekar.rb

Ich habe das -lnFlag als 4 Zeichen gezählt (Unterschied zwischen dem normalen Aufruf ruby kaprekar.rbund ruby -ln kaprekar.rb).


Ich habe dieses Skript als kaprekar.rb gespeichert und es dann mit aufgerufen ruby -lp kaprekar.rb. Geben Sie eine Nummer ein und drücken Sie die <Eingabetaste>, aber die Ausgabe ist die eingegebene Nummer. Mir fehlt ganz klar etwas ... Bitte geben Sie an, wie Sie das Skript verwenden sollen.
Lunohodov

@ Lunohodov: Ich habe ein Beispiel Aufruf hinzugefügt. Es wird nun auch die richtige Ausgabe für 6174als Eingabe generiert , was diese Lösung leider auf 128 Zeichen bringt.
Ventero

Die Verwendung von echo 1234 | ruby kaprekar.rblöst eine Warnung aus und endet mit einem Fehler undefined method 'chars' for nil:NilClass (NoMethodError). Das Ausführen echo 1234 | ruby -lp kaprekar.rbgibt nur eine Warnung aus und verhält sich wie erwartet. Die Ausgabe ist nicht wie erwartet, da sie eine Warnmeldung enthältkaprekar.rb:3: warning: regex literal in condition
Lunohodov

@lunohodov: Die Warnung und der Beispielaufruf wurden behoben.
Ventero

7

Python, 141 Zeichen

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 für Slick-Auffüllung mit% 04d. Ich habe heute etwas gelernt!
Arrdem

3
Ein paar Vorschläge: Setzen Sie die gesamte Schleife mit ;s auf eine Zeile . while n-6174. Kein Leerzeichen zwischen printund dem Zitat.
Keith Randall

@ keith-randall: danke, habe es jetzt auf 141 gebracht.
Martin Ueding

6

Golfscript, 74 Zeichen

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

5

Haskell, 197 192 182 181 Zeichen

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)

Inlining rund sspeichert 2 Zeichen. Auch "000" ist überflüssig. "0" ist genug. Dies bringt uns zu 188 Zeichen. Ich bin überrascht interact, hilft hier nicht. Das tut es normalerweise.
Rotsor

Ersetzen show x++smit shows x sgewinnt 2 weitere Bytes. 186 jetzt.
Rotsor

Mit Pattern Guards ( |k>0) kann man das loswerden f. Weitere Umbenennung gzu %bringt uns zu 182 Zeichen.
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;

Es ist kein großer Anwärter auf Golf, aber es hat Spaß gemacht zu schreiben. :)

Run with./fish.py kaprekar.fish -v <number>
EDIT: Nimmt jetzt Eingaben von STDIN entgegen.


4

JavaScript, 189 182 165 Zeichen

Gutschrift für 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 + '.');

1
Ich denke, dass Sie ändern können n != 6174, n-6174da es Null zurückgibt, was falsch ist (zumindest in C und Python).
Martin Ueding

Der Kredit sollte an Keith-Randall gehen, der ihn für meine Python-Lösung vorgeschlagen hat.
Martin Ueding

Sie können 5 weitere Zeichen sparen durch Ersetzen while(n.length<4)mit while(!n[3]).
DocMax

1
Ich kann nicht aufhören, diesen einen anzustarren! Das Folgende a) behebt die Ausgabe, wenn n = 6174, b) ordnet neu an, wenn n+'\n'hinzugefügt wird, um die Bedingung und ein Extra zu vermeiden \n, c) verwendet ein Temp, um eine Join-Split-Join-Sequenz zu vermeiden, d) nutzt die Tatsache, dass wir Es muss immer nur eine einzelne '0' zum Auffüllen hinzugefügt werden: Das 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+'.')sollten 172 Zeichen sein.
DocMax

1
Beeindruckend! Gemäß der obigen Spezifikation muss es jedoch, wenn n = 6174 ist, mindestens eine Iteration durchlaufen, also habe ich eine Prüfung hinzugefügt, ob i0 (+4) ist, aber diese mit der kombiniert i++. Leider gibt das einen Fehler von eins aus, also habe ich das Inkrement auf ein Dekrement umgestellt und dann am Ende ein bisschen Trick benutzt (-1). Dann habe ich i=0,o=e=''zu i=o=e=''(-2) gewechselt , die forSchleife neu formatiert , um zusätzliche Klammern (-1) zu vermeiden, das (b=...,a=...,b)Bit (-2) erweitert und mich a=b.joinin den reverse()Aufruf eingeschlichen (-1). Also 169, nicht schlecht!
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."

Besteht alle Testfälle aus der Frage.


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 Zeichen

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

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

Nutzt das App-Merkmal von Scala 2.9.

Bearbeiten: Gibt die korrekte Ausgabe für die anfängliche Eingabe von 6174 aus.


2

PHP, 215 259 276 Zeichen

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

Ich glaube nicht , müssen Sie die abs, maxund minFunktionen, da die Art immer bedeuten , dass $bgrößer ist als $a. Das könnte Ihnen 20 Charaktere ersparen. Außerdem denke ich, dass das Einfügen der Sortierung in die Schleife oben bedeutet, dass Sie sie nur einmal in Ihrem Code haben müssen, was Ihnen weitere 9
erspart

Wow, ich glaube, ich wurde durch die Anweisung "subtrahiere die kleinere Zahl von der größeren Zahl" abgelenkt. Vielen Dank.
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";} Sie können 12 Zeichen speichern, indem Sie Ihre forAnweisung ändern , diese als Funktion aufrufen und joinanstelle von verwenden implode.
TwoScoopsofPig

Außerdem hasse ich Mini-Abschriften.
TwoScoopsofPig

2

CoffeeScript, 233 225 Zeichen

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

Probieren Sie es hier oder mit Anweisungen hier .


Mein Browser friert ein - musste die Ausführung des Skripts abbrechen.
Lunohodov

Welche Nummer hast du eingegeben? Ich habe es in Firefox und Chrome für 4711 und 1 und ein paar andere ausprobiert.
Jonas Elfström

Wenn Sie 0(wie von der Eingabeaufforderung vorgeschlagen) verwenden oder auf die Schaltfläche Abbrechen klicken, friert Safari ein.
Lunohodov

Ich weiß nicht, warum das so war. Sie müssen eine Zahl zwischen 1 und 9998 eingeben, deren Ziffern nicht alle identisch sind. 0 ist dasselbe wie 0000 und führt zu einer Endlosschleife. Es scheint, dass die meisten Lösungen hier die Validierung von Eingaben übersprungen haben, um die Anzahl der Zeichen gering zu halten.
Jonas Elfström

Siehe i56.tinypic.com/bhhoqe.png Ihre Ausgabe endet auch mit "Es dauerte 5 Iterationen, um die Kaprekar-Konstante zu erreichen." was nicht den Anforderungen entspricht.
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 Zeichen

Dies ist eine GNU awk-Version. Es funktioniert möglicherweise nicht mit anderen Nicht-Gnu-Versionen.

{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

Ich erhalte awk: calling undefined function asort. Die Awk-Version ist 20070501 und läuft unter OSX 10.6.7. Vergessen Sie nicht, die .nach der Anzahl der Iterationen.
Lunohodov

lunohodov @: Fehlender Punkt hinzugefügt. Außerdem habe ich gnu awk (gawk) benutzt, und das könnte die fehlende Funktion erklären.
Dan Andreatta

Die Subtraktionszahlen sind falsch herum: zB sollte9992 - 2999 = 6993
Chris Degnen

2

Ruby, 179 Zeichen, aber trotzdem Posten

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 ist ziemlich cool
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";

Das sind ~ 310 Zeichen ...
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];}

Testfälle

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 Zeichen

Dies ist das Programm, 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]

Festlegen des Pfades vor dem Laufen: -

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

Ausführen des Programms: -

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

Probieren Sie es online!

Komplettes Programm, Eingabe wird STDINmit ausgeführt php -nF.

Ausgabe

> 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

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

Ich stelle dies als eine mögliche "Obergrenze" vor und fordere jeden dazu auf, eine Sprache zu finden, in der eine sinnvolle Implementierung länger ist - da nichts überflüssig ist, aber auch nichts, was auch nur annähernd offensichtlich ist, dass es erheblich schrumpfen würde. Die Sache mit Rust ist, dass es ungefähr 120 Zeichen braucht, um von stdin zu lesen und in eine Ganzzahl zu analysieren. "Oh, aber dann benutze einfach die String-Darstellung" ... aber ich bin zu 99% zuversichtlich, dass das noch länger dauern würde


0

Perl 6- n-Flag, 105 Bytes

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

Probieren Sie es online!

Endlich muss ich meinen {}...*Trick anwenden, da wir für 6174 mindestens eine Iteration benötigen. Ich bin mir nicht sicher, warum ich .&{ }die Sequenz zusätzlich umschließen muss , was irgendwie scheiße ist.

Erläuterung:

    .&{                         } # 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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.