Thr*_*eFx 5 combinations haskell set
Haskell的表现力使我们能够轻松定义一个powerset函数:
import Control.Monad (filterM)
powerset :: [a] -> [[a]]
powerset = filterM (const [True, False])
Run Code Online (Sandbox Code Playgroud)
为了能够执行我的任务,所述powerset按特定函数排序是至关重要的,所以我的实现类似于:
import Data.List (sortBy)
import Data.Ord (comparing)
powersetBy :: Ord b => ([a] -> b) -> [a] -> [[a]]
powersetBy f = sortBy (comparing f) . powerset
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,是否有一种方法只能在给定特定点和点的情况下生成powerset 的子集,其中和.例如,我的参数是一个整数列表(),它们按总和排序.现在我想提取只能在给定范围内的子集,可以说对.实现这一目标的一种方法是使powerset仅包括我的范围,但在处理更大的子集时这似乎(并且)无效:start
end
f(start) < f(end)
|start| < |end|
[1,2,3,4,5]
3
7
filter
badFunction :: Ord b => b -> b -> ([a] -> b) -> [a] -> [[a]]
badFunction start end f = filter (\x -> f x >= start && f x <= end) . powersetBy f
Run Code Online (Sandbox Code Playgroud)
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
子集,因为它不会检查所有元素而是"动态"生成它们将大大提高性能.
如果你想允许完全通用的排序函数,那么就无法检查powerset的所有元素.(毕竟,你怎么知道这不是一个特殊的条款,例如,特定的一组[6,8,34,42]
与其邻居的排名完全不同?)
但是,您可以通过以下方式快速提高算法速度
所以
import Control.Arrow ((&&&))
lessBadFunction :: Ord b => (b,b) -> ([a]->b) -> [a] -> [[a]]
lessBadFunction (start,end) f
= map snd . sortBy (comparing fst)
. filter (\(k,_) -> k>=start && k<=end)
. map (f &&& id)
. powerset
Run Code Online (Sandbox Code Playgroud)
基本上,让我们面对现实,除了非常小的基础之外的任何东西都是不可行的.特定应用"总和在一定范围内"几乎是一个包装问题 ; 有很多有效的方法来做这种事情,但你必须放弃完美的通用性和量化的概念而不是一般的子集.
归档时间: |
|
查看次数: |
310 次 |
最近记录: |