【发布时间】:2014-09-02 11:04:44
【问题描述】:
我正在尝试构建一个包含无限位图的惰性数据结构。我愿意支持以下操作:
-
true :: InfBitMap返回 True 的无限位图,即所有位置的值都应为 True。
-
falsify :: InfBitMap -> [Int] -> InfBitMap将列表中的所有位置设置为 False。该列表可能是无限的。例如,falsify true [0,2..] 将返回一个列表,其中所有(且只有)奇数位置为 True。
-
check :: InfBitMap -> Int -> Bool检查索引的值。
到目前为止,这是我能做的。
-- InfBitMap will look like [(@), (@, @), (@, @, @, @)..]
type InfBitMap = [Seq Bool]
true :: InfBitMap
true = iterate (\x -> x >< x) $ singleton True
-- O(L * log N) where N is the biggest index in the list checked for later
-- and L is the length of the index list. It is assumed that the list is
-- sorted and unique.
falsify :: InfBitMap -> [Int] -> InfBitMap
falsify ls is = map (falsify' is) ls
where
-- Update each sequence with all indices within its length
-- Basically composes a list of (update pos False) for all positions
-- within the length of the sequence and then applies it.
falsify' is l = foldl' (.) id
(map ((flip update) False)
(takeWhile (< length l) is))
$ l
-- O(log N) where N is the index.
check :: InfBitMap -> Int -> Bool
check ls i = index (fromJust $ find ((> i) . length) ls) i
我想知道是否有一些我缺少的 Haskellish 概念/数据结构可以使我的代码更优雅/更高效(常量对我来说无关紧要,只需订购)。我尝试查看拉链和镜片,但它们似乎没有帮助。我想保持更新和检查的复杂性对数(可能只是摊销对数)。
注意:在有人怀疑之前,不,这不是作业问题!
更新:
我突然想到检查可以改进为:
-- O(log N) where N is the index.
-- Returns "collapsed" bitmap for later more efficient checks.
check :: InfBitMap -> Int -> (Bool, InfBitMap)
check ls i = (index l i, ls')
where
ls'@(l:_) = dropWhile ((<= i) . length) ls
可以将其转换为 Monad 以保持代码整洁。
【问题讨论】:
-
你确定
InfBitMap?如果true应该与repeat True同构,则InfBitMap需要是[Bool]或Seq Bool,但不能同时是两者。 -
@Zeta 我的意思并不是说真要同构重复真。我的意思是它拥有无限的 True 序列。如果重复 True 是同构的,那将使检查在 N 中成为线性。
-
falsify的复杂性似乎不正确。L更新了N长度序列,已经是 O(L * log N)。 -
@AndrásKovács 在第一个序列中最多有 1 次更新,在第二个中最多有 2 次,...,在第 k 个中最多有 2^k 次更新。总结一下,更新次数
-
@aelguindy for
Data.Sequence单个更新的大小为日志 N。我不太明白“L + log N”中的“+”是从哪里来的。