回答
即使情況
讓我們爲簡單起見首先假設n
甚至,以後我們可以概括的功能。我們可以爲此使用遞歸。我們定義了一個幫助函數pal' :: Integer -> [String] -> [String]
。這裏的第二個參數是累加的反向字符串。所以一旦我們打0
,我們只需要發出一個單一的列表中包含的累積逆轉字符串,如:
pal' 0 r = [r]
鑑於但是我們仍然在迴文結構產生部分,左側因此,我們可以使用列表理解,如:
pal' k r = [ c : p | c <- ['a'..'z'], p <- pal' (k-1) (c:r) ]
所以我們遍歷[a..z]
併爲每個這樣的字符,我們對我們進行pal'
遞歸調用,我們需要生成一個附加k-1
字符,(c:r)
作爲反向字符串發射。此外,我們爲這些迴文產生c : p
。我們把這個選擇字符放在迴文前面。
所以現在的even_palindrome
功能產生甚至迴文,我們可以這樣寫:
evenpalindrome :: Integer -> [String]
evenpalindrome n = pal' (div n 2) []
where pal' 0 r = [r]
pal' k r = [ c : p | c <- ['a'..'z'], p <- pal' (k-1) (c:r) ]
出於測試目的,我設置的代碼'C <的範圍內挑選 - [「一」。 。'd'],但您可以將其設置爲您想要的任何範圍。
如果我們生成長度0,2和4迴文,我們得到:
*Main> evenpalindrome 0
[""]
*Main> evenpalindrome 2
["aa","bb","cc","dd"]
*Main> evenpalindrome 4
["aaaa","abba","acca","adda","baab","bbbb","bccb","bddb","caac","cbbc","cccc","cddc","daad","dbbd","dccd","dddd"]
所以這似乎工作。如果我們寫不過evenpalindrome 1
,它會在這個意義上的工作,將採取整數除法,並因此產生了長度爲0
奇數的情況下回文
現在的問題是我們有什麼以改變到讓它適用於奇數長度。有需要改變這裏兩件事情:
- 我們需要生成一個附加的性格,所以我們不應該使用
div n 2
,但div (n+1) 2
;和 - 最後生成的字符應該是而不是可以在相反的情況下重複。
因此,這意味着,我們應該先檢查n
模2(那一定是d
),然後改寫:
pal' 0 r = [drop (fromInteger d) r]
而且爲說,我們應該叫初始pal'
與pal' (div (n+1) 2) []
之前,所以現在廣義的版本是:
palindrome :: Integer -> [String]
palindrome n = pal' (div (n+1) 2) []
where pal' 0 r = [drop (fromInteger d) r]
pal' k r = [ c : p | c <- ['a'..'z'], p <- pal' (k-1) (c:r) ]
d = mod n 2
主要生產:
*Main> palindrome 1
["a","b","c","d"]
*Main> palindrome 2
["aa","bb","cc","dd"]
*Main> palindrome 3
["aaa","aba","aca","ada","bab","bbb","bcb","bdb","cac","cbc","ccc","cdc","dad","dbd","dcd","ddd"]
*Main> palindrome 4
["aaaa","abba","acca","adda","baab","bbbb","bccb","bddb","caac","cbbc","cccc","cddc","daad","dbbd","dccd","dddd"]
*Main> palindrome 5
["aaaaa","aabaa","aacaa","aadaa","ababa","abbba","abcba","abdba","acaca","acbca","accca","acdca","adada","adbda","adcda","addda","baaab","babab","bacab","badab","bbabb","bbbbb","bbcbb","bbdbb","bcacb","bcbcb","bcccb","bcdcb","bdadb","bdbdb","bdcdb","bdddb","caaac","cabac","cacac","cadac","cbabc","cbbbc","cbcbc","cbdbc","ccacc","ccbcc","ccccc","ccdcc","cdadc","cdbdc","cdcdc","cdddc","daaad","dabad","dacad","dadad","dbabd","dbbbd","dbcbd","dbdbd","dcacd","dcbcd","dcccd","dcdcd","ddadd","ddbdd","ddcdd","ddddd"]
存儲器結構
約構建使用遞歸這種方式反向部分A好處,就是所有的迴文的第二半被更有效地存儲。鑑於我們產生了`[「A」 ..「B」]範圍內,最終名單長度爲5迴文(完整的評估後),會看起來像:
+---+ | o--- 'a' -- 'a' -> 'a' -\ +---+ > 'a' -\ | o--> 'a' -> 'a' -> 'b' -/ \ +---+ > 'a' | o--> 'a' -> 'b' -> 'a' -\ / +---+ > 'b' -/ | o--> 'a' -> 'b' -> 'b' -/ +---+ | o--> 'b' -> 'a' -> 'a' -\ +---+ > 'a' -\ | o--> 'b' -> 'a' -> 'b' -/ \ +---+ > 'b' | o--> 'b' -> 'b' -> 'a' -\ / +---+ > 'b' -/ | o--> 'b' -> 'b' -> 'b' -/ +---+
迴文是一個字符串,其中最後一個一半的字符與前半部分字符相反。因此,一個簡單的算法將生成長度爲n/2
的所有字符串,然後將每個字符串的反轉附加到末尾。對於奇數長度的迴文,我們可以放棄字符串後半部分的第一個字符,並且當我們找到n/2
時確保四捨五入。
現在棘手的部分是產生長度爲n/2
的所有可能的字符串。我們需要爲字符串中的每個字符從['a'..'z']
中選擇一個字符,並在Haskell中選擇lists can represent non-determinism。因此,我們所需要做的就是使用replicateM
,它會創建每個字符串,其中每個字符都是從字母表中非確定性地選擇的。
附註中,任何長度n
可能的迴文數可能以指數速率增加。使用Integer
作爲輸入是矯枉過正的,因爲Int
的最大值已經超過9個百分點。
下面就來實現完整的算法的一種方法:
palindrome :: Int -> [String]
palindrome n
| n < 0 = []
| even n = map (\front -> front ++ reverse front) fronts
| odd n = map (\front -> front ++ tail (reverse front)) fronts
where fronts = replicateM (div (n + 1) 2) ['a'..'z']
- 1. 如何從所有排列生成所有可能的組合?
- 2. 如何有效地從圖形生成所有可能的生成樹
- 3. 生成所有可能的替換
- 4. 生成所有可能的組合
- 5. 生成所有可能的配對
- 6. 生成所有可能的分割
- 7. 爲什麼回溯無法生成所有可能的組合?
- 8. 代碼,以生成所有可能的組合
- 9. 生成所有可能的n字符密碼
- 10. Haskell列表的所有可能分區
- 11. 使用點生成所有可能性
- 12. 在Perl中,如何生成列表的所有可能組合?
- 13. 如何在python中生成所有可能的排列?
- 14. 如何按以下順序生成所有可能的總和?
- 15. 如何在SQL中生成所有可能的數據組合?
- 16. PHP:如何生成數組中所有可能的值組合?
- 17. 如何在c#中生成所有可能的3字符串?
- 18. 如何使用urandom生成所有可能的base64字符?
- 19. 如何在python中生成所有可能的字符串?
- 20. 如何生成所有可能的Torrent信息散列?
- 21. 是否有可能生產獨立的haskell可執行文件
- 22. VB.NET:生成的文件中的所有可能的話
- 23. 如何在Haskell中列出所有可能的替換項目?
- 24. 從txt文件生成所有可能的試卷
- 25. 如何讀取Haskell中目錄的所有文件
- 26. Haskell/GHC性能的`任何'/`所有`
- 27. Haskell編譯器的代碼生成
- 28. 在具有所有可能性的字符之間生成點
- 29. 從集合中生成所有可能的有序子集
- 30. 如何爲其他目錄中的所有C++文件生成標籤文件?
那你試試?這看起來像一個問題轉儲。 – chi
你有什麼嘗試過自己? –
練習的哪一部分是你遇到的麻煩? – amalloy