Код Гольф: 6174 - мифическая константа Капрекара

24

Почему номер 6174 такой интересный? Как определено в Википедии

  1. Возьмите любое четырехзначное число, используя как минимум две разные цифры. (Допускаются ведущие нули.)
  2. Расположите цифры по возрастанию, а затем по убыванию, чтобы получить два четырехзначных числа, при необходимости добавляя начальные нули.
  3. Вычтите меньшее число из большего числа.
  4. Вернитесь к шагу 2.

Вышеупомянутый процесс, известный как рутина Капрекара, всегда будет достигать 6174 не более чем за 7 итераций. Как только 6174 достигнут, процесс продолжит давать его.

Напишите программу, которая запускает процедуру Капрекара с заданным четырехзначным числом (см. Определение выше), распечатывая каждый шаг этой процедуры.

Правила:

  • Материалы должны быть законченными программами.
  • Ввод должен быть прочитан из стандартного ввода. Трубопровод от эха в порядке.
  • Ввод должен быть в числовой форме.
  • Требуется распечатать ведущие нули. (См. Примеры ниже.)
  • В последней строке должно быть указано, сколько итераций понадобилось. Пунктуация обязательна.

Примеры:

> 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 в качестве входных данных. Спасибо Питеру Тейлору за уведомление.

lunohodov
источник
Это новость для меня. Кто-то называет модератором ...
Э-э ... разве нет кнопки "мигрировать"?
Доктор Ребму
Я пометил это для модератора для миграции. Могу ли я предложить изменить правила ввода-вывода для согласования с более ранней трехзначной версией? И ссылка на более раннюю версию в теле вопроса.
dmckee
@dmckee Я не знал об этом сайте и не мог знать, что уже есть подобный вопрос (на stackoverflow его не было). Однако я бы не стал менять правила, чтобы согласиться с трехзначной версией, и, таким образом, сделать эти два вопроса еще более похожими. Бессмысленно публиковать дубликат или небольшое изменение существующего вопроса. Даже когда сделано непреднамеренно.
луноходов
3
Пожалуйста, добавьте 6174 в качестве примера, чтобы мы могли видеть, как форматировать вывод.
Питер Тейлор

Ответы:

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

swilliams
источник
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).

Ventero
источник
Я сохранил этот скрипт как kaprekar.rb, а затем вызвал его ruby -lp kaprekar.rb. Ввели номер и нажали <Enter>, но выводом является сам введенный номер. Я явно что-то упускаю ... Посоветуйте, пожалуйста, как использовать скрипт.
луноходов
@lunohodov: я добавил пример вызова. Теперь он также генерирует правильный вывод для 6174ввода, что, к сожалению, позволяет использовать это решение до 128 символов.
Вентеро
Использование 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: исправлено предупреждение и вызов примера.
Вентеро
7

Питон, 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
3
Несколько предложений: поместите весь цикл в одну строку, используя ;s. while n-6174, Между пробелом printи цитатой нет места .
Кит Рэндалл
@ Кит-Рэндалл: спасибо, теперь получил 141.
Мартин Юдинг
6

Golfscript, 74 символа

);:|;{0):0;|$:§-1%" - "§" = ""0"4$~§~-+-4>:|n|6174`=!}do"Iterations: "0"."
Ventero
источник
5

Haskell, 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)
Хаммар
источник
Встраивает rи sсохраняет 2 символа. Кроме того, «000» является избыточным. «0» достаточно. Это подводит нас к 188 персонажам. Я удивлен interact, не помогает здесь. Обычно это так.
Роцор
Замена show x++sс shows x sусилением еще 2 байта. 186 сейчас.
Роцор
Используя pattern guard ( |k>0) можно избавиться от f. Дальнейшее переименованиеg до %заставляет нас 182 символов.
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;

Не много претендента на гольф, но было весело писать. :)

Run with./fish.py kaprekar.fish -v <number>
EDIT: теперь принимает данные из STDIN.

swilliams
источник
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+'.')

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
Я думаю, что вы можете изменить n != 6174на, n-6174так как он вернет ноль, что ложно (по крайней мере, в C и Python).
Мартин Уединг,
Автор должен отдать должное keith-randall, который предложил его для моего решения на Python.
Мартин Уединг
Вы можете сохранить еще 5 символов, заменив while(n.length<4)на while(!n[3]).
DocMax
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
1
Впечатляет! Однако, согласно приведенной выше спецификации, когда n = 6174, он должен пройти хотя бы одну итерацию, поэтому я добавил проверку, если iравно 0 (+4), но в сочетании с проверкой i++. К сожалению, это приводит к отключению на одну ошибку, поэтому я переключил приращение на уменьшение, а затем использовал немного побитовый трюк в конце (-1). Затем я изменил i=0,o=e=''на i=o=e=''(-2), переформатировал forцикл, чтобы избежать лишних скобок (-1), расширенного (b=...,a=...,b)бита (-2) и пробрался a=b.joinвнутрь reverse()вызова (-1). Итак, 169, неплохо!
Кейси Чу
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+".")
pimvdb
источник
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)))))))
kotarak
источник
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+".")}

Использует черту App из Scala 2.9.

Редактировать: дает правильный вывод для начального ввода 6174.

Gareth
источник
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";

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";
rintaun
источник
Я не думаю, что вам нужны функции abs, maxи min, так как сортировка всегда будет означать, что $bбольше, чем $a. Это может спасти вас 20-ти символов. Кроме того, я думаю, что размещение сортировки внутри цикла в верхней части будет означать, что вам нужно иметь его в своем коде только один раз, что сэкономит вам еще 9.
Гарет
Ух ты, наверное, меня отвлекла инструкция «вычесть меньшее число из большего числа». Спасибо.
Ринтаун
<?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";} Вы можете сохранить 12 символов, изменив свой forоператор, вызвав его как функцию и используя joinвместо implode.
TwoScoopsofPig
Также я ненавижу мини-уценку.
TwoScoopsofPig
2

CoffeeScript, 233 225 символов

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

Попробуйте здесь или с инструкциями здесь .

Йонас Эльфстрём
источник
Мой браузер зависает - пришлось отменить выполнение скрипта.
луноходов
Какой номер вы ввели? Я пробовал это в Firefox и Chrome для 4711 и 1 и нескольких других.
Йонас Эльфстрём
Использование 0(в соответствии с подсказкой) или нажатие кнопки отмены приводит к зависанию Safari.
луноходов
Я не знаю, почему это предположило. Вы должны ввести число от 1 до 9998, цифры которого не являются идентичными. 0 соответствует 0000 и вызовет бесконечный цикл. Кажется, что большинство решений здесь пропустили проверку ввода, чтобы уменьшить количество символов.
Йонас Эльфстрем
См. I56.tinypic.com/bhhoqe.png Ваш вывод также заканчивается словами «Потребовалось 5 итераций, чтобы достичь константы Капрекара». который не соответствует требованиям.
луноходов
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 символа

Это версия 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 20070501 работает на OSX 10.6.7. Не забывайте .после количества итераций.
луноходов
lunohodov @: добавлена ​​пропущенная точка. Кроме того, я использовал gnu awk (gawk), и это может объяснить отсутствующую функцию.
Дэн Андреатта
Числа вычитания неправильные: например, должно быть9992 - 2999 = 6993
Крис Дегнен
2

Рубин, 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

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";
Аман ЗееК Верма
источник
Это ~ 310 символов ...
Aman ZeeK Verma
1

К, 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
tmartin
источник
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.
640 КБ
источник
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 заключается в том, что для считывания из стандартного ввода и анализа целого числа требуется около 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
Джо Кинг
источник