Haskell的表达能力使我们可以相对容易地定义一个幂集函数:
import Control.Monad (filterM)
powerset :: [a] -> [[a]]
powerset = filterM (const [True, False])
为了能够完成我的任务,关键是需要按照特定函数对该幂集进行排序,因此我的实现看起来有点像这样:
要执行此任务,必须按照特定的函数对幂集进行排序,因此我的实现类似于以下内容:
import Data.List (sortBy)
import Data.Ord (comparing)
powersetBy :: Ord b => ([a] -> b) -> [a] -> [[a]]
powersetBy f = sortBy (comparing f) . powerset
现在我的问题是,是否有一种方法只生成幂集的子集,给定特定的起点和终点,其中 f(start) < f(end)
且 |start| < |end|
。例如,我的参数是一个整数列表([1,2,3,4,5]
),它们按它们的总和排序。现在我想提取给定范围内的子集,比如说 3
到 7
。实现这个的一种方法是将幂集过滤为仅包括我的范围,但是当处理更大的子集时,这似乎是低效的。
badFunction :: Ord b => b -> b -> ([a] -> b) -> [a] -> [[a]]
badFunction start end f = filter (\x -> f x >= start && f x <= end) . powersetBy f
badFunction 3 7 sum [1,2,3,4,5]
生成的结果是 [[1,2],[3],[1,3],[4],[1,4],[2,3],[5],[1,2,3],[1,5],[2,4],[1,2,4],[2,5],[3,4]]
。现在我的问题是是否有一种直接生成此列表的方法,而不必先生成所有的
2^n
子集,因为这样可以通过“即时生成”而大大提高性能,而不必检查所有元素。