获取haskell中所有非减少列表集的列表

时间:2011-08-11 20:56:55

标签: list haskell

如何生成具有当前长度的列表元素的所有可能的非减少集?

getSets :: [Int] -> Int -> [[Int]]
...

> getSets [0..9] 3
[[0,0,0],[0,0,1]..[3,9,9],[4,4,4]..[8,9,9],[9,9,9]]

6 个答案:

答案 0 :(得分:7)

getSets s n = filter nonDec $ replicateM n s
  where nonDec xs = and $ zipWith (>=) (drop 1 xs) xs

答案 1 :(得分:6)

让我们开始有点简单,使用一个函数从给定的列表元素生成给定大小的所有集合:

getAllSets :: [Int] -> Int -> [[Int]]
getAllSets _  0 = [[]]
getAllSets xs n = [(x:ys) | x <- xs, ys <- getAllSets xs (n-1)]

您可以将此功能视为一次构建一个元素。它会将x添加到每个较短集合ys的前面,并为xs中的元素添加{。}}。

我们可以做些什么来获得最终答案,决定不为xs中的每个元素构建更长的集合,但仅针对那些小于或等于x中每个元素的ys {1}}:

getSets :: [Int] -> Int -> [[Int]]
getSets _  0 = [[]]
getSets xs n = [(x:ys) | x <- xs, ys <- getSets xs (n-1), all (x <=) ys]

这是一个很好看的解决方案,但它比我们实际需要的工作更多。毕竟,为什么要将xys中的每个元素进行比较?我们知道ys已经按照正确的顺序排列,因为我们以递归的方式构建它,所以让我们确保x小于或等于ys的第一个元素,如果有的话:

getSets' :: [Int] -> Int -> [[Int]]
getSets' _  0 = [[]]
getSets' xs n = [(x:ys) | x <- xs, 
                          ys <- getSets' xs (n-1), 
                          null ys || x <= head ys]

更新:除了整合Thomas M. DuBuisson更清晰的谓词之外,我还对他的,chrisdb和我的解决方案进行了基准测试:http://hpaste.org/50195

更新x2 :修正了错误的标准标签;基准测试是正确的,但输出结果令人困惑。

答案 2 :(得分:3)

这是一个干净的版本也应该相当快(即它只构造正确的列表,不构造然后丢弃不正确的列表)。

import Data.List

getSets _ 0 = [[]]
getSets xs n = do
        a <- xs
        rest <- getSets (filter (>= a) xs) (n - 1)
        return (a : rest)
编辑:但它比ACF慢 - 使用filter是昂贵的,ACF智能地构建了他的列表,因此在添加一个非常便宜的元素之后将发现一个“坏”列表。非常好,因为我认识到了。

答案 3 :(得分:2)

这样做你想要的吗?

import Data.List

getSets :: [Int] -> Int -> [[Int]]

getSets xs n
    | n > 0     = getSets' (sort xs) n
    | otherwise = []

getSets' _ 0          = [[]]
getSets' [] _         = [] 
getSets' xs@(x:xss) n = map (x:) (getSets' xs (n-1)) ++ getSets' xss n 

答案 4 :(得分:1)

也许这个?对于列表x = [a 1 ,..., n ],nondec k x返回所有子序列的列表[a i 1 i 2 ,..., i k ]长度k,其中i 1 &lt; = i 2 &lt; = ...&lt; = i k

import Data.List

nondec 0 _ = return []
nondec n x = do (a,y) <- zip x (tails x)
                map (a:) $ nondec (n-1) y

x = nondec 3 [0..9]

答案 5 :(得分:0)

我为[0..9] 3案例做了一些时间,我得到了:

benchmarking subsets/chrisdb
mean: 193.2204 us, lb 193.0333 us, ub 193.4622 us, ci 0.950
std dev: 1.076765 us, lb 865.2091 ns, ub 1.456463 us, ci 0.950

benchmarking subsets/acfoltzer
mean: 218.5110 us, lb 218.2996 us, ub 218.8322 us, ci 0.950
std dev: 1.309867 us, lb 951.4661 ns, ub 1.793697 us, ci 0.950

benchmarking subsets/TMD
mean: 198.9438 us, lb 194.3482 us, ub 206.6694 us, ci 0.950
std dev: 29.88779 us, lb 20.14344 us, ub 41.98061 us, ci 0.950

我排除了sdcwc的解决方案,因为我认为它不能解决问题。特别是,如果初始列表未排序,则它不会产生非递减子列表。正如你所看到的,没有太大的区别,但Thomas M. DuBuisson和我自己的解决方案的平均速度要快一些。