最近做Project Euler的第41問時學到了不少東西,數論、Mathematica⋯⋯
題目是這樣的:如果一個n位數的各位數字中恰好1到n各出現了一次,那麼就說這個數pandigital。比如,2143就是一個4位的pandigital質數。請問是否存在最大的pandigital質數?
我不管三七二十一,用Ruby暴力搜索了好一會,終於獲得了論壇的入場券。Project Euler問題後面的討論是一筆寶貴的財富,你總能找到一些耀眼的思想火花。比如,我就看到了某哥們寫到:
以前我總認爲Mathematica不過是把圓括號變成方括號的Lisp,語法應該不難,但現在我懵了,這是什麼寫法。我不喜歡Mathematica,主要是因爲我不喜歡那一大砣看似毫無聯繫的函數。但現在,我決定好好地學學Mathematica。
Mathematica繼承了Lisp簡約的語法和統一的形式,雖然在list的實現方式上略有不同(Mathematica是用數組而非鏈接表來實現list的)。
- Mathematica中一切都皆爲表達式(其實也好理解,Lisp程序不就是由lisp構成的嗎)
- 模式匹配和代入規則
a->b
這句話的意思是,凡遇到a,則替換爲b。如果要應用規則,則需要用/.來應用規則。
Mathematica計算的核心是一個循環:它根據表達式不斷地套用規則,直到結果不再變化爲止。
I Mathematica中的四種括號:
- 圓括號( ),用於改變操作的結合順序;
- 花括號{ },專用於列表;
- 單方括號[ ],標識表達式的域;
- 雙方括號[[ ]],Part函數的簡寫,作用同下標。
II 純函數,就是Mathematica中的Λ-算子
Function[x, body]等價於body&
這裏先介紹四個記號用於純函數中的特殊記號:
- #n,表示第n個參數;
- #,表示第一個參數,即#1;
- ##,表示所有參數;
- ##n,表示第n個及之後的參數。
III 一些語言習慣
函數都是平等的,但總有些函數更平等,因爲它們應用得更廣泛。本着少寫代碼的原則,Wolfram爲這些高階函數制定了一些“黑話”:
IV 最後介紹一下Mathematica中函數的幾種作用方式:
現在可以看看我們那位美國仁兄用了多少奇技淫巧了。他動用了函數的四種作用方式、Map的簡寫等來隱藏其背後蠻力搜索的直白算法^_^
最後,說說那個不起眼的7。我們要找一個最大的pandigital質數,但其實只要搜索1到987654321就行了。但987654321畢竟也是個很大的數,但注意到我們要考慮的只是1到n的輪換,而且還是質數,所以沒必要搜索987654321個數。另外,我們注意到
1+……+9 = 45,
1+……+8 = 36,
1+……+7 = 28,
1+……+6 = 21,
1+……+5 = 15,
1+……+4 = 10,
1+……+3 = 6,
1+……+2 = 3,
(1就不用考慮了,它連質數都不算)
除了1到4和1到7,其他都能被3整除(說明這些組合都是3的倍數)
其實,只需考慮1到7的情況,誰讓它大呢!
Fold[Plus, 0, Range[1, 9]]
這裏又要多一句,爲什麼一個數的各位數相加,如果其和能被3整除,則其數能被3整除。
顯而易見, 只要(an + …… + a2 + a1)能被3整除,那麼 an……a2a1也能被3整除。
P.S. 7652413