作者LPH66 (かつて交わした約束)
看板Mathematica
標題Re: [心得] 鉍鎝氫--可拆成元素符號的英文單字
時間Thu Jan 5 01:55:02 2017
※ 引述《jurian0101 (Hysterisis)》之銘言:
: 因為元素符號有一或兩個字母,強烈在引誘我利用費氏數列解題
: 'bitch':> b-i-t-c-h, b-it-c-h, b-it-ch, b-i-tc-h,
: b-i-t-ch, bi-t-c-h, bi-tc-h, bi-t-ch
: 拆成這恰好八種,分別檢查是否子字串屬於元素符號即可
: 這八種的邏輯等於「下五階樓梯,一次可走一或兩階」的走法 Fibonacci[5]=8
: --元素名可以從 MMA 的化學資料集取得
: ElementData[#, "Abbreviation"] & /@ ElementData[]
: 再自己加上最新最潮的四個新元素 "Nh", "Mc", "Ts", "Og"。
: 後來我發現這樣簡潔的暴力法對於 WordList["KnownWords"] 永遠也跑不出來
: 原因是這個字集裡含有 acrylonitrile-butadiene-styrene (ABS塑膠的全名)
: 這種長字...qq 真是暴力的單字 (很顯然它以 -ene 結尾,不能拆)
: 而 Fibonacci[29] = 514229 等於要查遍有半百萬個元素的清單,會爆記憶體。
其實這個方向下去只差一步了
既然是費氏數列, 那就能利用「下一個值等於前兩個值的和」這資訊
於是:
checkSpellCount[""] = 1
checkSpellCount[s_] :=
checkSpellCount[s] =
If[StringLength[s] >= 2 && MemberQ[elem, StringTake[s, -2]],
checkSpellCount[StringTake[s, {1, -3}]], 0] +
If[StringLength[s] >= 1 && MemberQ[elem, StringTake[s, -1]],
checkSpellCount[StringTake[s, {1, -2}]], 0]
是的, 這是個有點無恥的 Memoization XD
elem 是已經轉成小寫的元素列表
計算邏輯本身其實看上面程式就很清楚了
由於這是全域筆記, 不僅同一字內可以共享, 有共同 prefix 的字的組法數也能共享
(所以才說有點無恥www)
用你那行 GatherBy 的寫法計時, 在我的電腦上只要 3.5~4 秒就可以完成 KnownWords
之後用 Save 把所存的定義給倒出來看的結果一共有約十七萬四千筆資料
記憶體用量看起來也並不是很大
--
然後根據這份 Save 的存檔, ABS 塑膠那個單字是在碰到 -st- 時死掉的
它的結尾是 -rene = Re 錸 + Ne 氖
--
有人喜歡邊
玩遊戲邊
上逼;
也有人喜歡邊
聽歌邊
打字。
但是,我有個請求,
選字的時候請
專心好嗎?
-- 改編自「古 火田 任三郎」之開場白
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 180.177.29.238
※ 文章網址: https://www.ptt.cc/bbs/Mathematica/M.1483552505.A.BCC.html
※ 編輯: LPH66 (180.177.29.238), 01/05/2017 03:40:02
推 jurian0101: 總是會忘記有錸這個元素qq 01/05 09:47
推 jurian0101: 哦!懂了。所謂全域記憶就是簡化所有重複做工的方法, 01/05 09:50
→ jurian0101: 教會我從「什麼是程式一做再做的計算」方向考慮優化。 01/05 09:51
→ jurian0101: 3Q太感謝。 01/05 09:52
→ LPH66: 其實這東西的傳統解法是動態規劃 Dynamic Programming 01/06 09:35
→ LPH66: 只是在 MMA 上寫 DP 稍微麻煩了點, 不如筆記法直覺 01/06 09:35
推 ntust661: XD 04/22 19:10