challenge コラッツ・角谷の問題

任意の数nを与えたときに
・nが偶数ならば2で割る (n=n/2)
・nが奇数ならば3倍して1を足す (n = 3*n+1)
を繰り返すと、いづれは1になる。というものがあります。

数値計算の上ではかなりの数まで成り立つことが知られています。
(すべての数について成り立つかは不明)
参考リンク先参照

ある任意の数nがコラッツ・角谷の問題で1になるまでのステップ数をf(n)とします。
1~2^20までの数でf(n)を求めて、f(n)が最大になるときのnとf(n)を表示してください。

たとえばn=9だと次のような数列をたどって、19ステップで1になります。
9->28->14->7->22->11->34->17->52->26->13->40->20->10->5->16->8->4->2->1
つまりf(9)=19です。

また、最大を求めた際の実行時間と環境を書いてください。

Posted feedbacks - Batchfile

バッチで書いてみました。

速度に難があるため、1 ~ 2^12までの範囲でしか確認できていませんが、一応投稿します。

実行時間の計測には「実行時間の測定」で投稿したものを使用しています。

  e.g.
    実行環境 : Pentium M (1.6GHz), 768MB RAM
    実行結果 : f(3711) = 237
    実行時間 : 450050 (ms)

最初は以下のようにcallを使用して再帰的に書いていたのですが、速度を考慮してgotoを
利用したループに書き換えました。

  e.g.
    :collatz
      if %1 leq 1 goto :EOF
      set /a m=%1%%2
      if %m% equ 0 (set /a n=%1/2) else (set /a n=3*%1+1)
      call :collatz %n%
    goto :EOF

ただそれでも2^20まで実行した場合 1日では終わらないので、全く異なるロジックを編み
出す以外、手詰まりとなってしまいました。

# おそらく、遅延環境変数展開を利用して書き換えたくらいでは焼け石に水でしょう。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@echo off
  setlocal
    set s_=0
    set i_=0
    set /a "i=1<<12"

    for /l %%i in (1,1,%i%) do call :collatz %%i

    echo f(%i_%) = %s_%
  endlocal
goto :EOF

:collatz
  set n=%1
  set s=0

  :loop
    if %n% leq 1 goto compare
    set /a m=%n%%%2
    if %m% equ 0 (set /a n/=2) else (set /a n=3*%n%+1)
    set /a s+=1
  goto loop

  :compare
    if %s% leq %s_% goto :EOF
    set s_=%s%
    set i_=%1
goto :EOF

Index

Feed

Other

Link

Pathtraq

loading...