web-dev-qa-db-ja.com

コードゴルフ:Collat​​z予想

http://xkcd.com/710/ からインスピレーションを受けましたここにコードゴルフがあります。

チャレンジ

0より大きい正の整数を指定して、その数のひょうのシーケンスを出力します。

ひょうのシーケンス

詳細は Wikipedia を参照してください。

  • 数が偶数の場合は、2で割ります。
  • 数が奇数の場合は、3倍にして1を加えます。

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には完全なユーザー入力と出力が含まれている必要があります。

86
Earlz

x86アセンブリ、1337文字

;
; 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
129
Martin

Befunge

&>:.:1-|
  >3*^ @
  |%2: <
 v>2/>+
64
Josh Lee

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!

52
lunohodov

Python- 956451 46文字

明らかに、スタックオーバーフローは発生しません。

n=input()
while n>1:n=(n/2,n*3+1)[n%2];print n
51
makapuf

Haskell、62文字 637683、 86、 97、 137

_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に落ちました)

23
jkff

Perl

私は少し反競争的であることに決め、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スイッチがないとコードは機能しません。したがって、例全体をカウントに含めます。

23
Brad Gilbert

Golfscript:20文字

  ~{(}{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;
22
kennytm

bc 41文字

この種の問題は 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サイクル。

19

Perl:31文字

Perl -nE 'say$_=$_%2?$_*3+1:$_/2while$_>1'
#         123456789 123456789 123456789 1234567

2つの不要なスペースを削除するように編集されました。

1つの不要なスペースを削除するように編集されました。

16
a'r

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回コピー/貼り付けるだけでした。;)

15
Lance McNearney

C:64文字

main(x){for(scanf("%d",&x);x>=printf("%d,",x);x=x&1?3*x+1:x/2);}

大きな整数のサポート:431(必須)文字

#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文字を削除しました...:|)

14
kennytm

別のアセンブラバージョン。これは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
12
Skizz

dc-24文字 2528

dc は、このシーケンスに適したツールです。

?[d5*2+d2%*+2/pd1<L]dsLx
 dc -f collat​​z.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 collat​​z-spec.dc 
数値:3 
結果:3-> 10-> 5-> 16-> 8-> 4-> 2-> 1 
10

スキーム: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つの数字です。画面に収まるように分割しました。]

9
Jerry Coffin

Mathematica、45歳 50 チャー

c=NestWhileList[If[OddQ@#,3#+1,#/2]&,#,#>1&]&
8
Pillsy

Python 45文字

マカプフの答えからイワナを剃った。

n=input()
while~-n:n=(n/2,n*3+1)[n%2];print n
7
GuillaumeDufay

Ruby、50文字、スタックオーバーフローなし

基本的に makapuf's Python solution の直接のリップ:

def c(n)while n>1;n=n.odd?? n*3+1: n/2;p n end end

ルビー、45文字、オーバーフローします

基本的に質問で提供されたコードの直接のリップ:

def c(n)p n;n.odd?? c(3*n+1):c(n/2)if n>1 end
7
Jordan Running
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);
    }
}
7
wowest

TI-BASIC

最短ではなく、斬新なアプローチ。大きなシーケンスではかなり遅くなりますが、オーバーフローすることはありません。

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
5
Jonathan

ルビー、43文字

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」については知りませんでした。

4

最短ではありませんが、エレガントなclojureソリューション

(defn collatz [n]
 (print n "")
 (if (> n 1)
  (recur
   (if (odd? n)
    (inc (* 3 n))
    (/ n 2)))))
4
cobbal

nroff1

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バージョン

4
DigitalRoss

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減らすことができます...

4
retronym

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

ハスケル:50

c 1=[1];c n=n:(c$if odd n then 3*n+1 else n`div`2)
4
Josh Lee

一般的な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 
3
Vatine

Ruby、43歳、おそらくI/O要件を満たしている


Ruby -n hailで実行

n=$_.to_i
(n=n%2>0?n*3+1: n/2
p n)while n>1
3
DigitalRoss

F#、90文字

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"
3
Joel Mueller

C#:BigIntegerをサポートする659文字

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

Windows cmd-68文字

@set/pd=
:l 
@set/ad=(d+d%%2*(d*5+2))/2&echo %d%&if %d% NEQ 1 goto:l
3

JavaScript-68文字

他の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
3
gnarf

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ステップです。

3
Soumen Sarkar

MATLAB 7.8.0(R2009a):58文字

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
2
gnovice

Fortran:71文字

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つ減らします(スタイルのポイント!)

2
F'x

Javascript、 67 56文字

for(a=[i=Prompt()];i-1;a.Push(i=i%2?i*3+1:i/2));alert(a)
2
Marko Dumic

ルビー、41文字

n=gets.to_i
p n=[n/2,n*3+1][n%2]while n>1
2
steenslag

[〜#〜] 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/>";
        }
    }

}
2
Bad Programmer

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>を使用して実行されます
  • GTFOがループまたは条件付きのスイッチ/ケースから中断する

そして、最後のカウントが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
user359512

PHP、 7872 67文字

私が実際にこのプログラムを書いたのは、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の緩い型付けを利用して、さらにいくつかの文字を削除できます。
  • また、以下のクリスチャンのコメントを組み込んで(無限ループを防ぐための小さな変更を加えて)、もう1つ削除できます。
  • 最後に、PHPスクリプトは終了?>、さらに2つの文字を取り除くことができます。

最終結果:

<?$n=fgets(STDIN);while($n>1){$n=(!($n&1))?$n/2:$n*3+1;echo"$n\n";}
2
Jonathan

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
1
Fredou

バッシュ、スペースと改行を含む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がスクリプトファイルの名前であり、スクリプトを実行しているユーザーのパスにあることを前提としています。

1
executor21

Microsoft Small Basic

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

1
Danko Durbić

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に収束しないシーケンスで終了しない(編集:入力部分を忘れた)

1
Raceimaztion

Perl、59文字:

sub c{print my$x="@_\n";@_=$x&1?$x*3+1:$x/2,goto&c if$x!=1}
1
Sean

F#82文字

let rec f n=printfn "%A" n;if n>1I then if n%2I=0I then f(n/2I)else f(3I*n+1I)
1
ChaosPandion

J、45文字

(-: * 0&=@(2&|)) + (1 + 3&*) * -.@(0&=@(2&|))

私はJの専門家ではありません。平均の関数は+ /%#なので、これを短くすることができると確信しています。

1
REDace0

GW-BASIC-54文字

1INPUT N
2N=(N+(N*5+2)*(N MOD 2))/2:?N:IF N>1GOTO 2
1

一般的なLISP、 76 74文字

(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))))))
0
Frank Shearar

因子

ゴルフなしで

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
0
egaga

C:63文字

main(x){scanf("%d",&x);while(x>printf("%d ",x=x&1?3*x+1:x/2));}

これは、KennyTMからの回答に基づいています。 forループはwhileループに変更され、コードはwhile内に組み込まれました。

0
jme

JavaScript、61 70 入力付きの文字

反復、精度はJS制限に依存

var i=Prompt('');while(i>1){console.log(i);i=(i%2)?3*i+1:i/2}
0
Kuroki Kaze

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
0
cheng81

PHP。 69キャラクター

Fgets(STDIN)を提供してくれたDankoDurbićに感謝します。

<?$i=fgets(STDIN);while($i!=1){echo ($i=$i%2?$i*3+1:$i/=2),"\r\n";}?>
0
Neil Aitken

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
0
JohnK813

Fortran-60文字

read*,n
1 if(n/2*2<n)n=6*n+2
n=n/2
print*,n
if(n>1)goto1
end
0
John La Rooy

Clojure-70文字

((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実装に気づきました。しかし、それは短くするつもりはないので、ここでは答えをここに残しておきます。

0
jqno

J、31文字

-:`(>:@(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
0
David

Powershell:80文字

一発ギャグ:

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

入力プロンプトと出力フォーマットなし-44文字:

for($x=read-Host;1%$x;$x=@($x/2;3*$x+1)[$x%2]){$x}1
0
Danko Durbić

Grooovy-59文字

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
0
armandino

Smalltalk、103文字

[: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 collat​​z」と言います。)

0
Frank Shearar

Ruby 55文字

n=gets.to_i
while(n>1) do n=((n%2)==1)?3*n+1:n/2;p n end
0
Gerhard

Arのコードに基づいて、実際に出力要件に準拠するPerlバージョンを示します

Perl -E 'print"Number: ";$_=<STDIN>;chomp;print"Results: $_";$_=$_%2?$_*3+1:$_/2,print" -> ",$_ while$_!=1;say""'

長さ:Perlの呼び出しと引用を含めて114、104はなし

一部の経験豊富なゴルファーは、この原油バージョンをさらに減らすことができると思います。

0
sorpigal

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;
}
0
user2016243

行く、130文字

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
0
user257858

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="->";}}
0
mdm20

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<<" -> ";}
0
Jerry Coffin

ミランダ(101文字)

c n=" 1",if n=1
   =" "++shownum(n)++c(n*3+1),if n mod 2=1
   =" "++shownum(n)++c(n div 2),otherwise

(空白は構文的に重要です)

0
Derek H

bash 57/61/60

別の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
0
Dan Andreatta

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
0
jeremy