2016-12-29 26 views
1

我正在寫一個函數來確定一個數是否是迴文。如何將字符串解構爲第一個,中間和最後一個?

我想在第一種情況下做的是將字符串解構爲第一個字符,中間的所有字符和最後一個字符。我所做的是檢查第一個字符是否與最後一個字符相等,如果是,則繼續檢查中間字符。

我有什麼是在下面,但編譯時會產生類型錯誤。

numberIsPalindrome :: Int -> Bool 
numberIsPalindrome n = 
    case nString of 
    (x:xs:y) -> (x == y) && numberIsPalindrome xs 
    (x:y) -> x == y 
    x -> True 
    where nString = show n 
+0

列表鏈接列表(不陣列) ,因此訪問最後一個操作是昂貴的,不能通過模式匹配來執行。可以使用'last'庫函數,但是它會很慢。如下所示,反轉列表並檢查相等性會更有效率,也更簡單。 – chi

回答

3

使用String表示被欺騙......

不是真的,但這是更多的樂趣:

import Data.List 

palindrome n = list == reverse list where 
    list = unfoldr f n 
    f 0 = Nothing 
    f k = Just (k `mod` 10, k `div` 10) 

它所做的是創建一個數字的數字列表(unfoldr對於這樣的任務非常有用),然後比較是否列表保持不變。

你試過的有幾個問題,例如:您錯過了從數字到String(這只是Haskell中的Char列表)的轉換,並且列表的工作與您嘗試的完全不同:將它們更多地視爲堆棧,通常只在一端運行。

也就是說,列表中有一個initlast函數,這些函數允許您從列表的「外部」元素到內部元素的工作。一個天真的(且效率低下)實施看起來是這樣的:

palindrome n = f (show n) where 
    f [] = True 
    f [_] = True 
    f (x : xs) = (x == last xs) && (f (init xs)) 

但這僅僅是出於演示的目的,在現實生活的不使用這樣的代碼......

+0

一些可能的改進:1。追蹤列表的長度,以便知道何時停止比較。 2.使用'quotRem'而不是'div'和'mod'。 3.如果參數不是零而是最低有效數字是零,立即返回false。 4.從列表切換到矢量以減少分配和指針追逐。 – dfeuer

1

你可能想定義是

numberIsPalindrome :: Int -> Bool 
numberIsPalindrome num = let str = show num 
         in (str == reverse str) 
+4

如果你對OP的陳述策略表示「是」,那將會很不錯,幫助他們,而不是用你自己的想法替換他們的想法 – luqui

1

(:)操作被稱爲cons,它預先考慮項目清單: 1:2:[]結果[1,2]

你得到一個類型錯誤,因爲您試圖比較第一個參數Char和最後一個參數[a]

如果你真的想比較第一個和最後一個,你會使用headlast

但你更好的使用taktoa提出的解決方案:

numberIsPalindrome :: Int -> Bool 
numberIsPalindrome num = 
    numberString == reverse numberString 
    where numberString = show num 
+0

注意,如果你在每次迭代中調用last,算法將是O(n^2)而不是O(n),因爲'last'是O(n)。 – taktoa

相關問題