Code Golf: 6174 - mityczna stała Kaprekara


24

Dlaczego liczba 6174 jest tak interesująca? Zgodnie z definicją Wikipedii

  1. Weź dowolny czterocyfrowy numer, używając co najmniej dwóch różnych cyfr. (Zera wiodące są dozwolone.)
  2. Ułóż cyfry w kolejności rosnącej, a następnie malejącej, aby uzyskać dwie czterocyfrowe liczby, dodając w razie potrzeby zera na początku.
  3. Odejmij mniejszą liczbę od większej liczby.
  4. Wróć do kroku 2.

Powyższy proces, znany jako rutyna Kaprekara, zawsze osiągnie 6174 w maksymalnie 7 iteracjach. Po osiągnięciu 6174 proces będzie go nadal uzyskiwał.

Napisz program, który uruchamia procedurę Kaprekara względem podanej czterocyfrowej liczby (patrz definicja powyżej), wypisując każdy krok procedury.

Zasady:

  • Zgłoszenia muszą być kompletnymi programami.
  • Wejście należy odczytać ze standardowego wejścia. Przesyłanie z echa jest prawidłowe.
  • Dane wejściowe powinny mieć postać liczbową.
  • Wymagane jest wydrukowanie zer wiodących. (Zobacz przykłady poniżej.)
  • W ostatnim wierszu należy podać, ile iteracji było potrzebnych. Wymagana jest interpunkcja.

Przykłady:

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

Każdy język programowania jest mile widziany. Dodatkowe punkty dla ezoterycznych + mała nagroda.

Aktualizacja 1 : Istnieje już podobne pytanie .

Aktualizacja 2 : Dodano przykład dla 6174 jako danych wejściowych. Dzięki Peter Taylor za powiadomienie.


To dla mnie nowość.

Uh ... czy nie ma przycisku „migruj”?
Dr. Rebmu

Oflagowałem to, aby moderator mógł przeprowadzić migrację. Czy mogę zasugerować zmianę zasad dotyczących danych wejściowych, aby zgadzały się z wcześniejszą trzycyfrową wersją? I link do wcześniejszej wersji w treści pytania.
dmckee,

@dmckee Nie wiedziałem o tej stronie i nie mogłem wiedzieć, że istnieje już podobne pytanie (na przepływie stosów nie było żadnych). Wahałbym się jednak, zmieniając zasady, aby zgodzić się na wersję trzycyfrową, a tym samym czyniąc te dwa pytania jeszcze bardziej podobnymi. Publikowanie duplikatu lub niewielkiej odmiany istniejącego pytania jest bezcelowe. Nawet jeśli zrobione niezamierzone.
lunohodov

3
Dodaj 6174 jako przykład, abyśmy mogli zobaczyć, jak formatować dane wyjściowe.
Peter Taylor,

Odpowiedzi:


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"

EDYCJA: Teraz jest zgodny ze skrzynką 6174, kosztem kilku znaków ... uciekaj echo -n <number> | perl kaprekar.pl

EDYCJA: W końcu z powrotem do miejsca, w którym byłem wcześniej: D


10

Ruby 1.9, 122 znaków

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

Przykładowe wywołanie:

$ echo 1211 | ruby -ln kaprekar.rb

Policzyłem -lnflagę jako 4 znaki (różnica między normalnym wywołaniem ruby kaprekar.rba ruby -ln kaprekar.rb).


Zapisałem ten skrypt jako kaprekar.rb, a następnie wywołałem go ruby -lp kaprekar.rb. Wpisano liczbę i wcisnął <Enter>, ale wynikiem jest sama wprowadzona liczba. Najwyraźniej czegoś mi brakuje ... Proszę doradzić, jak korzystać ze skryptu.
lunohodov

@lohohodov: Dodałem przykładowe wywołanie. Teraz generuje również prawidłowe dane wyjściowe 6174jako dane wejściowe, co niestety zwiększa to rozwiązanie do 128 znaków.
Ventero

Korzystanie echo 1234 | ruby kaprekar.rbpodnosi ostrzeżenie i kończy się błędem undefined method 'chars' for nil:NilClass (NoMethodError). Wykonanie echo 1234 | ruby -lp kaprekar.rbpowoduje tylko ostrzeżenie i działa zgodnie z oczekiwaniami. Dane wyjściowe nie są zgodne z oczekiwaniami, ponieważ zawierają komunikat ostrzegawczykaprekar.rb:3: warning: regex literal in condition
lunohodov

@lunohodov: Naprawiono ostrzeżenie i przykładowe wywołanie.
Ventero

7

Python, 141 znaków

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 za gładkie wypełnienie za pomocą% 04d. Nauczyłem się dziś czegoś!
arrdem

3
Kilka sugestii: umieść całą pętlę w jednej linii za pomocą ;s. while n-6174. Brak spacji między printi cytatem.
Keith Randall

@ keith-randall: dzięki, udało mi się teraz zmniejszyć do 141.
Martin Ueding

6

Golfscript, 74 znaki

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

5

Haskell, 197 192 182 181 znaków

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 ri szapisuje 2 znaki. Również „000” jest zbędne. „0” wystarczy. Daje nam to 188 znaków. Dziwię się, interactże tu nie pomaga. Zwykle tak jest.
Rotsor,

Wymiana show x++sz shows x szysków 2 więcej bajtów. 186 teraz.
Rotsor,

Korzystając ze strażników wzorów ( |k>0) można się pozbyć f. Dalsza zmiana nazwy gpozwala %nam uzyskać 182 znaki.
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;

Niewiele pretenduje do golfa, ale pisanie było fajne. :)

Uruchom z./fish.py kaprekar.fish -v <number>
EDYCJA: Teraz pobiera dane wejściowe z STDIN.


4

JavaScript, 189 182 165 znaków

Podziękowania dla 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+'.')

Oryginalny:

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

Nie golfowany:

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
Myślę, że możesz zmienić n != 6174na, n-6174ponieważ zwróci zero, co jest fałszem (przynajmniej w C i Pythonie).
Martin Ueding,

Podziękowania powinny pochodzić od keith-randall, który zaproponował to dla mojego rozwiązania Python.
Martin Ueding,

Możesz zapisać 5 dodatkowych znaków, zastępując while(n.length<4)je while(!n[3]).
DocMax

1
Nie mogę przestać się na to gapić! Poniższe a) naprawia wyjście, gdy n = 6174, b) zmienia kolejność, gdy n+'\n'jest dodawany, aby uniknąć warunkowego i dodatkowego \n, c) używa temp, aby uniknąć sekwencji łączenia-podziału-łączenia, d) wykorzystuje fakt, że wystarczy tylko dodać jedno „0” dla dopełnienia: 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+'.')powinno to być 172 znaki.
DocMax

1
Imponujący! Jednak zgodnie z powyższą specyfikacją, gdy n = 6174, musi przejść przez co najmniej jedną iterację, więc dodałem sprawdzenie, czy iwynosi 0 (+4), ale połączyłem to z i++. Niestety, powoduje to błąd o jeden błąd, więc zmieniłem przyrost na zmniejszenie, a następnie na końcu użyłem trochę sztuczek (-1). Następnie zmieniłem i=0,o=e=''na i=o=e=''(-2), sformatowałem forpętlę, aby uniknąć dodatkowych nawiasów (-1), rozszerzyłem (b=...,a=...,b)bit (-2) i zakradłem się a=b.joindo reverse()wywołania (-1). A więc 169, nieźle!
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."

Przechodzi wszystkie przypadki testowe z pytania.


2

JavaScript, 260 bajtów

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 znaków

(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 znaków

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

Wykorzystuje cechę aplikacji ze Scali 2.9.

Edycja: daje poprawne wyjście dla początkowego wejścia 6174.


2

PHP, 215 259 276 postacie

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

Nie golfowany:

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

Nie sądzę, że trzeba zastosować abs, maxoraz minfunkcje, ponieważ ten rodzaj będzie zawsze oznacza, że $bjest większy niż $a. To może uratować cię 20ish postaci. Myślę też, że umieszczenie sortowania wewnątrz pętli u góry oznacza, że ​​musisz go tylko raz umieścić w kodzie, co pozwoli Ci zaoszczędzić kolejne 9.
Gareth,

Wow, chyba rozproszyło mnie polecenie „odejmij mniejszą liczbę od większej liczby”. Dzięki.
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";} Możesz zapisać 12 znaków, zmieniając forinstrukcję, wywołując ją jako funkcję i używając joinzamiast niej implode.
TwoScoopsofPig

Poza tym nienawidzę mini-markdown.
TwoScoopsofPig

2

CoffeeScript, 233 225 znaków

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

Wypróbuj tutaj lub z instrukcjami tutaj .


Moja przeglądarka zawiesza się - musiał anulować wykonanie skryptu.
lunohodov

Jaki numer podałeś? Próbowałem w Firefox i Chrome dla 4711 i 1 oraz kilku innych.
Jonas Elfström

Użycie 0(zgodnie z sugestią) lub kliknięcie przycisku Anuluj powoduje, że Safari zawiesza się.
lunohodov

Nie wiem, dlaczego to sugeruje. Musisz wprowadzić liczbę od 1 do 9998, której cyfry nie są identyczne. 0 jest takie samo jak 0000 i spowoduje nieskończoną pętlę. Wydaje się, że większość rozwiązań tutaj pominęła sprawdzanie poprawności danych wejściowych, aby zmniejszyć liczbę znaków.
Jonas Elfström

Zobacz i56.tinypic.com/bhhoqe.png Twój wynik również kończy się słowami: „Osiągnięcie 5 iteracji wymagało osiągnięcia stałej Kaprekara”. co nie spełnia wymagań.
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 znaki

To jest wersja GNU awk. Może nie działać z innymi wersjami nie-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

Otrzymuję awk: calling undefined function asort. Wersja Awk to 20070501 działająca na OSX 10.6.7. Nie zapomnij .o liczbie powtórzeń.
lunohodov

lunohodov @: Dodano brakujący punkt. Użyłem również gnu awk (gawk), co może wyjaśniać brakującą funkcję.
Dan Andreatta

Odejmowanie liczb jest 9992 - 2999 = 6993
odwrotne

2

Ruby, 179 znaków, ale i tak publikowanie

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 jest całkiem fajny
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";

To ~ 310 znaków ...
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];}

Przypadki testowe

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

Matematyka, 314 291 znaków

To jest program, 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]

Ustawianie ścieżki przed uruchomieniem: -

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

Uruchamianie programu: -

$ 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 bajtów

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

Wypróbuj online!

Kompletny program, wejście jest STDINuruchomione z php -nF.

Wydajność

> 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

Rdza - 375 bajtów

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

Przedstawiam to jako możliwą „górną granicę”, wzywam każdego do znalezienia języka, w którym rozsądna implementacja tego jest dłuższa - ponieważ w tym nie ma nic zbędnego, ale także nic nawet oczywistego, co by go znacznie zmniejszyło. Rdza polega na tym, że do odczytania ze standardowego wejścia i przetworzenia na liczbę całkowitą potrzeba około 120 znaków. „Och, ale potem użyj reprezentacji ciągu” ... ale jestem w 99% pewien, że byłoby to jeszcze dłuższe


0

Flaga Perl 6- n, 105 bajtów

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

Wypróbuj online!

W końcu muszę użyć mojej {}...*sztuczki, ponieważ musimy mieć co najmniej jedną iterację dla 6174. Nie jestem pewien, dlaczego potrzebuję dodatkowego owijania .&{ }wokół sekwencji, co jest trochę do bani.

Wyjaśnienie:

    .&{                         } # 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.