http://xkcd.com/710/ からインスピレーションを受けましたここにコードゴルフがあります。
チャレンジ
0より大きい正の整数を指定して、その数のひょうのシーケンスを出力します。
ひょうのシーケンス
詳細は Wikipedia を参照してください。
1に達するまで、生成された数でこれを繰り返します(1の後に続く場合は、1 -> 4 -> 2 -> 1...
の無限ループに入ります)。
時々コードは説明するのに最良の方法なので、ここにウィキペディアからのいくつかがあります
function collatz(n)
show n
if n > 1
if n is odd
call collatz(3n + 1)
else
call collatz(n / 2)
このコードは機能しますが、もう1つ問題があります。 プログラムはスタックオーバーフローに対して脆弱であってはなりません。したがって、反復または末尾再帰を使用する必要があります。
また、大きな数値を計算でき、言語にまだ実装されていない場合のボーナスポイントもあります。 (または、固定長整数を使用して大きな数のサポートを再実装する場合)
テストケース
Number: 21
Results: 21 -> 64 -> 32 -> 16 -> 8 -> 4 -> 2 -> 1
Number: 3
Results: 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
また、コードGolfには完全なユーザー入力と出力が含まれている必要があります。
;
; To assemble and link this program, just run:
;
; >> $ nasm -f elf collatz.asm && gcc -o collatz collatz.o
;
; You can then enjoy its output by passing a number to it on the command line:
;
; >> $ ./collatz 123
; >> 123 --> 370 --> 185 --> 556 --> 278 --> 139 --> 418 --> 209 --> 628 --> 314
; >> --> 157 --> 472 --> 236 --> 118 --> 59 --> 178 --> 89 --> 268 --> 134 --> 67
; >> --> 202 --> 101 --> 304 --> 152 --> 76 --> 38 --> 19 --> 58 --> 29 --> 88
; >> --> 44 --> 22 --> 11 --> 34 --> 17 --> 52 --> 26 --> 13 --> 40 --> 20 --> 10
; >> --> 5 --> 16 --> 8 --> 4 --> 2 --> 1
;
; There's even some error checking involved:
; >> $ ./collatz
; >> Usage: ./collatz NUMBER
;
section .text
global main
extern printf
extern atoi
main:
cmp dword [esp+0x04], 2
jne .usage
mov ebx, [esp+0x08]
Push dword [ebx+0x04]
call atoi
add esp, 4
cmp eax, 0
je .usage
mov ebx, eax
Push eax
Push msg
.loop:
mov [esp+0x04], ebx
call printf
test ebx, 0x01
jz .even
.odd:
lea ebx, [1+ebx*2+ebx]
jmp .loop
.even:
shr ebx, 1
cmp ebx, 1
jne .loop
Push ebx
Push end
call printf
add esp, 16
xor eax, eax
ret
.usage:
mov ebx, [esp+0x08]
Push dword [ebx+0x00]
Push usage
call printf
add esp, 8
mov eax, 1
ret
msg db "%d --> ", 0
end db "%d", 10, 0
usage db "Usage: %s NUMBER", 10, 0
&>:.:1-|
>3*^ @
|%2: <
v>2/>+
LOLCODE:406 CHARACTERS
HAI
BTW COLLATZ SOUNDZ JUS LULZ
CAN HAS STDIO?
I HAS A NUMBAR
BTW, I WANTS UR NUMBAR
GIMMEH NUMBAR
VISIBLE NUMBAR
IM IN YR SEQUENZ
MOD OF NUMBAR AN 2
BOTH SAEM IT AN 0, O RLY?
YA RLY, NUMBAR R QUOSHUNT OF NUMBAR AN 2
NO WAI, NUMBAR R SUM OF PRODUKT OF NUMBAR AN 3 AN 1
OIC
VISIBLE NUMBAR
DIFFRINT 2 AN SMALLR OF 2 AN NUMBAR, O RLY?
YA RLY, GTFO
OIC
IM OUTTA YR SEQUENZ
KTHXBYE
JUSTIN J. MEZA'S INTERPRETER の下でテストされました。 KTHXBYE!
明らかに、スタックオーバーフローは発生しません。
n=input()
while n>1:n=(n/2,n*3+1)[n%2];print n
_c 1=[1]
c n=n:c(div(n`mod`2*(5*n+2)+n)2)
main=readLn>>=print.c
_
ユーザー入力、印刷出力、定数メモリとスタックを使用し、任意の大きな整数で動作します。
サンプルラン 入力としてすべての「1」(!)の80桁の数字が与えられた場合、このコードはとても楽しいです。
オリジナル、機能のみのバージョン:
Haskell 51文字
_f n=n:[[],f([n`div`2,3*n+1]!!(n`mod`2))]!!(1`mod`n)
_
とにかく、@&^#に条件文が必要なのは誰ですか?
(編集:私は「賢く」なっていて、修正を使用しました。それがないと、コードは54文字に落ちました。edit2:f()
を除外することにより、51に落ちました)
私は少し反競争的であることに決め、Perlでそのような問題を通常どのようにコーディングするかを示します。
最後に46(合計)文字のコードゴルフエントリもあります。
これらの最初の3つの例はすべて、このヘッダーから始まります。
#! /usr/bin/env Perl
use Modern::Perl;
# which is the same as these three lines:
# use 5.10.0;
# use strict;
# use warnings;
while( <> ){
chomp;
last unless $_;
Collatz( $_ );
}
単純な再帰バージョン
use Sub::Call::Recur;
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
say $n;
given( $n ){
when( 1 ){}
when( $_ % 2 != 0 ){ # odd
recur( 3 * $n + 1 );
}
default{ # even
recur( $n / 2 );
}
}
}
単純な反復バージョン
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
say $n;
while( $n > 1 ){
if( $n % 2 ){ # odd
$n = 3 * $n + 1;
} else { #even
$n = $n / 2;
}
say $n;
}
}
最適化された反復バージョン
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
#
state @next;
$next[1] //= 0; # sets $next[1] to 0 if it is undefined
#
# fill out @next until we get to a value we've already worked on
until( defined $next[$n] ){
say $n;
#
if( $n % 2 ){ # odd
$next[$n] = 3 * $n + 1;
} else { # even
$next[$n] = $n / 2;
}
#
$n = $next[$n];
}
say $n;
# finish running until we get to 1
say $n while $n = $next[$n];
}
次に、v5.10.0より前のバージョンのPerlで最後の例をどのように実行するかを示します
#! /usr/bin/env Perl
use strict;
use warnings;
while( <> ){
chomp;
last unless $_;
Collatz( $_ );
}
{
my @next = (0,0); # essentially the same as a state variable
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
# fill out @next until we get to a value we've already worked on
until( $n == 1 or defined $next[$n] ){
print $n, "\n";
if( $n % 2 ){ # odd
$next[$n] = 3 * $n + 1;
} else { # even
$next[$n] = $n / 2;
}
$n = $next[$n];
}
print $n, "\n";
# finish running until we get to 1
print $n, "\n" while $n = $next[$n];
}
}
まず、IOは常に遅い部分です。ですので、実際にそれらをそのままベンチマークした場合、それぞれの速度はほぼ同じになるはずです。
次に、これらをテストするために、/dev/null
($null
)へのファイルハンドルを開き、say $n
をすべて編集して、代わりにsay {$null} $n
を読み取りました。これは、IOへの依存を減らすためです。
#! /usr/bin/env Perl
use Modern::Perl;
use autodie;
open our $null, '>', '/dev/null';
use Benchmark qw':all';
cmpthese( -10,
{
Recursive => sub{ Collatz_r( 31 ) },
Iterative => sub{ Collatz_i( 31 ) },
Optimized => sub{ Collatz_o( 31 ) },
});
sub Collatz_r{
...
say {$null} $n;
...
}
sub Collatz_i{
...
say {$null} $n;
...
}
sub Collatz_o{
...
say {$null} $n;
...
}
10回実行した後の代表的なサンプル出力は次のとおりです。
レート再帰反復最適化 再帰1715 /秒--27%-46% 反復2336 /秒36%--27% 最適化3187/s 86%36%-
最後に、実際のコードゴルフエントリー:
Perl -nlE'say;say$_=$_%2?3*$_+1:$_/2while$_>1'
合計46文字
開始値を印刷する必要がない場合は、さらに5文字削除できます。
Perl -nE'say$_=$_%2?3*$_+1:$_/2while$_>1'
合計41文字
実際のコード部分は31文字ですが、-n
スイッチがないとコードは機能しません。したがって、例全体をカウントに含めます。
~{(}{3*).1&5*)/}/1+`
#
# Usage: echo 21 | Ruby golfscript.rb collatz.gs
これは
stack<int> s;
s.Push(21);
while (s.top() - 1) {
int x = s.top();
int numerator = x*3+1;
int denominator = (numerator&1) * 5 + 1;
s.Push(numerator/denominator);
}
s.Push(1);
return s;
この種の問題は bc
が発明されたものだと思います:
for(n=read();n>1;){if(n%2)n=n*6+2;n/=2;n}
テスト:
bc1 -q collatz.bc
21
64
32
16
8
4
2
1
適切なコード:
for(n=read();n>1;){if(n%2)n=n*3+1else n/=2;print n,"\n"}
bc
は、以下の数値を処理しますINT_MAX
桁
編集:Wikipediaの記事 は、この推測が20x2までのすべての値についてチェックされていると述べています58(約5.76e18)。このプログラム:
c=0;for(n=2^20000+1;n>1;){if(n%2)n=n*6+2;n/=2;c+=1};n;c
テスト220,000+1(約3.98e6,020)in68秒、 144,404サイクル。
Perl -nE 'say$_=$_%2?$_*3+1:$_/2while$_>1'
# 123456789 123456789 123456789 1234567
2つの不要なスペースを削除するように編集されました。
1つの不要なスペースを削除するように編集されました。
MS Excel、35文字
=IF(A1/2=ROUND(A1/2,0),A1/2,A1*3+1)
Wikipedia から直接引用:
In cell A1, place the starting number.
In cell A2 enter this formula =IF(A1/2=ROUND(A1/2,0),A1/2,A1*3+1)
Drag and copy the formula down until 4, 2, 1
開始番号1000の結果を取得するには、式を111回コピー/貼り付けるだけでした。;)
main(x){for(scanf("%d",&x);x>=printf("%d,",x);x=x&1?3*x+1:x/2);}
#include <stdlib.h>
#define B (w>=m?d=realloc(d,m=m+m):0)
#define S(a,b)t=a,a=b,b=t
main(m,w,i,t){char*d=malloc(m=9);for(w=0;(i=getchar()+2)/10==5;)
B,d[w++]=i%10;for(i=0;i<w/2;i++)S(d[i],d[w-i-1]);for(;;w++){
while(w&&!d[w-1])w--;for(i=w+1;i--;)putchar(i?d[i-1]+48:10);if(
w==1&&*d==1)break;if(*d&1){for(i=w;i--;)d[i]*=3;*d+=1;}else{
for(i=w;i-->1;)d[i-1]+=d[i]%2*10,d[i]/=2;*d/=2;}B,d[w]=0;for(i=0
;i<w;i++)d[i+1]+=d[i]/10,d[i]%=10;}}
注:削除しないでください#include <stdlib.h>
少なくともプロトタイピングmalloc/reallocなしでは、64ビットプラットフォームでは安全ではありません(64ビットvoid *は32ビットintに変換されます)。
これはまだ精力的にテストされていません。短縮も使用できます。
以前のバージョン:
main(x){for(scanf("%d",&x);printf("%d,",x),x-1;x=x&1?3*x+1:x/2);} // 66
(誰も出力フォーマットに従わないため、12文字を削除しました...:|)
別のアセンブラバージョン。これは32ビットの数値に限定されず、10までの数値を処理できます。65534 MS-DOSが使用する「.com」形式は80桁の数字に制限されています。 A86アセンブラー用に作成されており、実行にはWin-XP DOSボックスが必要です。 180バイトにアセンブルします。
mov ax,cs
mov si,82h
add ah,10h
mov es,ax
mov bh,0
mov bl,byte ptr [80h]
cmp bl,1
jbe ret
dec bl
mov cx,bx
dec bl
xor di,di
p1:lodsb
sub al,'0'
cmp al,10
jae ret
stosb
loop p1
xor bp,bp
Push es
pop ds
p2:cmp byte ptr ds:[bp],0
jne p3
inc bp
jmp p2
ret
p3:lea si,[bp-1]
cld
p4:inc si
mov dl,[si]
add dl,'0'
mov ah,2
int 21h
cmp si,bx
jne p4
cmp bx,bp
jne p5
cmp byte ptr [bx],1
je ret
p5:mov dl,'-'
mov ah,2
int 21h
mov dl,'>'
int 21h
test byte ptr [bx],1
jz p10
;odd
mov si,bx
mov di,si
mov dx,3
dec bp
std
p6:lodsb
mul dl
add al,dh
aam
mov dh,ah
stosb
cmp si,bp
jnz p6
or dh,dh
jz p7
mov al,dh
stosb
dec bp
p7:mov si,bx
mov di,si
p8:lodsb
inc al
xor ah,ah
aaa
stosb
or ah,ah
jz p9
cmp si,bp
jne p8
mov al,1
stosb
jmp p2
p9:inc bp
jmp p2
p10:mov si,bp
mov di,bp
xor ax,ax
p11:lodsb
test ah,1
jz p12
add al,10
p12:mov ah,al
shr al,1
cmp di,bx
stosb
jne p11
jmp p2
dc
は、このシーケンスに適したツールです。
?[d5*2+d2%*+2/pd1<L]dsLx
dc -f collatz.dc 21 64 32 16 8 4 2 1
Golfscript エントリの式を使用した24文字も:
?[3*1+d2%5*1+/pd1<L]dsLx
57文字で仕様を満たす:
[Number: ]n?[Results: ]ndn[d5*2+d2%*+2/[ -> ]ndnd1<L]dsLx
dc -f collatz-spec.dc 数値:3 結果:3-> 10-> 5-> 16-> 8-> 4-> 2-> 1
スキーム:72
(define(c n)(if(= n 1)`(1)(cons n(if(odd? n)(c(+(* n 3)1))(c(/ n 2))))))
これは再帰を使用しますが、呼び出しは末尾再帰であるため、繰り返しに最適化されると思います。いくつかの簡単なテストでは、スタックがオーバーフローする数値を見つけることができませんでした。ちょうど例:
(c 9876543219999999999000011234567898888777766665555444433332222 7777777777777777777777777777777798797657657651234143375987342987 5398709812374982529830983743297432985230985739287023987532098579 058095873098753098370938753987)
...うまく動作します。 [これはすべて1つの数字です。画面に収まるように分割しました。]
c=NestWhileList[If[OddQ@#,3#+1,#/2]&,#,#>1&]&
Python 45文字
マカプフの答えからイワナを剃った。
n=input()
while~-n:n=(n/2,n*3+1)[n%2];print n
基本的に makapuf's Python solution の直接のリップ:
def c(n)while n>1;n=n.odd?? n*3+1: n/2;p n end end
基本的に質問で提供されたコードの直接のリップ:
def c(n)p n;n.odd?? c(3*n+1):c(n/2)if n>1 end
import Java.math.BigInteger;
public class SortaJava {
static final BigInteger THREE = new BigInteger("3");
static final BigInteger TWO = new BigInteger("2");
interface BiFunc<R, A, B> {
R call(A a, B b);
}
interface Cons<A, B> {
<R> R apply(BiFunc<R, A, B> func);
}
static class Collatz implements Cons<BigInteger, Collatz> {
BigInteger value;
public Collatz(BigInteger value) { this.value = value; }
public <R> R apply(BiFunc<R, BigInteger, Collatz> func) {
if(BigInteger.ONE.equals(value))
return func.call(value, null);
if(value.testBit(0))
return func.call(value, new Collatz((value.multiply(THREE)).add(BigInteger.ONE)));
return func.call(value, new Collatz(value.divide(TWO)));
}
}
static class PrintAReturnB<A, B> implements BiFunc<B, A, B> {
boolean first = true;
public B call(A a, B b) {
if(first)
first = false;
else
System.out.print(" -> ");
System.out.print(a);
return b;
}
}
public static void main(String[] args) {
BiFunc<Collatz, BigInteger, Collatz> printer = new PrintAReturnB<BigInteger, Collatz>();
Collatz collatz = new Collatz(new BigInteger(args[0]));
while(collatz != null)
collatz = collatz.apply(printer);
}
}
最短ではなく、斬新なアプローチ。大きなシーケンスではかなり遅くなりますが、オーバーフローすることはありません。
PROGRAM:COLLATZ
:ClrHome
:Input X
:Lbl 1
:While X≠1
:If X/2=int(X/2)
:Then
:Disp X/2→X
:Else
:Disp X*3+1→X
:End
:Goto 1
:End
bignumがサポートされ、スタックオーバーフローの影響を受けやすい:
def c(n)p n;n%2>0?c(3*n+1):c(n/2)if n>1 end
... 50文字、bignumをサポート、スタックオーバーフローなし:
def d(n)while n>1 do p n;n=n%2>0?3*n+1:n/2 end end
ヨルダンへの称賛。プットの代わりとしての「p」については知りませんでした。
最短ではありませんが、エレガントなclojureソリューション
(defn collatz [n]
(print n "")
(if (> n 1)
(recur
(if (odd? n)
(inc (* 3 n))
(/ n 2)))))
nroff -U hail.g
で実行
.warn
.pl 1
.pso (printf "Enter a number: " 1>&2); read x; echo .nr x $x
.while \nx>1 \{\
. ie \nx%2 .nr x \nx*3+1
. el .nr x \nx/2
\nx
.\}
1. groffバージョン
Scala + Scalaz
import scalaz._
import Scalaz._
val collatz =
(_:Int).iterate[Stream](a=>Seq(a/2,3*a+1)(a%2)).takeWhile(1<) // This line: 61 chars
そして実際に:
scala> collatz(7).toList
res15: List[Int] = List(7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2)
Scala 2.8
val collatz =
Stream.iterate(_:Int)(a=>Seq(a/2,3*a+1)(a%2)).takeWhile(1<) :+ 1
これには、末尾の1も含まれます。
scala> collatz(7)
res12: scala.collection.immutable.Stream[Int] = Stream(7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1)
次の暗黙の
implicit def intToEven(i:Int) = new {
def ~(even: Int=>Int, odd: Int=>Int) = {
if (i%2==0) { even(i) } else { odd(i) }
}
}
これは以下に短縮できます
val collatz = Stream.iterate(_:Int)(_~(_/2,3*_+1)).takeWhile(1<) :+ 1
編集-58文字(入力と出力を含むが、初期番号は含まない)
var n=readInt;while(n>1){n=Seq(n/2,n*3+1)(n%2);println(n)}
改行が必要ない場合は、2減らすことができます...
C#:216文字
using C=System.Console;class P{static void Main(){var p="start:";System.Action<object> o=C.Write;o(p);ulong i;while(ulong.TryParse(C.ReadLine(),out i)){o(i);while(i > 1){i=i%2==0?i/2:i*3+1;o(" -> "+i);}o("\n"+p);}}}
長い形式で:
using C = System.Console;
class P
{
static void Main()
{
var p = "start:";
System.Action<object> o = C.Write;
o(p);
ulong i;
while (ulong.TryParse(C.ReadLine(), out i))
{
o(i);
while (i > 1)
{
i = i % 2 == 0 ? i / 2 : i * 3 + 1;
o(" -> " + i);
}
o("\n" + p);
}
}
}
新しいバージョン。コマンドラインから入力として1つの数値を受け入れます。入力の検証は行いません。 173 154文字
using System;class P{static void Main(string[]a){Action<object>o=Console.Write;var i=ulong.Parse(a[0]);o(i);while(i>1){i=i%2==0?i/2:i*3+1;o(" -> "+i);}}}
長い形式で:
using System;
class P
{
static void Main(string[]a)
{
Action<object>o=Console.Write;
var i=ulong.Parse(a[0]);
o(i);
while(i>1)
{
i=i%2==0?i/2:i*3+1;
o(" -> "+i);
}
}
}
私はこれのアイデアを取り除くことでいくつかの文字を剃ることができます answer forループを使用するのではなく、しばらく使用します。 150文字。
using System;class P{static void Main(string[]a){Action<object>o=Console.Write;for(var i=ulong.Parse(a[0]);i>1;i=i%2==0?i/2:i*3+1)o(i+" -> ");o(1);}}
c 1=[1];c n=n:(c$if odd n then 3*n+1 else n`div`2)
一般的なLISP、141文字:
(defun c ()
(format t"Number: ")
(loop for n = (read) then (if(oddp n)(+ 1 n n n)(/ n 2))
until (= n 1)
do (format t"~d -> "n))
(format t"1~%"))
テスト走行:
Number: 171
171 -> 514 -> 257 -> 772 -> 386 -> 193 -> 580 -> 290 -> 145 -> 436 ->
218 -> 109 -> 328 -> 164 -> 82 -> 41 -> 124 -> 62 -> 31 -> 94 -> 47 ->
142 -> 71 -> 214 -> 107 -> 322 -> 161 -> 484 -> 242 -> 121 -> 364 ->
182 -> 91 -> 274 -> 137 -> 412 -> 206 -> 103 -> 310 -> 155 -> 466 ->
233 -> 700 -> 350 -> 175 -> 526 -> 263 -> 790 -> 395 -> 1186 -> 593 ->
1780 -> 890 -> 445 -> 1336 -> 668 -> 334 -> 167 -> 502 -> 251 -> 754 ->
377 -> 1132 -> 566 -> 283 -> 850 -> 425 -> 1276 -> 638 -> 319 ->
958 -> 479 -> 1438 -> 719 -> 2158 -> 1079 -> 3238 -> 1619 -> 4858 ->
2429 -> 7288 -> 3644 -> 1822 -> 911 -> 2734 -> 1367 -> 4102 -> 2051 ->
6154 -> 3077 -> 9232 -> 4616 -> 2308 -> 1154 -> 577 -> 1732 -> 866 ->
433 -> 1300 -> 650 -> 325 -> 976 -> 488 -> 244 -> 122 -> 61 -> 184 ->
92 -> 46 -> 23 -> 70 -> 35 -> 106 -> 53 -> 160 -> 80 -> 40 -> 20 ->
10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Ruby -n hail
で実行
n=$_.to_i
(n=n%2>0?n*3+1: n/2
p n)while n>1
let c=Seq.unfold(function|n when n<=1->None|n when n%2=0->Some(n,n/2)|n->Some(n,(3*n)+1))
> c 21;;
val it : seq<int> = seq [21; 64; 32; 16; ...]
または、F#インタラクティブを使用して結果を表示しない場合は、102文字です。
let c=Seq.unfold(function|n when n<=1->None|n when n%2=0->Some(n,n/2)|n->Some(n,(3*n)+1))>>printf"%A"
using System.Linq;using C=System.Console;class Program{static void Main(){var v=C.ReadLine();C.Write(v);while(v!="1"){C.Write("->");if(v[v.Length-1]%2==0){v=v.Aggregate(new{s="",o=0},(r,c)=>new{s=r.s+(char)((c-48)/2+r.o+48),o=(c%2)*5}).s.TrimStart('0');}else{var q=v.Reverse().Aggregate(new{s="",o=0},(r, c)=>new{s=(char)((c-48)*3+r.o+(c*3+r.o>153?c*3+r.o>163?28:38:48))+r.s,o=c*3+r.o>153?c*3+r.o>163?2:1:0});var t=(q.o+q.s).TrimStart('0').Reverse();var x=t.First();q=t.Skip(1).Aggregate(new{s=x>56?(x-57).ToString():(x-47).ToString(),o=x>56?1:0},(r,c)=>new{s=(char)(c-48+r.o+(c+r.o>57?38:48))+r.s,o=c+r.o>57?1:0});v=(q.o+q.s).TrimStart('0');}C.Write(v);}}}
ゴルフなし
using System.Linq;
using C = System.Console;
class Program
{
static void Main()
{
var v = C.ReadLine();
C.Write(v);
while (v != "1")
{
C.Write("->");
if (v[v.Length - 1] % 2 == 0)
{
v = v
.Aggregate(
new { s = "", o = 0 },
(r, c) => new { s = r.s + (char)((c - 48) / 2 + r.o + 48), o = (c % 2) * 5 })
.s.TrimStart('0');
}
else
{
var q = v
.Reverse()
.Aggregate(
new { s = "", o = 0 },
(r, c) => new { s = (char)((c - 48) * 3 + r.o + (c * 3 + r.o > 153 ? c * 3 + r.o > 163 ? 28 : 38 : 48)) + r.s, o = c * 3 + r.o > 153 ? c * 3 + r.o > 163 ? 2 : 1 : 0 });
var t = (q.o + q.s)
.TrimStart('0')
.Reverse();
var x = t.First();
q = t
.Skip(1)
.Aggregate(
new { s = x > 56 ? (x - 57).ToString() : (x - 47).ToString(), o = x > 56 ? 1 : 0 },
(r, c) => new { s = (char)(c - 48 + r.o + (c + r.o > 57 ? 38 : 48)) + r.s, o = c + r.o > 57 ? 1 : 0 });
v = (q.o + q.s)
.TrimStart('0');
}
C.Write(v);
}
}
}
@set/pd=
:l
@set/ad=(d+d%%2*(d*5+2))/2&echo %d%&if %d% NEQ 1 goto:l
他のJS(および他のほとんどの言語)とは異なり、これは実際には出力の->
に準拠しています。
for(s='',c=' -> ',i=readline();i>1;i=i%2?i*3+1:i/2)s+=i+c
print(s+1)
それを回避する場合、これは53 charの代替であり、1行に1つの数値を出力します。
for(p=print,i=readline(),p(i);i>1;)p(i=i%2?i*3+1:i/2)
SpiderMonkeyで実行する意味:
echo 21 | js thisfile.js
21 -> 64 -> 32 -> 16 -> 8 -> 4 -> 2 -> 1
Jerry Coffinプログラムは、整数オーバーフローを持っています。これを試してください:
#include <iostream>
int main(unsigned long long i)
{
int j = 0;
for( std::cin>>i; i>1; i = i&1? i*3+1:i/2, ++j)
std::cout<<i<<" -> ";
std::cout<<"\n"<<j << " iterations\n";
}
テスト済み
停止時間の合計が最も長い1億未満の数は63,728,127で、949ステップあります。
合計停止時間が最も長い10億未満の数は670,617,279、986ステップです。
n=input('');while n>1,n=n/2+rem(n,2)*(n*5+2)/2;disp(n);end
テストケース:
>> n=input('');while n>1,n=n/2+rem(n,2)*(n*5+2)/2;disp(n);end
21
64
32
16
8
4
2
1
n=1
1 if(n==1)read*,n
n=merge(n/2,3*n+1,mod(n,2)==0)
print*,n
goto1
end
誰かがそれをしなければならなかったので:)
カウントには、必要な改行が含まれます。完全準拠のFortran 95(およびそれ以降)コード。完全なI/Oを含み、何回でも実行できます!
編集: gotoを使用してcharを1つ減らします(スタイルのポイント!)
for(a=[i=Prompt()];i-1;a.Push(i=i%2?i*3+1:i/2));alert(a)
ルビー、41文字
n=gets.to_i
p n=[n/2,n*3+1][n%2]while n>1
[〜#〜] php [〜#〜]
function Collatz($n)
{
$i = 0;
while($n>1)
{
if($n % 2)
{
$n = (3*$n) + 1;
$i++;
echo "step $i: $n <br/>";
}
else
{
$n = $n/2;
$i++;
echo "step $i: $n <br/>";
}
}
}
LOLCODEソリューションには少し関心があるようですので、この言語での2つのソリューションアプローチ(反復と末尾再帰)の実装を比較すると思います。
最初に、203文字の反復解があります。
HAI 1.2
I HAS A n
GIMMEH n
IM IN YR l
VISIBLE n
BOTH SAEM 1 BIGGR OF 1 n
O RLY?
YA RLY
GTFO
OIC
MOD OF n 2
WTF?
OMG 0
n R QUOSHUNT OF n 2
GTFO
OMG 1
n R SUM OF 1 PRODUKT OF 3 n
OIC
IM OUTTA YR l
KTHXBYE
何が起こっているのかを説明するには:
GIMMEH
キーワードを使用してSTDINから読み取られますIM IN YR <loopname>
ステートメントとIM OUTTA YR <loopname>
ステートメントの間でループが行われますVISIBLE
はSTDOUTへの出力に使用されますO RLY?
、YA RLY
、およびOIC
ステートメントは、条件付きのIf/Then/Elseロジックを処理しますWTF?
、OMG <expression>
、およびOIC
ステートメントは、条件付きのスイッチ/ケースロジックを処理します<variable> R <value>
を使用して実行されますそして、最後のカウントが201になるように2つの追加文字を削り落とすことに成功した末尾再帰ソリューションがあります。
HAI 1.2
HOW Duz I c YR n
VISIBLE n
DIFFRINT 1 BIGGR OF 1 n
O RLY?
YA RLY
MOD OF n 2
WTF?
OMG 0
c QUOSHUNT OF n 2
GTFO
OMG 1
c SUM OF 1 PRODUKT OF 3 n
OIC
OIC
IF U SAY SO
I HAS A i
GIMMEH i
c i
KTHXBYE
ここでの違いは、HOW Duz I <funcname> YR <args>
ステートメントとIF U SAY SO
ステートメント間の関数の定義です。関数は<funcname> <args>
で呼び出されます。
私が実際にこのプログラムを書いたのは、2年ほど前、Pickoverの本でシーケンスについて読んだ後です。私はそれを少し整理しました、そしてこれは私が作ることができる最小のものであり、それでもユーザー入力と素晴らしい、読みやすい出力を持っています:
<?$n=fgets(STDIN);while($n!=1){$n=(($n&1)==0)?($n/2):(($n*3)+1);echo"$n\n";}?>
短いタグが有効になっていると想定する必要があり、入力がすべてのコンソールで機能するかどうかはわかりません。しかし、私のWindowsマシンでは完全に動作します。
pdate:数学をごまかすだけで、一部の文字を削ることができます。
<?$n=fgets(STDIN);while($n!=1){$n=(($n&1)==0)?$n/2:$n*3+1;echo"$n\n";}?>
更新:
$n&1
はどちらかを返します1
または0
、PHPの緩い型付けを利用して、さらにいくつかの文字を削除できます。?>
、さらに2つの文字を取り除くことができます。最終結果:
<?$n=fgets(STDIN);while($n>1){$n=(!($n&1))?$n/2:$n*3+1;echo"$n\n";}
VB.Net、約180文字
Sub Main()
Dim q = New Queue(Of Integer)
q.Enqueue(CInt(Console.ReadLine))
Do
q.Enqueue(CInt(If(q.Peek Mod 2 = 0, q.Dequeue / 2, q.Dequeue * 3 + 1)))
Console.WriteLine(q.Peek)
Loop Until q.Peek = 1
End Sub
面白いのは、このコードをc#に変換して、さらに文字を作成することです。
空の.vbファイル(約245文字)で機能させる
Imports System.Collections.Generic
Imports System
Module m
Sub Main()
Dim q = New Queue(Of Integer)
q.Enqueue(CInt(Console.ReadLine))
Do
q.Enqueue(CInt(If(q.Peek Mod 2 = 0, q.Dequeue / 2, q.Dequeue * 3 + 1)))
Console.WriteLine(q.Peek)
Loop Until q.Peek = 1
End Sub
End Module
バッシュ、スペースと改行を含む130:
#!/bin/bash
if [ $1 == 1 ]; then echo $1
else if [ $(($1%2)) == 0 ]; then n=$(($1/2))
else n=$(($1*3+1))
fi
echo "$1 -> `c $n`"
fi
これは、cがスクリプトファイルの名前であり、スクリプトを実行しているユーザーのパスにあることを前提としています。
TextWindow.Write( "Number: " )
n = TextWindow.ReadNumber()
TextWindow.Write( "Results: " )
While ( n > 1 )
TextWindow.Write( n + " -> " )
If Math.Remainder( n, 2 ) = 0 Then
n = n / 2
Else
n = n * 3 + 1
EndIf
EndWhile
TextWindow.WriteLine(1)
次の場所で実行できます http://smallbasic.com/program/?ZZR544
Python:
def collatz(n):
if (n%2) == 0:
return n/2
else:
return 3*n+1
def do_collatz(n):
while n > 1:
print n
n = collatz(n)
print n
do_collatz(int(input("Start number: ")))
スタックオーバーフローに対して脆弱ではないが、1に収束しないシーケンスで終了しない(編集:入力部分を忘れた)
Perl、59文字:
sub c{print my$x="@_\n";@_=$x&1?$x*3+1:$x/2,goto&c if$x!=1}
let rec f n=printfn "%A" n;if n>1I then if n%2I=0I then f(n/2I)else f(3I*n+1I)
J、45文字
(-: * 0&=@(2&|)) + (1 + 3&*) * -.@(0&=@(2&|))
私はJの専門家ではありません。平均の関数は+ /%#なので、これを短くすることができると確信しています。
1INPUT N
2N=(N+(N*5+2)*(N MOD 2))/2:?N:IF N>1GOTO 2
(defun c(n)(if (eql n 1)'(1)(cons n(if(oddp n)(c(1+(* 3 n)))(c(/ n 2))))))
または、適切に書かれ、
(defun collatz (n)
(if (eql n 1)
'(1)
(cons n (if (oddp n)
(collatz (1+ (* 3 n)))
(collatz (/ n 2))))))
因子:
ゴルフなしで
USE: math
: body ( n -- n ) >integer dup . "->" . dup odd? = [ 3 * 1 + ] [ 2 / ] if ;
: hailstone ( n -- ) dup 1 > [ body hailstone ] [ . ] if ;
21 hailstone
ゴルフ:
21 [ dup 1 > ] [ >integer dup . "->" . dup 2 mod 1 = [ 3 * 1 + ] [ 2 / ] if ] while .
出力:
21
"->"
64
"->"
32
"->"
16
"->"
8
"->"
4
"->"
2
"->"
1
main(x){scanf("%d",&x);while(x>printf("%d ",x=x&1?3*x+1:x/2));}
これは、KennyTMからの回答に基づいています。 forループはwhileループに変更され、コードはwhile内に組み込まれました。
反復、精度はJS制限に依存
var i=Prompt('');while(i>1){console.log(i);i=(i%2)?3*i+1:i/2}
Erlang、120文字
-module (f).
-export ([f/1]).
f(1)->1;
f(N)->
io:format("~p ",[N]),
if N rem 2 =:= 0
->f(trunc(N/2));
true->f(3*N+1)
end.
テスト:
f:f(171).
171 514 257 772 386 193 580 290 145 436 218 109 328 164 82 41 124 62 31 94 47
142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466
233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167 502 251
754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619
4858 2429 7288 3644 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154
577 1732 866 433 1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53 160
80 40 20 10 5 16 8 4 2 1
Fgets(STDIN)を提供してくれたDankoDurbićに感謝します。
<?$i=fgets(STDIN);while($i!=1){echo ($i=$i%2?$i*3+1:$i/=2),"\r\n";}?>
VBScript:105文字
どうやら私は罰の大食いだ。
c(InputBox( "?")) Public Sub c(i) msgbox(i) If i> 1 Then If i mod 2 = 0次に、 c(i/2) Else c(3 * i + 1) End If End If End Sub
read*,n
1 if(n/2*2<n)n=6*n+2
n=n/2
print*,n
if(n>1)goto1
end
((fn[n](prn n)(if(> n 1)(recur(if(odd? n)(+(* 3 n)1)(/ n 2)))))(read))
または、適切な空白とインデントで:
((fn [n]
(prn n)
(if (> n 1)
(recur
(if (odd? n)
(+ (* 3 n) 1)
(/ n 2)))))
(read))
recur
はClojureに末尾呼び出し再帰を使用するように強制するため、スタックオーバーフローは発生しません。任意の大きな数で動作します。入力と出力が含まれますが、非数値を入力するとクラッシュします:)。
注:私の回答を投稿して間もなく、ほぼ同じアルゴリズムを使用した別のClojure実装に気づきました。しかし、それは短くするつもりはないので、ここでは答えをここに残しておきます。
-:`(>:@(3&*))`1:@.(1&=+2&|)^:a:
使用法:
-:`(>:@(3&*))`1:@.(1&=+2&|)^:a: 9
9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
一発ギャグ:
"Results: $(for($x=read-Host Number;1%$x;$x=@($x/2;3*$x+1)[$x%2]){""$x ->""}) 1"
プリティプリント:
"Results: $( for( $x = read-Host Number; 1%$x; $x = @( $x/2; 3*$x+1 )[ $x%2 ] )
{
""$x ->""
}
) 1"
for($x=read-Host;1%$x;$x=@($x/2;3*$x+1)[$x%2]){$x}1
int n=args[0] as int
while(n>1){println n=n%2==0?n/2:n*3+1}
例
$ ./collatz.groovy 5
16
8
4
2
1
よりきれいな出力(66文字)
int n=args[0] as int
while(n>1){print " -> ${n=n%2==0?n/2:n*3+1}"}
例
$ ./collatz.groovy 5
-> 16 -> 8 -> 4 -> 2 -> 1
[:n||l|l:=OrderedCollection with:1.[n>1]whileTrue:[l addLast:n.n:=n odd ifTrue:[3*n+1]ifFalse:[n/2]].l]
メッセージ#value:を送信し、必要なパラメーターを指定して呼び出します。
[:n||l|l:=OrderedCollection with:1.[n>1]whileTrue:[l addLast:n.n:=n odd ifTrue:[3*n+1]ifFalse:[n/2]].l] value: 123
または、より正気に:
[:n | | result |
result := OrderedCollection with: 1.
[n > 1] whileTrue: [
result addLast: n.
n := n odd ifTrue: [3*n + 1] ifFalse: [n / 2]].
result] value: 123
(適切な方法は、上記をIntegerのメソッドとして定義することになるため、匿名のクロージャーとしてではなく、「123 collatz」と言います。)
n=gets.to_i
while(n>1) do n=((n%2)==1)?3*n+1:n/2;p n end
Arのコードに基づいて、実際に出力要件に準拠するPerlバージョンを示します
Perl -E 'print"Number: ";$_=<STDIN>;chomp;print"Results: $_";$_=$_%2?$_*3+1:$_/2,print" -> ",$_ while$_!=1;say""'
長さ:Perlの呼び出しと引用を含めて114、104はなし
一部の経験豊富なゴルファーは、この原油バージョンをさらに減らすことができると思います。
Perl、59文字
$n=shift;for($i=1;$n>1;$i++){$n=$n%2==0?$n/2:$n*3+1;printf"%002s: %s\n",$i,$n;}
ただし、このバージョンは79文字(空白を数えない)でより良いので、行番号と反復値が出力されます。
$n = shift; for($i = 1; $n > 1; $i++){ $n = $n % 2 == 0 ? $n / 2 : $n*3 + 1; printf "%002s: %s\n", $i, $n;}
$n = shift;
for($i = 1; $n > 1; $i++){
$n = $n % 2 == 0 ? $n / 2 : $n*3 + 1;
printf "%002s: %s\n", $i, $n;
}
package main
import(."os"
."strconv")
func main(){n,_:=Atoi(Args[1])
println(n)
for n>1{if n%2!=0{n=n*3+1}else{n/=2}
println(n)}}
例
./collatz 3
3
10
5
16
8
4
2
1
C#、88文字だと思います。再帰的
void T(int i,string s){Console.Write("{0}{1}",s,i);if(i!=1)T(i%2==0?i/2:(i*3)+ 1,"->");}
さらに、この最初の呼び出し
T(171, "");
これは非再帰的な方法です、107文字だと思います
void T2(int i){string s="";while(i>=1){Console.Write("{0}{1}",s,i);i=i==1?-1:i=i%2==0?i/2:(i*3)+1;s="->";}}
C++ 113100 95
#include <iostream>
int main(int i){for(std::cin>>i;i>1;i=i&1?i*3+1:i/2)std::cout<<i<<" -> ";}
c n=" 1",if n=1
=" "++shownum(n)++c(n*3+1),if n mod 2=1
=" "++shownum(n)++c(n div 2),otherwise
(空白は構文的に重要です)
別のbashエントリ。無限精度の計算を実行せず、オーバーフローする可能性があります。
#!/bin/bash
x=$1;echo $x;((x>1))&&$0 $((x%2?x*3+1:x/2))
オーバーフローしてはならないバージョンは
#!/bin/bash
x=$1;echo $x;((x>1))&&exec $0 $((x%2?x*3+1:x/2))
(編集)反復バージョンも:
#!/bin/bash
for((x=$1;x>1;x=x%2?x*3+1:x/2));do echo $x;done
Josl-58文字
このバージョンでは、末尾再帰のためにスタックオーバーフローは発生しません。
c dup println dup 1 > if dup odd? if 3 * 1+ else 2 / end c
使用する:
main 21 c
または、他の例:
main
21 c
63,728,127 c