[心得] EIORU tree
這篇文章靈感是EIORU大在帕索板提出的問題,每次EIORU提出的問題都蠻適合練習
Mathematica或其他程式之解題技巧 @@
作者: EIORU () 看板: puzzle
標題: [問題] 樹幹 樹枝 果實
有一棵 樹 種進土裡後 長出了樹幹 │
╲╱ <- 左/右 樹枝 往前/後的樹枝->∣ ╲╱
第一天早上 長出了樹枝 │ <- 樹幹 ∣ ∣ <-樹幹 ∣ ∣
╲╱ ╲╱
第一天晚上 樹枝上長出了樹幹 │ ∣
原本的樹枝變成了樹幹
第二天 在左邊的樹幹 往 前/後 長出了樹枝 , 在右邊的樹幹 往 左/右 長出了樹枝
第二天晚上 樹枝上長出了樹幹 原本的樹枝變成了樹幹
第三天 在前方的樹幹 往 前/後 長出了樹枝 , 在後方的樹幹 往 左/右 長出了樹枝
在左邊的樹幹 往 前/後 長出了樹枝 , 在右邊的樹幹 往 左/右 長出了樹枝
第三天晚上 樹枝上長出了樹幹 原本的樹枝變成了樹幹
第四天之後 會重複有顏色的行為
如果早上兩枝樹枝 碰到了一起 在晚上就會結出了果實 而不會長出樹幹
PS. 在頂端的樹幹才有生長能力 樹枝長度 = √2 , 樹幹長度 = 1
樹枝生長永遠和地面呈45度 樹幹生長永遠和地面呈90度
Q1. 第10天早上 會長出幾枝樹枝?
Q2. 從第一天開始到第幾天晚上能採收到第100顆果實?
題外話 ... OEIS 沒有樹枝數量的數列 XD
... 畫到一半感覺像 某 立體結構的 聚合物
= = = = 分析 by jurian0101= = = =
O代表原枝幹 WASD代表前左後右 (XD) 上一天的以小寫wasd表示。
Q代表果子,一個位置結了果實就不會再往上長,第二天就忽視他。
以下是轉變法則,用字代表就不會忘了是什麼朝向的枝幹,也可以方便繪圖(設定坐標)
W W
w AsD a AdD
S S
假設要算枝幹總長度的話(原題沒有但可以算) 就是一層層加上去,正是每一層中
__ __
W=A=S=D = 1+V 2 ,Q = 2V 2 ,初始枝幹O=1 這樣
= = = = 手動實作 = = = =
第一天 (第0層)
O 長度1
第二天
W __
o 長度 2* (1+V 2 )
S
第三天
W
w 以下省略長度,一樣意思就好
S
AsD
第四天 果子 +=1
W
w
S
QsD
aAdD
S
第五天 果子 +=2
W
w
S
AsD
QsD
aAdD
AsQ
第六天 果子 += 2
W
w
S
QsD
aAdD
S QdD
W aAdD
a S
S
........依此類推,是個二維cellular automata QQ
= = = = 最後是解答與Mathematica碼 = = = =
先形容一下畫出來這顆神奇的樹,
"分層畫"的輸出可以看到,每層中同一側形成無間隙的枝幹網格。果子也是交替排列。
這個構造姑且叫做基底膜好了@@
相對方向形成兩種排列形式 1.cluster: 形狀不一的離散團塊,似乎彼此長像是一樣的
或 2. escalator,一路連回基底膜的長短不一的纖維狀構造
然後就是整體了,窩的天啊它長的超像 Sierpinski triangle (轉到側面) 相異點是
這個...就叫他 EIORU XD triangle 好了...是由多於而非原本1:2的挖空比例構成的
/\
/__\ <-- 很差的示意圖
/\/\/\
以下一是傷眼Mathematica函數,速度效率很差,但計較這點可能要重寫過就...算了
Clear[枝幹];枝幹[直][0]={{0,0}->"W"};
枝幹[直][n_]/;n>0:=
枝幹[直][n]=
(枝幹[斜][n]=Sort[枝幹[直][n-1]/.rule1])//.
{p___,q_Rule,r___,s_Rule,t___}/;q[[1]]==s[[1]]:>{p,q[[1]]->"Q",t}
(*迭代規則。到下一層Q=果子須移除,是故有Q一行*)
rule1={
(*W*)({x_,y_}->"W"):>Sequence[{x,y+1}->"W",{x,y-1}->"S"],
(*A*)({x_,y_}->"A"):>Sequence[{x,y+1}->"W",{x,y-1}->"S"],
(*S*)({x_,y_}->"S"):>Sequence[{x-1,y}->"A",{x+1,y}->"D"],
(*D*)({x_,y_}->"D"):>Sequence[{x-1,y}->"A",{x+1,y}->"D"],
(*Q*)({_,_}->"Q")->Sequence[]
};
(*把第i層枝幹data轉換成繪圖物件。枝幹[直][i]裡包含Q=果子,是往上畫。枝幹[斜
][i]不包含Q,是往下畫*)
Clear[轉換];
轉換[i_]:=Join[{Hue[Mod[i,10]/10]},
枝幹[斜][i]/.x:{_Integer,_}:>Append[x,2i-1]/.rule2,
枝幹[直][i]/.x:{_Integer,_}:>Append[x,2i-1]/.rule3
]
(*斜枝幹變斜線*)
rule2={
(*W*)({x_,y_,z_}->"W"):>Line[{{x,y,z},{x,y-1,z-1}}],
(*A*)({x_,y_,z_}->"A"):>Line[{{x,y,z},{x+1,y,z-1}}],
(*S*)({x_,y_,z_}->"S"):>Line[{{x,y,z},{x,y+1,z-1}}],
(*D*)({x_,y_,z_}->"D"):>Line[{{x,y,z},{x-1,y,z-1}}]
};
(*直枝幹或果子*)
rule3={
(*Q*)({x_,y_,z_}->"Q"):>{color=Black,PointSize[0.03],Point[{x,y,z}]},
(*else*) ({x_,y_,z_}->Except["Q"]):>Line[{{x,y,z},{x,y,z+1}}]
};
= = = = = = =
(*起始!,50層在我電腦跑很慢,約5分鐘*)(*不知道這麼慢的原因是...*)
枝幹[直][50];
= = = = = = =
(*輸出測試*)
枝幹[斜][5]
枝幹[直][10]
= = = = = = =
(*單層graphics測試*)
Graphics3D[轉換[10]]
= = = = = = =
(*多層graphics,視角是正上方,以看清分布*)
Table[Graphics3D[轉換[i], ViewPoint -> Top, BoxStyle -> Dashed], {i, 1,
50(*層數*)}]
= = = = = = =
(*重頭戲!! 大融合繪圖。果子大小為手動調整,0是看不見*)
Graphics3D[
Flatten@Table[轉換[i], {i, 1, 50(*層數*)}] /.
PointSize[_] -> PointSize[0(*大小*)], ViewPoint -> Top,
BoxStyle -> Dashed]
= = = = = = = = =
(*第i層的果實計數*)
c=Table[Count[枝幹[直][i],"Q",Infinity],{i,1,50}]
(*到第n天總共果實計數*)
Accumulate[c]
(*斜枝幹計數*)
Table[Length@枝幹[斜][i],{i,1,50}]
(*直枝幹計數,含果子,自行扣除*)
Table[Length@枝幹[直][i],{i,1,50}]
= = =全文完的分隔線= = =
※ 編輯: jurian0101 來自: 140.112.213.88 (07/18 18:40)
→
07/18 18:43, , 1F
07/18 18:43, 1F
→
07/18 18:43, , 2F
07/18 18:43, 2F
Mathematica 近期熱門文章
PTT數位生活區 即時熱門文章
0
18