コラッツの問題

このエントリーをはてなブックマークに追加

コラッツの問題とは,任意の1以上の自然数 n は,以下の手続きを繰り返すと必ず1になるか,という問題である.

  • n が偶数なら2で割る
  • n が奇数なら3倍して1を足す

この問題は正しいか間違っているかまだわかっていない.正しいことを示すには数学的な証明が必要であり,間違っていることを示すには反例を示せば良い.
今,nより小さい自然数については,主張が成り立っているとする.

  • n = 2m1 の場合,次のステップの値は m1 であり,n より小さいから,手続きを繰り返すと必ず1になる.
  • n = 2m1+1 の場合,次のステップの値は 6m1+4,その次は 3m1+2 となりn より大きい.

n = 2m1+1 の場合について,さらに場合分けを続けるとどうなるだろうか.

リンク

m1 = 2m2 の場合とm1 = 2m2+1 の場合に分ける.

  • n = 2m1+1 = 4m2+1 の場合,以下のように 3m2+1 となり,n より小さくなる.

 n = 4m2+1
 → 12m2+4
 → 6m2+2
 → 3m2+1


  • n = 2m1+1 = 4m2+3 の場合,以下のように 9m2+8 となり,n より大きくなる.

 n = 4m2+3
 → 12m2+10
 → 6m2+5
 → 18m2+16
 → 9m2+8


29の場合

29 までで,調べるべき場合は以下の38通りである.他の場合は,元の値より小さくなる.

n 結果
512*m+27 2187*m+121
512*m+283 6561*m+3644
512*m+155 2187*m+668
512*m+411 729*m+587
512*m+91 2187*m+395
512*m+347 729*m+496
512*m+251 2187*m+1079
512*m+507 729*m+724
512*m+71 729*m+103
512*m+327 2187*m+1403
512*m+167 2187*m+719
512*m+423 729*m+604
512*m+103 2187*m+445
512*m+359 6561*m+4616
512*m+231 2187*m+992
512*m+487 729*m+695
512*m+207 2187*m+890
512*m+463 729*m+661
512*m+47 2187*m+206
512*m+303 729*m+433
512*m+111 2187*m+479
512*m+367 729*m+524
512*m+239 6561*m+3077
512*m+495 2187*m+2119
512*m+31 2187*m+137
512*m+287 729*m+410
512*m+159 6561*m+2051
512*m+415 2187*m+1777
512*m+223 729*m+319
512*m+479 2187*m+2051
512*m+63 729*m+91
512*m+319 2187*m+1367
512*m+191 2187*m+820
512*m+447 6561*m+5741
512*m+127 6561*m+1640
512*m+383 2187*m+1640
512*m+255 6561*m+3280
512*m+511 19683*m+19682

大きくなる場合の数

n = 2k の時,調べるべき場合の数は以下の通り.

k 場合の数
1 1
2 1
3 2
4 3
5 4
6 8
7 13
8 19
9 38
10 64
11 128
12 226
13 367
14 734
15 1295
16 2114

プログラム

#!/usr/bin/perl
use strict;

my $p = shift;
my $max = 2**9;
if ($p) {
    $max = 2**$p;
}
&collatz(1, 0, 1, 0, 0);
exit 0;

sub collatz {
    my ($a0, $b0, $a, $b, $step) = @_;
    if ($a % 2 == 0 && $b % 2 == 0) {
	&collatz($a0, $b0, $a/2, $b/2, $step+1);
    } elsif ($a % 2 == 0 && $b % 2 == 1) {
	&collatz($a0, $b0, $a*3, $b*3+1, $step+1);
    } elsif ($a < $a0 || ($a == $a0 && $b < $b0)) {
	print "$a0*m+$b0 --> $a*m+$b\n";
    } elsif ($a0 >= $max) {
	print "$a0*m+$b0 --> $a*m+$b --> ?\n";
    } else {
	&collatz(2*$a0, $b0, 2*$a, $b, $step);
	&collatz(2*$a0, $a0+$b0, 2*$a, $a+$b, $step);
    }
}