计算整数哈斯克尔中的奇数位数



我正在尝试制作使用Haskell计算整数中奇数位数的程序。我在检查较长的整数时遇到了问题。我的程序目前如下所示:

oddDigits:: Integer -> Int
x = 0
oddDigits i
| i `elem` [1,3,5,7,9] = x + 1
| otherwise = x + 0

例如,如果我的整数是22334455我的程序应该返回值 4,因为该整数中有 4 个奇数。如何检查该整数中的所有数字?目前它只检查第一个数字并返回 1 或 0。我对哈斯克尔还是很陌生的。

您可以先将整数22334455转换为列表"22334455"。然后找到满足要求的所有元素。

import Data.List(intersect)
oddDigits = length . (`intersect` "13579") . show

为了解决这些问题,您通常会将其拆分为较小的问题。典型的管道是:

  1. 将数字拆分为数字列表;
  2. 过滤奇数数字;和
  3. 计算结果列表的长度。

因此,您可以在此处实现/使用帮助程序函数。例如,我们可以生成一个数字列表:

digits' :: Integral i => i -> [i]
digits' 0 = []
digits' n = r : digits' q
where (q, r) = quotRem n 10

在这里,数字将以相反的顺序生成,但由于这不会影响位数,因此这不是问题。我将其他辅助函数保留为练习。

这是一种有效的方法:

oddDigits :: Integer -> Int
oddDigits = go 0
where
go :: Int -> Integer -> Int
go s 0 = s
go s n = s `seq` go (s + fromInteger r `mod` 2) q
where (q, r) = n `quotRem` 10

这是尾递归的,不会累积垃圾,也不会构建不必要的列表或其他需要垃圾回收的结构。它还可以正确处理负数。

最新更新