我会去创建所有具有 sum 属性的列表,例如使用列表理解。然后通过唯一性属性进行过滤,例如:
- 获取第一个子列表和生成器列表的列表差异并检查下一个子列表是否包含在生成器中,
- 然后删除一个子列表,如果它不是改变的生成器的子集
- 或执行与 1 中相同的程序。
- 如果更改的生成器的总和小于 m,则可以结束该过程
请注意,结果取决于您对所有子列表进行排序的方式 - 因此解决方案不是唯一的最长子列表列表,而只是具有 sum 和“唯一性”属性的众多结果之一。
编辑:一些代码 - 不是完美的最大解决方案
只是一些开始和思考的事情,我只收集简单的两个元素列表,否则取一个最大列表。
下一个改进将是使一个函数不仅容易收集,而且收集所有两个元素列表,然后将其推广到给定长度的子列表,也许你想看看基本的组合。
module Sublists where
import Data.List ((\\))
subLists :: Int -> Int -> [[Int]]
subLists n = subLists' ([],[1..n])
subLists' :: ([[Int]],[Int]) -> Int -> [[Int]]
subLists' aa m = fst (mLSubLists (tLSubLists aa m) m)
_subLists :: ([Int] -> Int -> [Int]) -> ([[Int]],[Int]) -> Int -> ([[Int]],[Int])
_subLists _ yx@(_,[ ]) _ = yx
_subLists _ yx@(_,[_]) _ = yx
_subLists f yx@(yy,xx) m | sum xx < m = yx
| otherwise = if tt == []
then yx
else _subLists f (tt:yy,xx\\tt) m
where tt = f xx m
tLSubLists :: ([[Int]],[Int]) -> Int -> ([[Int]],[Int])
tLSubLists = _subLists twoList
mLSubLists :: ([[Int]],[Int]) -> Int -> ([[Int]],[Int])
mLSubLists = _subLists manyList
twoList :: [Int] -> Int -> [Int]
twoList [ ] _ = []
twoList [_] _ = []
twoList xx@(x:xs) m | (x + l) < m = []
| x == l = []
| (x + l) `rem` m == 0 = [x,l]
| otherwise = twoList ii m
where l = last xs
ii = init xx
manyList :: [Int] -> Int -> [Int]
manyList xx m | s < m = []
| s == m = xx
| s `rem` m == 0 = xx
| otherwise = manyList xs m
where s = sum xx
xs = tail xx
和一些测试用例:
import Sublists
import Test.HUnit
import Data.List ((\\))
main = testAll
testAll = runTestTT $ TestList tests
tests :: [Test]
tests = [
"n=6 m=7" ~: "subLists" ~: [[3,4],[2,5],[1,6]]
~=? subLists 6 7,
"n=6 m=7" ~: "twoList" ~: [1,6]
~=? twoList [1..6] 7,
"n=6 m=7" ~: "twoList" ~: [2,5]
~=? twoList ([1..6]\\[1,6]) 7,
"n=6 m=7" ~: "twoList" ~: [3,4]
~=? twoList (([1..6]\\[1,6])\\[2,5]) 7,
"n=6 m=7" ~: "manyList" ~: [2,3,4,5]
~=? manyList [1..5] 7,
"dummy" ~: "dummy" ~: "result"
~=? (\_ -> "result") "function"
]