haskell:数字中的最大乘积连续数字

时间:2014-08-02 18:46:53

标签: haskell

我正在尝试编写一个函数,该函数找到具有k位数的给定z数字的n个连续数字的最高乘积。

例如:

z = 1240313 -- number entered
n = 7 -- number of digits

k = 2 => 2*4 => 8 -- example if k = 2
k = 3 => 3*1*3 => 9
k = 4 => 0

如果k > n我被要求收回错误。

直到现在我的想法是从给定的数字z逐个获取所有数字并将它们插入列表中。然后我可能会使用这个列表,但我不确切知道如何。

我设法处理错误(我认为) 这是我的代码,直到现在:

myList 0 = []
myList x = (x `mod` 10 : myList (x `div` 10))

myReverse x = reverse (myList x)

maxConProduct :: Integer -> Integer -> Integer
maxConProduct z k | k > length(myReverse) = error "more consecutive digits entered as required"

我是Haskell和编程世界的新手。我很感激能帮到这个问题。

3 个答案:

答案 0 :(得分:2)

TL; DR:

maximum . map product . takeWhile ((==n).length) . map (take n) . tails

撰写函数

你可以通过编写功能来非常干净地完成这项工作:

import Data.List (tails)
import Data.Char (isDigit)

maxProd :: (Num a, Ord a) => Int -> [a] -> a
maxProd n = maximum                      -- biggest
          . map product                  -- product in the list
          . takeWhile ((== n) . length)  -- once the too-short ones have gone
          . map (take n)                 -- when you take the first n of each
          . tails                        -- of the tails of the original

请注意

((== n) . length) :: [a] -> Bool

首先找到列表的长度,如果该长度与True匹配,则给出n

它是如何工作的?

通过举例说明,让我们通过您的示例跟踪。注意尾部是如何具有所有长度的,但是当我们map (take 3)时它只保留每个尾部的前三个。另请注意,有三个列表太短([1,3],[3],[]),这就是我们takeWhile ((==3).length)的原因。

ghci> tails $ [1,2,4,0,3,1,3]
[[1,2,4,0,3,1,3],[2,4,0,3,1,3],[4,0,3,1,3],[0,3,1,3],[3,1,3],[1,3],[3],[]]
ghci> map (take 3) . tails $ [1,2,4,0,3,1,3] 
[[1,2,4],[2,4,0],[4,0,3],[0,3,1],[3,1,3],[1,3],[3],[]]
ghci> takeWhile ((==3).length) . map (take 3) . tails $ [1,2,4,0,3,1,3]
[[1,2,4],[2,4,0],[4,0,3],[0,3,1],[3,1,3]]
ghci> map product . takeWhile ((==3).length) . map (take 3) . tails $ [1,2,4,0,3,1,3]
[8,0,0,0,9]
ghci> maximum . map product . takeWhile ((==3).length) . map (take 3) . tails $ [1,2,4,0,3,1,3]
9

减少无益

现在,当n超过原始列表的长度时会出现错误,因为takeWhile将过滤掉所有列表,并且您将获取最大的空列表,但是更明确的信息会更有帮助。从单个Int转换它也很方便:

digits :: Int -> [Int]
digits = map (read . (:"")) . show

通过将显示的String的每个字符转换为String本身,方法是将它放在带有(:“”)的空字符串前面,然后读取每个字符。最初我是从字符串中取出来的,因为我错误地认为这就是你所拥有的。没关系。

findMaxProd :: Int -> Int -> Int
findMaxProd n i
          | n > length (show i) = error "findMaxProd: product length exceeds number length"
          | otherwise = maxProd n . digits $ i

在行动中,这给出了:

ghci> findMaxProd 10 1240313
*** Exception: findMaxProd: product length exceeds number length
ghci> findMaxProd 3 1240313
9

答案 1 :(得分:1)

另一种解决方案是这样的:

maxConProduct z k | k > length (myReverse z) = error "more consecutive digits entered as required"
maxConProduct z k = solve (myReverse z) [] k
  where solve :: (Num a, Ord a) => [a] -> [a] -> Int -> a
        solve [] acc _ = head $ reverse $ sort acc
        solve x'@(x:xs) acc k = if k > length x'
                                then solve [] acc k
                                else solve xs (product (take k x'):acc) k

ghci中的演示:

λ> maxConProduct 1240313 2
8
λ> maxConProduct 1240313 3
9
λ> maxConProduct 1240313 4
0
λ> maxConProduct 1240313 8
*** Exception: more consecutive digits entered as required

您可以在solve函数中看到,我正在获取所有首个k个数字的产品,并将其累积在列表acc中。一旦输入列表为空,那么我只需对acc进行排序并给出其中的最高元素。

答案 2 :(得分:0)

试试这个:

maxProduct number k 
  | length (show number) < k = error "more consecutive digits entered as required"
  | otherwise = maxProductHelp (transform number) k
    where
      transform 0 = []
      transform number = mod number 10 : transform (div number 10) -- returns digits
      maxProductHelp digits k = maximum $ products digits k -- gets maximum
        where
          products d k -- returns a list of products of consecutive groups of length k 
            | length d < k = []
            | otherwise = (product $ take k d) : products (tail d) k

您的maxConProduct已实施为maximum $ products digits k

让我们看看这个解决方案:

  • maxProduct调用maxProductHelp,号码以某种方式更改。
  • transform只返回指定号码的数字。
  • maxProductHelp现在获得了products返回的列表的最大值。
  • products会返回长度为k的连续子列表的产品列表。

最重要的功能是products,这个功能相对容易理解:

我们希望产品返回k个连续数字的产品列表,因此我们只将k个连续数字的乘积合并到下一个k个连续数字的乘积中。如果我们的剩余数字列表比我们指定的k短,那么我们返回一个空列表,其中包含所有内容。

这里只是products的一个小例子:

products [3,1,3,0,4,2,1] 3 = (product [3,1,3]) : products [1,3,0,4,2,1]
products [1,3,0,2,4,2,1] 3 = (product [1,3,0]) : products [3,0,4,2,1]
products [3,0,4,2,1] 3 = (product [3,0,4]) : products [0,4,2,1]
products [0,4,2,1] 3 = (product [0,4,2]]) : products [4,2,1]
products [4,2,1] 3 = (product [4,2,1]]) : products [2,1]
products [2,1] = []

这只是一个清单:

9 : 0 : 0 : 0 : 8 : [] == [9,0,0,0,8]