Код гольфу: 6174 - міфічна константа Капрекара


24

Чому число 6174 таке цікаве? Як визначено у Вікіпедії

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

Наведений вище процес, відомий як розпорядження Kaprekar, завжди буде досягати 6174 щонайбільше 7 ітерацій. Як тільки 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 як вхід. Дякуємо Пітеру Тейлору за повідомлення.


Це новина для мене. Хтось дзвонить модератору ...

Ага ... чи не існує кнопки "міграції"?
Доктор Ребму

Я позначив це, щоб модератор мігрував. Чи можу я запропонувати змінити правила вхідного виводу, щоб узгодити попередню тризначну версію? І посилання на більш ранню версію в тілі питання.
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"

EDIT: Тепер він відповідає 6174 випадку, ціною кількох символів ... запустіть echo -n <number> | perl kaprekar.pl

EDIT: Нарешті, назад, де я був раніше: D


10

Рубін 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. Ввели число і натиснули <Введення>, але вихід - це саме введене число. Ясна річ мені щось не вистачає ... Будь ласка, порадьте, як користуватися сценарієм.
lunohodov

@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

@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цитатами.
Кіт Рендалл

@ keith-randall: спасибі, зараз це знизилось до 141.
Мартін Удінг

6

Гольфскрипт, 74 символи

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

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 зараз.
Ротсор

Використовуючи захисні шаблони ( |k>0), можна позбутися f. Подальше перейменування gдо %змушує нас 182 символів.
Ротсор

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).
Мартін Удінг

Кредит має бути наданий кіт-рандаллу, який запропонував це для мого рішення Python.
Мартін Удінг

Можна зберегти ще 5 символів, замінивши while(n.length<4)на while(!n[3]).
DocMax

1
Я не можу перестати дивитися на цього! Далі a) виправляє результат, коли n = 6174, б) переставляє, коли n+'\n'додається, щоб уникнути умовного та додаткового \n, в) використовує темп, щоб уникнути послідовності приєднання-розділення приєднання, г) користується тим, що ми тільки коли-небудь доведеться додати єдиний '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+".")

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

Використовує функцію App від Scala 2.9.

Правка: дає правильний вихід для початкового введення 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";

Я не думаю , що вам потрібно abs, maxі minфункції, так як - то завжди буде означати , що $bбільше $a. Це може заощадити 20 символів. Крім того, я думаю, що введення сорту всередині циклу вгорі означатиме, що вам потрібно буде мати його у своєму коді лише один раз, що заощадить вам ще 9.
Гарет

Нічого собі, я думаю, мене відволікає інструкція "відняти меншу кількість від більшої кількості". Спасибі.
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";} Ви можете зберегти 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+'.')

Спробуйте тут або з інструкціями тут .


Мій браузер замерзає - довелося скасувати виконання сценарію.
lunohodov

Яке число ви ввели? Я спробував це у Firefox та Chrome для 4711 та 1 та ще декількох інших.
Йонас Ельфстрем

Використання 0(як пропонується у запиті) або натискання кнопки скасувати спричиняє замерзання Safari.
луноходов

Я не знаю, чому це запропонувало. Ви повинні ввести число від 1 до 9998, цифри якого не всі однакові. 0 такий же, як 0000, і призведе до нескінченного циклу. Здається, більшість рішень тут пропустили перевірку даних, щоб зменшити кількість символів.
Jonas Elfström

Див. 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))}

різн .:

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), і це може пояснити відсутність функції.
Dan Andreatta

Числа вирахування навиворіт: наприклад , має бути9992 - 2999 = 6993
Кріс Degnen

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
годин

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

1

Математика, 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.