Code Golf:Collat​​z猜想

时间:2010-03-05 16:27:18

标签: language-agnostic code-golf rosetta-stone collatz

http://xkcd.com/710/的启发,这是一个高尔夫代码。

挑战

给定大于0的正整数,打印出该数字的冰雹序列。

冰雹序列

有关详细信息,请参阅Wikipedia

  • 如果数字是偶数,则除以2。
  • 如果数字为奇数,则将其加倍并添加一个。

使用生成的数字重复此操作,直至达到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)

此代码有效,但我正在增加额外的挑战。 程序不得容易受到堆栈溢出的影响。所以它必须使用迭代或尾递归。

此外,奖励点是因为它可以计算大数字并且语言尚未实现。 (或者如果使用固定长度的整数重新实现大数字支持)

测试用例

Number: 21
Results: 21 -> 64 -> 32 -> 16 -> 8 -> 4 -> 2 -> 1

Number: 3
Results: 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

此外,代码高尔夫必须包括完整的用户输入和输出。

70 个答案:

答案 0 :(得分:129)

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

答案 1 :(得分:64)

Befunge

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

答案 2 :(得分:52)

LOLCODE:406 CHARAKTERZE

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 INTERPRETR下的测试。 KTHXBYE!

答案 3 :(得分:51)

Python - 95 64 51 46 char

显然不会产生堆栈溢出。

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

答案 4 :(得分:23)

的Perl

我决定有点反竞争,并展示你通常如何在Perl中编写这样的问题。
最后还有一个46(总)char code-golf条目。

前三个例子都是从这个标题开始的。

#! /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次之后,这是一个代表性的样本输出:

            Rate Recursive Iterative Optimized
Recursive 1715/s        --      -27%      -46%
Iterative 2336/s       36%        --      -27%
Optimized 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开关,代码将无法工作。所以我将整个例子包含在我的计数中。

答案 5 :(得分:23)

Haskell,62个字符 63 76 83 86 97 , <击> 137

c 1=[1]
c n=n:c(div(n`mod`2*(5*n+2)+n)2)
main=readLn>>=print.c

用户输入,打印输出,使用常量内存和堆栈,使用任意大整数。

这段代码的

A sample run,给出了所有'1'(!)作为输入的80位数字,看起来非常有趣。


原创,仅限功能版本:

Haskell 51 chars

f n=n:[[],f([n`div`2,3*n+1]!!(n`mod`2))]!!(1`mod`n)

@&amp; ^#究竟是谁需要条件?

(编辑:我是“聪明”并使用修复。没有它,代码下降到54个字符。  edit2:通过分解f()

降至51

答案 6 :(得分:22)

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;

答案 7 :(得分:19)

bc 41 chars

我想这类问题是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 article提到此猜想已检查所有值 20x2 58 (aprox。 5.76e18 )。这个计划:

c=0;for(n=2^20000+1;n>1;){if(n%2)n=n*6+2;n/=2;c+=1};n;c

68 秒内测试 2 20,000 +1 (aprox。 3.98e6,020 > 144,404 周期。

答案 8 :(得分:16)

Perl:31个字符

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

编辑删除2个不必要的空格。

编辑删除1个不必要的空间。

答案 9 :(得分:15)

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

只需复制/粘贴公式111次即可得到起始编号为1000的结果。;)

答案 10 :(得分:14)

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

注意:在没有至少原型化malloc / realloc的情况下不要删除#include <stdlib.h>,因为这样做在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个字符,因为没有人遵循输出格式......:|)

答案 11 :(得分: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

答案 12 :(得分:10)

dc - 24个字符 25 28

dc是这个序列的好工具:

?[d5*2+d2%*+2/pd1<L]dsLx
dc -f collatz.dc
21
64
32
16
8
4
2
1

另外24个字符使用Golfscript条目中的公式:

?[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
Number: 3
Results: 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

答案 13 :(得分:9)

计划: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)

......运行得很好。 [这是所有一个数字 - 我刚刚打破它以适应屏幕。]

答案 14 :(得分:8)

Mathematica,45 50 chars

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

答案 15 :(得分:7)

Ruby,50个字符,没有堆栈溢出

基本上是makapuf's Python solution的直接翻录:

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

Ruby,45个字符,将溢出

基本上是直接翻录问题中提供的代码:

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

答案 16 :(得分:7)

Python 45 Char

从makapuf的回答中删除了一个字符。

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

答案 17 :(得分:7)

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

答案 18 :(得分:5)

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

答案 19 :(得分:4)

的nroff 1

使用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版

答案 20 :(得分:4)

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

答案 21 :(得分:4)

不是最短的,而是优雅的clojure解决方案

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

答案 22 :(得分:4)

Haskell:50

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

答案 23 :(得分:4)

Ruby,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'代替看跌期权。

答案 24 :(得分:4)

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

新版本,通过命令行接受一个数字作为输入,无输入验证。 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);}}

答案 25 :(得分:3)

Windows cmd - 68个字符

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

答案 26 :(得分: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 替代方案,每行打印一个数字:

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

答案 27 :(得分:3)

C#:659个具有BigInteger支持的字符

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

<强> Ungolfed

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

答案 28 :(得分:3)

ruby​​,43,可能符合I / O要求


使用ruby -n hail

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

答案 29 :(得分:3)

程序frm 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.

答案 30 :(得分:3)

Common 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 

答案 31 :(得分:3)

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#interactive来显示结果,则包含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"

答案 32 :(得分:2)

Ruby,41个字符

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

答案 33 :(得分:2)

PHP, 78 72 67个字符

在我读完Pickover书中的序列之后,我实际上大约两年前写了这个程序。我清理了一下,这是我能做到的最小的,仍然有用户输入和一个漂亮的,可读的输出:

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

必须假设启用了短标签,而我不确定输入是否适用于所有控制台。但它在我的Windows机器上完美运行。


更新:通过稍微欺骗数学,我们可以减少一些角色:

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

<强>更新

  • 鉴于$n&1返回10,我们可以利用PHP的松散类型并删除更多字符。
  • 另外,在下面加入Christian的评论(稍加改动以防止无限循环),我们可以再删除一个。
  • 最后,由于PHP脚本不需要终止?>,我们可以删除另外两个字符:

最终结果:

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

答案 34 :(得分:2)

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编辑:少一个字符(为样式指点!)

答案 35 :(得分:2)

Javascript, 67 56个字符

for(a=[i=prompt()];i-1;a.push(i=i%2?i*3+1:i/2));alert(a)

答案 36 :(得分:2)

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

答案 37 :(得分:2)

<强> 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/>";
        }
    }

}

答案 38 :(得分:2)

由于对LOLCODE解决方案似乎有点兴趣,我想我会用这种语言比较两种解决方案(迭代和尾递归)的实现。

首先,有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 RLYOIC语句处理条件If / Then / Else逻辑
  • WTF?OMG <expression>OIC语句处理条件切换/案例逻辑
  • 使用<variable> R <value>
  • 执行分配
  • GTFO中断循环或条件切换/案例

然后有一个尾递归解决方案,设法削减2个额外的字符,最终计数为201:

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>调用函数。

答案 39 :(得分:1)

的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的序列上终止。 (编辑:忘记输入部分)

答案 40 :(得分:1)

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

答案 41 :(得分:1)

Perl,59个字符:

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

答案 42 :(得分:1)

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

答案 43 :(得分:1)

J,45个字符

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

我不是J.的专家。因为平均值的函数是+ /%#,我确信这可以缩短。

答案 44 :(得分:1)

F#82 Chars

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

答案 45 :(得分:1)

Bash,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是脚本文件的名称,它位于运行脚本的用户的路径中。

答案 46 :(得分:1)

GW-BASIC - 54个字符

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

答案 47 :(得分:0)

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实现与几乎相同的算法。但是,由于那个不会试图做空,我会在这里留下我的答案,因为它的价值。

答案 48 :(得分:0)

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

答案 49 :(得分:0)

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

答案 50 :(得分:0)

PHP。 69个字符

感谢DankoDurbić为fgets(STDIN),希望你不要介意:)

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

答案 51 :(得分:0)

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

答案 52 :(得分:0)

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

答案 53 :(得分:0)

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

答案 54 :(得分:0)

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”,而不是匿名闭包。)

答案 55 :(得分:0)

Ruby 55 chars

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

答案 56 :(得分:0)

Perl,59 Chars

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

答案 57 :(得分:0)

Fortran - 60 Chars

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

答案 58 :(得分:0)

去,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

答案 59 :(得分:0)

C:63个字符

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

这是基于KennyTM的回答。 for循环被转换为while循环,代码进入while。

答案 60 :(得分:0)

JavaScript,61 70 带输入

的字符

迭代,精度取决于JS限制

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

答案 61 :(得分:0)

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

答案 62 :(得分:0)

<强>因子

没有打高尔夫球

USE: math
: body ( n -- n ) >integer dup . "->" . dup odd? = [ 3 * 1 + ] [ 2 / ] if ;
: hailstone ( n --  ) dup 1 > [ body hailstone ] [ . ] if  ;
21 hailstone

golfed:

21 [ dup 1 > ] [ >integer dup . "->" . dup 2 mod 1 = [ 3 * 1 + ] [ 2 / ] if ] while .

输出:

21
"->"
64
"->"
32
"->"
16
"->"
8
"->"
4
"->"
2
"->"
1

答案 63 :(得分:0)

VBScript:105个字符

显然我是一个受到侮辱的惩罚。

c(InputBox("?"))
Public Sub c(i)
msgbox(i)
If i>1 Then
If i mod 2=0 Then
c(i/2)
Else
c(3*i+1)
End If
End If
End Sub

答案 64 :(得分:0)

Powershell:80个字符

One-liner:

"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

答案 65 :(得分:0)

米兰达(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

(空格在语法上很重要)

答案 66 :(得分:0)

C ++ 113 100 95

#include <iostream>
int main(int i){for(std::cin>>i;i>1;i=i&1?i*3+1:i/2)std::cout<<i<<" -> ";}

答案 67 :(得分:0)

基于ar的代码,这是一个实际符合输出要求的perl版本

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

长度:114计算perl调用和引号,104 withouit

我相信一些经验丰富的高尔夫球手可以进一步减少这种原油版本。

答案 68 :(得分:0)

我认为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="->";}}

答案 69 :(得分:-6)

使用HQ9+的扩展名(我尚未编写),称为HQ9 + C,其中C打印出来自stdin的数字的Collat​​z序列。

C

:P