Code Golf: 6174 - Hằng số huyền thoại của Kaprekar


24

Tại sao số 6174 lại thú vị như vậy? Theo định nghĩa của Wikipedia

  1. Lấy bất kỳ số có bốn chữ số, sử dụng ít nhất hai chữ số khác nhau. (Các số 0 đứng đầu được phép.)
  2. Sắp xếp các chữ số tăng dần và sau đó theo thứ tự giảm dần để có hai số có bốn chữ số, thêm các số 0 đứng đầu nếu cần.
  3. Trừ số nhỏ hơn từ số lớn hơn.
  4. Quay trở lại bước 2.

Quá trình trên, được gọi là thói quen của Kaprekar, sẽ luôn đạt 6174 trong tối đa 7 lần lặp. Sau khi đạt được 6174, quy trình sẽ tiếp tục mang lại kết quả.

Viết chương trình chạy thói quen của Kaprekar theo số có bốn chữ số nhất định (xem định nghĩa ở trên) in ra từng bước của thói quen.

Quy tắc:

  • Đệ trình phải là chương trình hoàn chỉnh.
  • Đầu vào phải được đọc từ đầu vào tiêu chuẩn. Đường ống từ tiếng vang là OK.
  • Đầu vào phải ở dạng số.
  • In ra các số không hàng đầu là bắt buộc. (Xem ví dụ bên dưới.)
  • Dòng cuối cùng sẽ cho biết có bao nhiêu lần lặp lại là cần thiết. Dấu câu là bắt buộc.

Ví dụ:

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

Bất kỳ ngôn ngữ lập trình đều được chào đón. Thêm điểm cho những người bí truyền + một tiền thưởng nhỏ.

Cập nhật 1 : Đã có một câu hỏi tương tự .

Cập nhật 2 : Đã thêm ví dụ cho 6174 làm đầu vào. Cảm ơn Peter Taylor đã thông báo.


Đây là tin tức cho tôi. Ai đó gọi người điều hành ...

Uh ... không có nút "di chuyển" à?
Bác sĩ Rebmu

Tôi đã gắn cờ này để người điều hành di chuyển. Tôi có thể đề nghị thay đổi các quy tắc về đầu ra đầu vào để đồng ý với phiên bản 3 chữ số trước đó không? Và liên kết với phiên bản trước trong phần thân của câu hỏi.
dmckee

@dmckee Tôi không biết về trang web này và không thể biết rằng đã có một câu hỏi tương tự (trên stackoverflow không có câu hỏi nào). Tuy nhiên, tôi sẽ ngần ngại thay đổi các quy tắc để đồng ý với phiên bản 3 chữ số và do đó làm cho hai câu hỏi thậm chí giống nhau hơn. Việc đăng một bản sao hoặc một biến thể nhỏ của một câu hỏi hiện tại là vô nghĩa. Ngay cả khi thực hiện ngoài ý muốn.
lunohodov

3
Vui lòng thêm 6174 làm ví dụ để chúng tôi có thể thấy đầu ra sẽ được định dạng như thế nào.
Peter Taylor

Câu trả lời:


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: Bây giờ tuân thủ trường hợp 6174, với chi phí của một vài ký tự ... chạy với echo -n <number> | perl kaprekar.pl

EDIT: Cuối cùng trở lại nơi tôi đã ở trước đây: D


10

Ruby 1.9, 122 ký tự

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

Ví dụ gọi:

$ echo 1211 | ruby -ln kaprekar.rb

Tôi đã đếm -lncờ là 4 ký tự (sự khác biệt giữa cách gọi thông thường ruby kaprekar.rbruby -ln kaprekar.rb).


Tôi đã lưu tập lệnh này với tên kaprekar.rb sau đó gọi nó bằng ruby -lp kaprekar.rb. Đã nhập một số và nhấn <Enter> nhưng đầu ra là chính số đã nhập. Rõ ràng tôi đang thiếu một cái gì đó ... Xin tư vấn cách sử dụng tập lệnh.
lunohodov

@lunohodov: Tôi đã thêm một lời mời ví dụ. Bây giờ nó cũng tạo ra đầu ra chính xác cho 6174đầu vào, không may mang lại giải pháp này lên tới 128 ký tự.
Ventero

Sử dụng echo 1234 | ruby kaprekar.rbtăng cảnh báo và kết thúc với một lỗi undefined method 'chars' for nil:NilClass (NoMethodError). Thực hiện echo 1234 | ruby -lp kaprekar.rbcác vấn đề chỉ là một cảnh báo và hành xử như mong đợi. Đầu ra không như mong đợi, vì nó chứa thông điệp cảnh báokaprekar.rb:3: warning: regex literal in condition
lunohodov

@lunohodov: Đã sửa lỗi cảnh báo và lời gọi ví dụ.
Ventero

7

Python, 141 ký tự

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 cho phần đệm trơn với% 04d. Tôi đã học được một cái gì đó ngày hôm nay!
arrdem

3
Một vài gợi ý: đặt toàn bộ vòng lặp trên một dòng bằng ;s. while n-6174. Không có không gian giữa printvà trích dẫn.
Keith Randall

@ keith-randall: cảm ơn, đã giảm xuống còn 141 bây giờ.
Martin Uting

6

Golf, 74 ký tự

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

5

Haskell, 197 192 182 181 ký tự

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)

Nội tuyến rslưu 2 ký tự. Ngoài ra, "000" là dư thừa. "0" là đủ. Điều này mang lại cho chúng tôi tới 188 ký tự. Tôi ngạc nhiên interactkhông giúp được gì ở đây. Nó thường làm.
Rotsor

Thay thế show x++sbằng shows x stăng thêm 2 byte. 186 bây giờ.
Rotsor

Bằng cách sử dụng các mẫu bảo vệ ( |k>0) người ta có thể thoát khỏi f. Đổi tên thêm gđể đưa %chúng tôi đến 182 ký tự.
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;

Không có nhiều ứng cử viên cho golf, nhưng thật vui khi viết. :)

Chạy với./fish.py kaprekar.fish -v <number>
EDIT: Bây giờ lấy đầu vào từ STDIN.


4

JavaScript, 189 182 165 ký tự

Tín dụng cho 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+'.')

Nguyên:

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

Ung dung:

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
Tôi nghĩ rằng bạn có thể thay đổi n != 6174thành n-6174vì nó sẽ trả về 0, đó là sai (ít nhất là trong C và Python).
Martin Uting

Tín dụng nên được gửi tới keith-randall, người đã đề xuất nó cho giải pháp Python của tôi.
Martin Uting

Bạn có thể lưu thêm 5 ký tự bằng cách thay thế while(n.length<4)bằng while(!n[3]).
DocMax

1
Tôi không thể ngừng nhìn chằm chằm vào cái này! Sau đây a) sửa lỗi đầu ra khi n = 6174, b) sắp xếp lại khi n+'\n'được thêm vào để tránh điều kiện và thêm \n, c) sử dụng temp để tránh trình tự nối-tách-nối, d) lợi dụng thực tế là chúng ta chỉ bao giờ phải thêm một '0' cho phần đệm: 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+'.')phải là 172 ký tự.
DocMax

1
Ấn tượng! Theo thông số kỹ thuật ở trên, khi n = 6174, nó phải trải qua ít nhất một lần lặp, vì vậy tôi đã thêm một kiểm tra nếu ilà 0 (+4) nhưng kết hợp nó với i++. Thật không may, điều đó gây ra một lỗi, vì vậy tôi đã chuyển mức tăng sang giảm dần và sau đó sử dụng một chút mẹo nhỏ ở cuối (-1). Sau đó, tôi đổi i=0,o=e=''thành i=o=e=''(-2), định dạng lại forvòng lặp để tránh dấu ngoặc đơn (-1), (b=...,a=...,b)bit mở rộng (-2) và lẻn a=b.joinvào trong reverse()cuộc gọi (-1). Vậy 169, không tệ!
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."

Vượt qua tất cả các trường hợp kiểm tra từ câu hỏi.


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 ký tự

(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 ký tự

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

Làm cho việc sử dụng đặc điểm ứng dụng từ Scala 2.9.

Chỉnh sửa: cung cấp đầu ra chính xác cho đầu vào ban đầu là 6174.


2

PHP, 215 259 276 nhân vật

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

Ung dung:

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

Tôi không nghĩ rằng bạn cần abs, maxvà các minchức năng, vì sắp xếp sẽ luôn có nghĩa $blà lớn hơn $a. Điều đó có thể giúp bạn tiết kiệm 20 ký tự. Ngoài ra, tôi nghĩ rằng việc sắp xếp bên trong vòng lặp ở trên cùng sẽ có nghĩa là bạn chỉ cần có nó trong mã của mình một lần sẽ giúp bạn tiết kiệm thêm 9.
Gareth

Ồ, tôi đoán rằng tôi đã bị phân tâm bởi hướng dẫn "trừ số nhỏ hơn từ số lớn hơn". Cảm ơn.
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";} Bạn có thể lưu 12 ký tự bằng cách thay đổi forcâu lệnh của mình , gọi đây là hàm và sử dụng jointhay vì implode.
TwoScoopsofPig

Ngoài ra, tôi ghét đánh dấu nhỏ.
TwoScoopsofPig

2

CoffeeScript, 233 225 ký tự

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

Hãy thử nó ở đây hoặc với hướng dẫn ở đây .


Trình duyệt của tôi đóng băng - đã phải hủy việc thực thi tập lệnh.
lunohodov

Bạn đã nhập số nào? Tôi đã thử nó trong Firefox và Chrome cho 4711 và 1 và một vài người khác.
Jonas Elfström

Việc sử dụng 0(như được gợi ý bởi lời nhắc) hoặc nhấp vào nút hủy khiến Safari bị đóng băng.
lunohodov

Tôi không biết tại sao nó lại gợi ý như vậy. Bạn phải nhập một số từ 1 đến 9998 có chữ số không giống nhau. 0 giống như 0000 và sẽ gây ra một vòng lặp vô hạn. Có vẻ như hầu hết các giải pháp ở đây đã bỏ qua việc xác thực đầu vào để giảm số lượng ký tự.
Jonas Elfström

Xem i56.tinypic.com/bhhoqe.png Đầu ra của bạn cũng kết thúc bằng "Phải mất 5 lần lặp để đạt được hằng số của Kaprekar." mà không phù hợp với yêu cầu.
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))}

khác biệt

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

2

GAWK - 152 ký tự

Đây là phiên bản GNU awk. Nó có thể không hoạt động với các phiên bản không phải là gnu khác.

{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

Tôi nhận được awk: calling undefined function asort. Phiên bản Awk là 20070501 chạy trên OSX 10.6.7. Đừng quên .sau số lần lặp.
lunohodov

lunohodov @: Đã thêm điểm thiếu. Ngoài ra, tôi đã sử dụng gnu awk (gawk), và điều đó có thể giải thích chức năng bị thiếu.
Dan Andreatta

Các số trừ là vòng sai: ví dụ: nên9992 - 2999 = 6993
Chris Degnen

2

Ruby, 179 ký tự nhưng dù sao cũng đăng

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 khá tuyệt
don sáng

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

Đó là ~ 310 ký tự ...
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];}

Các trường hợp thử nghiệm

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

Toán học, 314 291 ký tự

Đây là chương trình, 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]

Đặt đường dẫn trước khi chạy: -

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

Chạy chương trình: -

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

Hãy thử trực tuyến!

Hoàn thành chương trình, đầu vào là STDIN, chạy với php -nF.

Đầu ra

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

Tôi trình bày điều này như một "giới hạn trên" có thể, tôi thách thức bất kỳ ai tìm một ngôn ngữ mà việc thực hiện hợp lý này lâu hơn - vì trong đó không có gì là thừa, nhưng cũng không có gì rõ ràng từ xa sẽ thu nhỏ nó đáng kể. Điều về Rust là phải mất khoảng 120 ký tự chỉ để đọc từ stdin và phân tích thành một số nguyên. "Ồ nhưng sau đó chỉ cần sử dụng biểu diễn chuỗi" ... nhưng tôi tự tin 99% rằng sẽ còn lâu hơn nữa


0

Cờ Perl 6 -n, 105 byte

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

Hãy thử trực tuyến!

Cuối cùng tôi đã sử dụng {}...*mánh khóe của mình, vì chúng tôi cần phải có ít nhất một lần lặp cho 6174. Tôi không chắc tại sao tôi lại cần thêm gói .&{ }xung quanh chuỗi, mặc dù điều đó thật tệ.

Giải trình:

    .&{                         } # 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.