如何生成具有当前长度的列表元素的所有可能的非减少集?
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]]
答案 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]
这是一个很好看的解决方案,但它比我们实际需要的工作更多。毕竟,为什么要将x
与ys
中的每个元素进行比较?我们知道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和我自己的解决方案的平均速度要快一些。