2011-06-30 90 views

回答

9

你寫這個問題的方法,它不會終止,因此如最終1和4 2等之間,交流的(所有的遞歸描述必須最終走出低谷的地方,和你的不包括案件在n=1)。

這工作:

ClearAll[collatz]; 
collatz[1] = 1; 
collatz[n_ /; EvenQ[n]] := collatz[n/2] 
collatz[n_ /; OddQ[n]] := collatz[3 n + 1] 

雖然它不給中間結果的列表。一個方便的方式,讓他們爲

ClearAll[collatz]; 
collatz[1] = 1; 
collatz[n_ /; EvenQ[n]] := (Sow[n]; collatz[n/2]) 
collatz[n_ /; OddQ[n]] := (Sow[n]; collatz[3 n + 1]) 
runcoll[n_] := [email protected]@Reap[collatz[n]] 

runcoll[115] 
(* 
-> {115, 346, 173, 520, 260, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56, 
28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1} 
*) 

colSeq[x_] := NestWhileList[ 
Which[ 
EvenQ[#], #/2, 
True, 3*# + 1] &, 
x, 
# \[NotEqual] 1 &] 

使得例如

colSeq[115] 
(* 
-> {115, 346, 173, 520, 260, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56, 
28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1} 
*) 

順便說最快的方法,我能想出(我想我需要它一些項目歐拉問題)有點像

[email protected]; 
collatz[1] := {1} 
collatz[n_] := collatz[n] = If[ 
    EvenQ[n] && n > 0, 
    {n}~Join~collatz[n/2], 
    {n}~Join~collatz[3*n + 1]] 

比較:

colSeq /@ Range[20000]; // Timing 
(* 
-> {6.87047, Null} 
*) 

Block[{$RecursionLimit = \[Infinity]}, 
    collatz /@ Range[20000];] // Timing 
(* 
-> {0.54443, Null} 
*) 

(我們需要增加的遞歸限制得到這個正確運行)。

+0

消化所有這一切需要我花些時間 - 謝謝! –

+0

@ M-V我認爲@Thies提供的答案更符合你最初嘗試的精神(而且他的解決方案正好與上述一致,即爲遞歸提供了一個基礎案例)。但當然,我認爲我上面提出的方法更容易理解和更靈活(我更喜歡母豬/自己的組合,因此經常使用它) – acl

+0

+1。我還在這裏討論了這個問題:http://www.mathprogramming-intro.org/book/node515.html,我的最終解決方案與您的解決方案非常相似。 –

7

你得到了正確的遞歸情況,但是你沒有基本情況來終止導致無限遞歸的遞歸(或者直到Mathematica達到模式替換限制)。如果停止當你到達1,它按預期工作:

In[1]:= A = {1,2,3,4} 
Out[1]= {1,2,3,4} 

In[2]:= A //. {x_?EvenQ /; x>1 -> x/2, x_?OddQ /; x>1 -> 3 x+1} 
Out[2]= {1,1,1,1} 
4

在文件中心,the section about writing packages與在Collat​​z功能的例子說明。

+1

+1。正如我在這裏討論的:http://www.mathprogramming-intro.org/book/node515.html,您鏈接到的解決方案(可能來自Roman Maeder的書)在概念上很清晰,但在性能方面並不理想。 –