高尔夫代码:6174-卡普雷卡的神话常数


24

为什么数字6174如此有趣?根据维基百科的定义

  1. 至少使用两个不同的数字,取任意四位数的数字。(允许前导零。)
  2. 按升序排列数字,然后按降序排列以获得两个四位数字,并在必要时添加前导零。
  3. 从较大的数字中减去较小的数字。
  4. 返回步骤2。

以上过程称为Kaprekar例程,最多7次迭代将始终达到6174。一旦达到6174,该过程将继续产生。

编写一个程序,对给定的四位数数字(请参见上面的定义)运行Kaprekar例程,以打印出例程的每个步骤。

规则:

  • 提交的内容必须是完整的程序。
  • 输入必须从标准输入中读取。从回显管道可以。
  • 输入应为数字形式。
  • 需要打印出前导零。(请参见下面的示例。)
  • 最后一行应说明需要进行多少次迭代。标点符号是必需的。

例子:

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

欢迎使用任何编程语言。深奥的加分+小赏金。

更新1:已经有一个类似的问题

更新2:添加了6174作为输入的示例。感谢Peter Taylor的通知。


对我来说这是新闻。有人称呼主持人...

呃...没有“迁移”按钮吗?
Rebmu博士2011年

我已将此标记为主持人进行迁移。我是否可以建议更改输入输出的规则以与早期的3位数版本一致?并链接到问题正文中的早期版本。
dmckee 2011年

@dmckee我不知道这个站点,也不知道已经有一个类似的问题(在stackoverflow上没有)。但是,我会犹豫更改规则以与3位数字版本一致,从而使两个问题更加相似。发布现有问题的重复内容或稍有变化是没有意义的。即使无意间完成。
lunohodov 2011年

3
请添加6174作为示例,以便我们可以看到如何格式化输出。
彼得·泰勒

Answers:


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"

编辑:现在符合6174的情况下,以几个字符为代价...用 echo -n <number> | perl kaprekar.pl

编辑:终于回到我之前的地方:D


10

Ruby 1.9,122个字符

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

调用示例:

$ echo 1211 | ruby -ln kaprekar.rb

我将-ln标记算作4个字符(正常调用ruby kaprekar.rb和之间的差异ruby -ln kaprekar.rb)。


我将此脚本另存为kaprekar.rb,然后使用调用了该脚本ruby -lp kaprekar.rb。输入一个数字并按<Enter>键,但输出是输入的数字本身。显然我遗漏了一些东西...请告知如何使用脚本。
lunohodov

@lunohodov:我添加了一个示例调用。现在,它也可以生成正确的输出6174作为输入,不幸的是,此解决方案最多可将128个字符输入。
Ventero 2011年

使用echo 1234 | ruby kaprekar.rb会发出警告,并以错误结尾undefined method 'chars' for nil:NilClass (NoMethodError)。执行echo 1234 | ruby -lp kaprekar.rb仅发出警告,并且行为符合预期。输出不符合预期,因为它包含警告消息kaprekar.rb:3: warning: regex literal in condition
lunohodov 2011年

@lunohodov:修复了警告和示例调用。
Ventero 2011年

7

Python,141个字符

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使用%04d进行平滑填充。我今天学到了一些东西!
arrdem 2011年

3
一些建议:使用;s 将整个循环放在一行上。while n-6174print与报价之间没有空格。
基思·兰德尔

@ keith-randall:谢谢,现在降至141。
马丁·乌丁2011年

6

Golfscript,74个字符

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

5

哈斯克尔, 197 192 182 181个字符

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)

内联rs保存2个字符。另外,“ 000”是多余的。“ 0”就足够了。这使我们达到188个字符。我很惊讶interact在这里没有帮助。通常会这样。
Rotsor 2011年

替换show x++sshows x s可获得另外2个字节。现在186。
Rotsor 2011年

通过使用模式保护器(|k>0)可以摆脱f。进一步重命名g%182个字符。
Rotsor 2011年

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;

高尔夫的竞争者并不多,但是写起来很有趣。:)

使用./fish.py kaprekar.fish -v <number>
EDIT 运行:现在接受来自STDIN的输入。


4

JavaScript, 189 182 165个字符

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

原版的:

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

取消高尔夫:

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
我认为您可以更改n != 6174为,n-6174因为它将返回零,这是错误的(至少在C和Python中)。
Martin Ueding 2011年

应该归功于keith-randall,他为我的Python解决方案提出了建议。
Martin Ueding 2011年

您可以将替换为while(n.length<4),再保存5个字符while(!n[3])
DocMax 2011年

1
我不能停止盯着这个!下面的a)在n = 6174时修复输出,b)在n+'\n'添加时避免重新排列以避免条件和额外\n,c)使用临时以避免join-split-join序列,d)利用了以下事实:只需添加单个“ 0”进行填充: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+'.')应为172个字符。
DocMax 2011年

1
令人印象深刻!但是根据上面的规范,当n = 6174时,它必须经过至少一次迭代,因此我添加了一个检查是否i为0(+4),但将其与结合在一起i++。不幸的是,这只会产生一个错误,因此我将增量更改为减量,然后在末尾(-1)使用一点按位欺骗。然后,我更改i=0,o=e=''i=o=e=''(-2),重新格式化for循环以避免使用多余的括号(-1),扩展了(b=...,a=...,b)位(-2),然后潜入a=b.joinreverse()调用(-1)。所以169,还不错!
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."

通过问题的所有测试用例。


2

JavaScript,260个字节

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个字符

(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个字符

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

利用了Scala 2.9中的App特性。

编辑:为6174的初始输入提供正确的输出。


2

PHP 215 259 276 人物

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

取消高尔夫:

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

我不认为你需要的absmaxmin功能,因为那种总是意味着$b大于$a。这样可以节省20个字符。另外,我认为将排序放在循环的顶部将意味着您只需要在代码中进行一次排序即可,这将为您节省另外9个
。– Gareth

哇,我猜想我对“从大数中减去小数”的指令分散了注意力。谢谢。
rintaun 2011年

<?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";} 您可以通过更改for语句,将其作为函数调用并使用join代替来保存12个字符implode
TwoScoopsofPig 2012年

另外,我讨厌迷你降价。
TwoScoopsofPig 2012年

2

CoffeeScript,233225个字符

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

试试在这里或说明这里


我的浏览器死机了-必须取消脚本的执行。
lunohodov

您输入了什么号码?我在Firefox和Chrome中尝试了4711和1以及其他几个版本。
乔纳斯·艾夫斯特伦2011年

使用0(如提示所建议)或单击“取消”按钮会使Safari冻结。
lunohodov 2011年

我不知道为什么会这样建议。您必须输入一个介于1到9998之间的数字,其数字并不完全相同。0与0000相同,将导致无限循环。似乎这里的大多数解决方案都跳过了验证输入,以减少字符数。
乔纳斯·艾夫斯特伦2011年

请参阅i56.tinypic.com/bhhoqe.png您的输出也以“花了5次迭代才能达到Kaprekar的常数”结束。这不符合要求。
lunohodov 2011年

2

斯卡拉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))}

斯卡拉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))}

差异:

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

2

GAWK-152个字符

这是GNU awk版本。它可能不适用于其他非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

我收到了awk: calling undefined function asort。Awk版本是在OSX 10.6.7上运行的20070501。不要忘记.迭代次数之后的情况。
lunohodov 2011年

lunohodov @:添加了缺失点。另外,我使用了gnu awk(gawk),这也许可以解释缺少的功能。
丹·安德雷塔

减法数字是南辕北辙:如要9992 - 2999 = 6993
克里斯Degnen

2

Ruby,179个字符,但仍然发布

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

红宝石非常酷
明亮的

1

佩尔

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

那就是约310个字符...
Aman ZeeK Verma 2011年

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

测试用例

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个字符

这是程序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]

在运行之前设置路径:

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

运行程序:

$ 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字节

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

在线尝试!

完整的程序,输入是STDIN,用运行php -nF

输出量

> 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

锈-375字节

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

我将其作为可能的“上限”提出,我向任何人发起挑战,要找到一种语言,在这种语言中,合理的实现时间会更长-因为其中没有多余的东西,但也没有任何明显的东西可以显着缩小它。关于Rust的事情是,仅从stdin读取并解析为整数,大约需要120个字符。“哦,但那就用字符串表示法吧” ...但是我99%的人相信那会更长


0

Perl 6 -n标志,105个字节

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

在线尝试!

我终于要用我的{}...*把戏了,因为我们至少需要为6174进行一次迭代。但是我不确定为什么我需要.&{ }在序列周围进行额外的包装,这有点糟。

说明:

    .&{                         } # 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.