2013-11-21 40 views
1

我下面這個教程標準ML:http://homepages.inf.ed.ac.uk/stg/NOTES/node2.html,我過這個問題就來了:標準ML semifactorial使用減少函數

的正整數n的semifactorial是1×3×5×.. 。如果n是奇數,則n×n,如果n是偶數,則爲2×4×6×...×n。使用reduce函數來定義一個計算半值的半方差函數。

減少被定義爲:

fun reduce (g, e, m, n, f) = 
    if m > n then e else g (reduce (g, e, m, n-1, f), f n); 

我已經花了幾個小時的問題亂搞,並不能找到一個滿意的答案,不需要改變減少功能。這個問題就變得很容易,如果你重新定義爲減少:

fun reduce' (g, e, m, n, f) = 
    if m > n then e else g (reduce'(g, e, m, n-2, f), f n); 

隨着作爲最終的解決方案:

fun semifactorial n = reduce'(fn (x,y) => x * y, 1, 1, n, fn x=>x); 

這是我覺得作者是想要知道的,但我不知道。無論如何要解決這個問題而不改變reduce的定義嗎?我在想,有一些非常明顯的功能方法可以做到這一點,但我看不出如何減少兩個而不是一個(我的直覺說,答案在於爲g和f選擇正確的函數值)。

回答

1

你非常接近。答案是選擇正確的f。特別是,f可以取決於n

fun semifactorial n = reduce(fn (x,y) => x * y, 1, 1, 
          n, fn x => if x mod 2 = n mod 2 then x else 1) 

應該工作。

或者,有點更乾淨:

fun foo n x = if (x + n) mod 2 = 0 then x else 1 
fun semifactorial n = reduce((op*), 1, 1, n, foo n x) 

雖然這種形式確實有潛在的失敗與nx特別大的值,如果你的ML實現不支持任意精度的整數。

1

您可以使用f來決定是否乘以索引。如果平價相同,它只應該乘以它們。

fun sfact n = reduce(op*, 1, 1, n, fn k => if n mod 2 + k mod 2 = 1 then 1 else k); 
+0

你們大約在同一時間回答 - 對不起,我不能接受這兩個答案! –