【问题标题】:Cross sum of digits of a non-negative number using list comprehension使用列表推导对非负数的数字进行交叉总和
【发布时间】:2021-05-24 17:07:15
【问题描述】:

我正在寻找一个非负数的数字总和(“交叉总和”)的非递归实现,如下所示:

cs :: Int -> Int 
cs n = sum digits_of_n where digits_of_n = [ . | ... ] 

一个数字的交叉和(例如 512)是其各个数字的总和(例如 5 + 1 + 2 = 8)

cs 将非负数“n”作为输入,然后应该使用列表推导将数字拆分为其数字(例如 1234 -> [1,2,3,4]),然后将其相加。

使用列表理解的部分是问题,我不知道如何实现。

“通常”的递归方式是使用模和除法递归地从数字中提取数字,然后像这样总结它们:

cs :: Int -> Int
cs n = if n == 0 then 0 else n `mod` 10 + cs (n `div` 10)

但是,如果没有递归和列表理解,我很难表达这个,有人对此有想法吗?

【问题讨论】:

  • 也许您可以尝试使用map (read . pure) . show 之类的方法将数字转换为字符串,然后将单个数字转换回数字。不过,我可能更喜欢递归解决方案。

标签: haskell sum list-comprehension digits sum-of-digits


【解决方案1】:

首先让我指出,这样的数字总和几乎是完全没用的东西,关于它们的问题太多了。

...无论如何——你的问题归结为编写一个函数Int -> [Int],它产生一个非负数的数字列表。好吧,这当然可以递归地完成,它可以使用 show 来完成(这有点小技巧,但是,anything 需要 十进制数字将是一个黑客),带有unfold,或者确实带有列表理解。在这种情况下,您不能很好地 终止 已经消耗了所有数字,但您仍然可以先计算数字的数量,然后确定每个 i 数字分别:

decimalDigits :: Int -> [Int]
decimalDigits n = [ _ | i <- [0 .. ceiling . logBase 10 $ fromIntegral n ]

然后,要计算 i-th 数字,您需要像在递归解决方案中一样使用 moddiv,只是不是使用 10,而是使用 i-th 幂。

【讨论】:

    【解决方案2】:

    这是一种可能的方法:

    f x = [(x `mod` (10 ^ y)) `div` (10 ^ (y-1)) | y <- [1.. ceiling $ logBase 10 $ fromIntegral x]]
    

    这假定数字作为整数输入。它首先计算大于输入的以 10 为底的对数的最接近的整数。该值为下一步提供了一个边界,我们使用divmod 的组合将数字拆分为数字。将所有内容放在一起,我们最终得到从右到左的数字。

    【讨论】:

      【解决方案3】:

      另一个间接的

      sumdigits = sum . map digitToInt . show
      

      你需要import Data.Char(digitToInt)

      【讨论】:

        猜你喜欢
        • 2021-08-11
        • 1970-01-01
        • 2020-10-20
        • 2019-09-04
        • 1970-01-01
        • 2014-02-05
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        相关资源
        最近更新 更多