簡體   English   中英

Haskell整數奇數位檢查器

[英]Haskell Integer Odd Digits Checker

我似乎陷入了一個問題,不知道如何處理它或我當前的代碼做錯了什么。

我必須編寫一個名為oddDigits的函數,它接受一個整數參數並返回一個布爾結果。 當且僅當參數是具有奇數位數的正整數時,它應該返回True。 如果參數為零或負數,則函數應該以錯誤消息停止。

此外,無法將參數轉換為字符串。 必須使用遞歸。 我感覺每個數字可以遞歸地存儲在列表中,然后列表的長度可以確定答案。

到目前為止,我有這個:

oddDigits :: Integer -> Bool 

lst = [] 

oddDigits x 
    | (x < 0) || (x == 0) = error 
    | x `mod` 10 ++ lst ++ oddDigits(x `div` 10) 
    | length(lst) `mod` 2 /= 0 = True
    | otherwise = False 

對不起,如果代碼看起來很糟糕。 我是Haskell的新手,還在學習。 我究竟做錯了什么,我怎么能糾正它?

首先,這看起來很奇怪。 或許你做錯了就是要考慮這個問題......

XKCD維基百科打印機

但是如果你堅持下去,你想知道一個奇數位數的整數的屬性......哦。 有很多可以改進的地方。 首先, (x < 0) || (x == 0) (x < 0) || (x == 0)不需要括號 - <== (中綴4)綁定比||更緊密 如果您對此不確定,可以隨時詢問GHCi:

Prelude> :i ==
class Eq a where
  (==) :: a -> a -> Bool
  ...
    -- Defined in ‘GHC.Classes’
infix 4 ==
Prelude> :i ||
(||) :: Bool -> Bool -> Bool    -- Defined in ‘GHC.Classes’
infixr 2 ||

但在這里你不需要|| 無論如何,因為有一個小於或等於的專用運算符。 因此你可以寫

oddDigits x 
  | x <= 0  = error "bla bla"
  | ...

然后, 可以將數字“轉換”為字符串。 轉換為字符串通常是一個非常令人討厭的事情,因為它會拋出窗口中的所有結構,類型檢查等; 但“數字位數”基本上字符串的屬性(十進制擴展),而不是數字本身,因此對於此特定任務而言,這並非完全不可見。 這可行:

oddDigits x 
 | x <= 0                      = error "blearg"
 | length (show x)`mod`2 /= 0  = True
 | otherwise                   = False 

然而,這是一個多余的冗余部門。 你正在檢查某些東西是否為True ,然后給出True作為結果......為什么不把它放在一個子句中:

oddDigits x 
 | x <= 0     = error "blearg"
 | otherwise  = length (show x)`mod`2 /= 0

這可能實際上是最好的實現。

對於任何正確 ,明智的任務,我不建議去字符串路線。 遞歸更好。 這是它的樣子:

oddDigits 1 = True
oddDigits x 
 | x <= 0     = error "blearg"
 | otherwise  = not . oddDigits $ x`div`10

您轉換為數字列表,然后查找列表長度的一般方法沒有任何問題。 真正出錯的地方是試圖把所有東西塞進一個功能。 正如您第一手發現的那樣,它使調試變得非常困難。 功能編程最適合非常小的功能。

如果你將整數轉換為數字列表的責任分開,使用像這個答案digs函數,你的算法的其余部分簡化為:

oddDigits x | x <= 0 = error
oddDigits x = odd . length $ digs x

leftaroundabout的最終答案是非常好的,但它對2,3和23這樣的數字失敗了。這是一個修復。

oddDigits x 
  | x <= 0     = error "blearg"
  | x < 10     = True
  | otherwise  = not . oddDigits $ x`div`10

它比我最初的答案要優雅得多,如下。 我將它包括在內,介紹一個常見的功能范例,即問題的工人/包裝轉換。 這里的包裝器提供了接口,並將工作傳遞給另一個函數。 請注意,否定性檢查現在只需要進行一次。

oddDigits :: Integer -> Bool
oddDigits x
   | x <= 0 = False
   | otherwise = oddDigits' True x

oddDigits' :: Bool -> Integer -> Bool
oddDigits' t x
   | x < 10 = t
   | otherwise = oddDigits' (not t) $ x `div` 10

oddDigits'帶有一個內部數據,最初的Bool。 我的第一個想法是讓Bool成為一個數字累加器,計算數字位數。 在這種情況下,需要提供“unwrapper”,在這種情況下是標准的“奇數”功能:

oddDigits x
   | x <= 0 = False
   | otherwise = odd . oddDigits'' 1  $  x

其中oddDigits'' :: Integer -> Integer -> Integer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM