【问题标题】:Haskell sublistsHaskell 子列表
【发布时间】:2012-05-21 16:55:57
【问题描述】:

我必须创建一个查找特定子列表的函数。

function :: Integer -> Integer -> [[Integer]]
function n m = …
  • 如果m 小于n,则程序退出。
  • 如果(mod (sum [1..n]) m) /= 0 那么又报错了。
  • 否则程序应该找到子列表。
  • 而主列表是从[1..n]生成的

例如,如果数字是 n = 6m = 7。列表是[1,2,3,4,5,6] 答案是[[6,1],[5,2],[4,3]]

function 6 7
>>> [[6,1],[5,2],[4,3]]

订单不是必需的。所以我已经做了这些步骤。任何帮助都会很有用。示例代码也会很有用。如果有人能解决这个问题,我将不胜感激。带有解决方案的代码对我来说非常有用。

    function :: Integer -> Integer -> [[Integer]]
    function n m 
      |m < n = error "m is smaller than n"
      |(mod (sum [1..n]) m) /= 0 = error "list sum doesn't devide with m"
      |otherwise = …

【问题讨论】:

  • 您能否更详细地解释一下子列表是如何找到的?示例似乎是由6+1=7,5+2=7,4+3=7 生成的,这是一个正确的猜测吗?
  • 每个子列表都是作为总和找到的。在此示例中,每个总和必须等于 7。而且每个数字必须在子列表中存在一次。所以在这个例子中,我们有包含 2 个参数的子列表。例如,如果我们想创建 3 个参数列表,例如 [1,2,4],我们不能,因为我们已经有包含这些数字的子列表。每个子列表最多只能显示一次。 [2,5] 和 [5,2] 相等。所以每个子列表总和必须等于 m。

标签: haskell


【解决方案1】:

我会去创建所有带有 sum 属性的列表,例如使用列表理解。然后通过唯一性属性进行过滤,例如:

  1. 获取第一个子列表和生成器列表的列表差异并检查下一个子列表是否包含在生成器中,
    • 如果子列表不是更改后的生成器的子集,则删除该子列表
    • 或执行与 1 中相同的过程。
  2. 如果更改的生成器的总和小于 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"
                            ]

【讨论】:

  • 你能用代码给出一个起点吗?不知道如何开始。
【解决方案2】:

Data.List 中的函数 subsequences 可能会有所帮助,例如

subsequences "abc" == ["","a","b","ab","c","ac","bc","abc"]

那么你“只是”需要过滤掉所有不符合你的条件的子列表。

【讨论】:

  • 现在我取得了那种成功,我得到了总和等于 m 的列表。但子列表仍然包含相似的数字。例如现在我得到 [[1,2,4],[3,4],[2,5],[1,6]]。每个数字必须表示一次。试图解决这个问题。但这是有用的提示。谢谢
  • @KasparKohler 你知道创建所有子列表是指数级的吗?该方法仅适用于小的n
  • 不知道。但首先我想让它与子序列一起工作。
  • 似乎子序列并没有那么有用,因为伟大的子列表需要很多时间。有人有其他解决方案的想法吗?
  • 我会先尝试使用subsequences 找到一个“慢”解决方案,然后编写我自己的版本(这样可以避免生成不必要的子列表,例如总和太大)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多