查找给定点积和另一个列表的列表的算法

时间:2018-10-16 22:05:01

标签: algorithm functional-programming sml

我需要编写一个函数findL,该函数采用整数列表 L 1 和所需的点积 n ,并返回非负整数的列表 L 2 ,这样 L 1 · L 2 == n 。 (“乘积”是指成对乘积的总和;例如,[1,2]·[3,4] = 1·3 + 2·4 = 11。)

例如,findL(11, [1,2])可能返回SOME [3,4]。如果没有可能的列表,我返回NONE

我正在使用一种功能语言。 (特别是标准ML,但是确切的语言并不那么重要,我只是想考虑一个FP算法。)到目前为止,我已经写了什么:

假设我有findL(n,L1):

  1. 如果L1 = [],我将返回NONE。
  2. 如果L1 = [x](长度为1的列表)
    • 如果(n> = 0且x> 0且n mod x = 0),则返回SOME [n div x]
    • 否则返回NONE
  3. 如果L1的长度大于1,则对findL(n,L [1:])递归。如果返回列表L2,则返回连接到L2的[1]。如果递归调用返回NONE,则对findL(0,L [1:])进行另一个递归调用,如果不是NONE,则在结果前加上[n div x]。这适用于许多输入,但不适用于其他输入。

我需要更改第3部分,但是我不确定我是否有正确的主意。我将不胜感激!

1 个答案:

答案 0 :(得分:1)

除非您需要说输入中的空列表总是不好的(即使列表[]的n = 0),否则我还是建议您根据是否在列表中达到0来为空列表返回不同的内容。结束(是否已减去所有内容),然后在接收到任何非空列表时进行递归,而不是对一个单元素列表进行特殊处理。

就第三步而言,您需要测试输入列表中第一个元素的个可能的正整数倍,直到它们超过n,而不仅仅是第一个和最后一个。您获得的第一个非值足够好,因此您只需将乘数(而不是乘数)放在返回列表中即可。如果一切都没有,您将返回无。


我不了解SML,但是这是我在Haskell中的做法:

import Data.Maybe (isJust, listToMaybe)

-- Find linear combinations of positive integers
solve :: Integer -> [Integer] -> Maybe [Integer]
-- If we've made it to the end with zero left, good!
solve 0 []     = Just []
-- Otherwise, this way isn't the way to go.
solve _ []     = Nothing
-- If one of the elements of the input list is zero, just multiply that element by one.
solve n (0:xs) = case solve n xs of
                      Nothing -> Nothing
                      Just ys -> Just (1:ys)
solve n (x:xs) =   listToMaybe                    -- take first solution if it exists
                 . map (\ (m, Just ys) -> m:ys)   -- put multiplier at front of list
                 . filter (isJust . snd)          -- remove nonsolutions
                 . zip [1 ..]                     -- tuple in the multiplier
                 . map (\ m -> solve (n - m) xs)  -- use each multiple
                 $ [x, x + x .. n]                -- the multiples of x up to n

Here it is solving 11 with [1, 2] and 1 with [1, 2]