2009/05/14

[scheme]またもやcollatz(角谷の予想)

WS0792
問題の概要は、「任意の0でない自然数 n をとり、
  • n が偶数の場合、n を 2 で割る
  • n が奇数の場合、n に 3 をかけて 1 を足す
という操作を繰り返すと、有限回で 1 に到達する」という主張である

おもしろい問題ですよね。この問題が好きで何度かやってます。
あまりしっくり来てなかったのでもう一度Schemeで書いてみました。(それでもまだなんだか・・・)

コード。ちょっと右よりなりますが気になるが・・・
(define collatz
  (lambda (n)
    (letrec
        ((iter (lambda (x col)
                 (append col
                         (cons x
                               (cond
                                ((= x 1) '())
                                ((odd? x)
                                 (iter (+ (* x 3) 1) col))
                                ((even? x)
                                 (iter (/ x 2) col))
                                (else (list #f))))))))
      (iter n '()))))

実行結果。
(collatz 100)
;; = (100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)

(collatz 1000)
;; =>(1000 500 250 125 376 188 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)

プログラミングGauche

2 件のコメント:

  1. こんなのはどうでしょう?

    (define collatz-list
      (lambda (n)
        (do ([n n (if [even? n] (/ n 2) (+ (* n 3) 1))]
              [ans '() (cons n ans)])
             ([= n 1] (reverse (cons 1 ans))))))

    返信削除
  2. catbird
    ある数が奇数なら、3を掛けて1を足す。ある数が偶数なら2で割る。計算結果が奇数なら、また3を掛けて1を足す。偶数なら、また2で割る。その計算を続けて行くと、ありとあらゆる数から始めても、最後は全て4→2→1→4→2→1の繰り返しになるのではないかと、コラッツは予想しました。
    計算値が次第に小さくなって行くと、必ず最終的には4→2→1の繰り返しになってしまいます。従って、計算値が、無限に大きくなって行く様な始まりの数があれば、必ずしも4→2→1の繰り返しにはならないことが証明されます。
    最初の数が奇数(X)の場合、3を掛けて1を足すと、X(奇数)×3(必ず奇数)+1=Y(必ず偶数)となります。従って、Yは偶数なので、次の計算は必ず割る2となります。よって、幾ら計算値をどんどん大きくしていこうとしても、X(奇数)×3+1=Y(偶数)→Y(偶数)÷2=Z(奇数)、Z(奇数)×3+1=O(偶数)、O(偶数)÷2=P(奇数)と、奇数→偶数の繰り返し以上には、計算値は大きくなっては行かないことが分かります。つまり、(ある奇数×3+1)÷2の計算結果が、必ず奇数であれば、計算値は無限に大きくなって行き、必ずしも最後は4→2→1の繰り返しとはならないことが証明されます。
     では、その様な始まりの奇数Xがあるか否か、エクセルを使って検証してみましょう。列Aに上の行から順番に、1・3・5・7・9・11・・・・と奇数を入力してください。列Bに上から順に「=(A1×3+1)/2」「=(A2×3+1)/2」「=(A3×3+1)/2」・・・・と、左のA列の奇数を3倍して1を足し2で割る数式を入力します。列Cに上から順に「=(B1×3+1)/2」「=(B2×3+1)/2」「=(B3×3+1)/2」・・・・B列のセルの計算値を、更に3倍して1を足し2で割る数式を入力します。同様の式をD列・E列・F列・・・に入力して行き、どんどん3倍して1を足し2で割る計算を行います。
    この結果、全ての列の計算値が奇数となるものがあれば、計算値は無限に大きくなって行きます。そこで、各列において奇数が出現する様子を見てみましょう。B列では、上から2回に1度5・11・17・23・29・35・・と奇数が現れます。C列では、4回に1度17・35・53・71・89・107・125・・・と奇数が現れます。D列では8回に1度53・107・161・215・269・323・・・と奇数が現れます。E列では、16回に1度161・323・485・647・809・・・と奇数が現れます。F列では、32回に1度485・971・1457・1943・2429・2915・・・と奇数が現れます。G列では、64回に1度1457・2915・4373・5831・7289・・・・と奇数が現れます。以後同様に、H列では128回に1度、I列では256回に1度、J列では512回に1度奇数が現れます。
    ここまでの計算で、奇数が連続するのは、512行目の1,023・1,535・2,303・3,455・5,183・7,775・11,663・17,495・26,243・39,365の1つです。3倍して1を足し2で割る計算をn回行えば、全ての計算値が奇数になるものは、2のn乗分の1に減少していきます。この事実は、簡単に証明出来るでしょう。
    従って、計算を行えば行う程、計算値が奇数の連続になるものは1/2・1/4・1/8・1/16・1/32・・どんどん半分に減少していきます。しかし、無限の数の中では、2のn乗分の1は決して0にはなりません。3倍して1を足し2で割る計算をn回する場合、1から数えて2のn乗番目の奇数(又はその倍数番目の奇数)から始めると、n回の計算結果全てが奇数となります。計算値は大きくなる一方で、4→2→1の繰り返しにはなりません。
    有限の数の範囲内では、計算値がその範囲を超えるまで計算を行っていけば、奇数が連続しなくなります。しかし、無限の数の中では、常に先に2のn乗番目の奇数があります。それは(1+2×2のn乗)で表現される数値で、尽きることはありません。そのnを∞にした数値から始めれば、無限に計算を繰り返しても4→2→1の繰り返しにはなりません。
    少なくとも1組は、永遠に奇数が連続し数値が大きくなっていく組み合わせが存在します。従って、コラッツの予想は残念ながら誤っています。

    返信削除