A better toSeq

This commit is contained in:
Smaug123
2020-10-25 14:30:00 +00:00
parent 4020f68c08
commit c19f6c8917
3 changed files with 60 additions and 10 deletions

View File

@@ -20,8 +20,9 @@ module TestRedBlackTree =
let ``Examples found by property-based testing`` (l : int list) =
l
|> List.fold (fun tree i -> RedBlackTree.add i () tree) RedBlackTree.empty
|> RedBlackTree.toList
|> RedBlackTree.toListRev
|> List.map fst
|> List.rev
|> shouldEqual (Set.ofList l |> Set.toList)
[<TestCase 9>]
@@ -30,7 +31,7 @@ module TestRedBlackTree =
let rbt =
perm
|> List.fold (fun tree i -> RedBlackTree.add i () tree) RedBlackTree.empty
if rbt |> RedBlackTree.toList |> List.map fst <> [1..n] then failwithf "Correctness error: %+A produced %+A" perm rbt
if rbt |> RedBlackTree.toListRev |> List.map fst |> List.rev <> [1..n] then failwithf "Correctness error: %+A produced %+A" perm rbt
let balance = RedBlackTree.balanceFactor rbt
if balance.Longest >= balance.Shortest * 2 then
failwithf "Unbalanced! %+A produced %+A (balance: %+A)" perm rbt balance
@@ -40,9 +41,24 @@ module TestRedBlackTree =
let property (list : int list) =
list
|> List.fold (fun tree i -> RedBlackTree.add i () tree) RedBlackTree.empty
|> RedBlackTree.toList
|> RedBlackTree.toListRev
|> List.map fst
|> List.rev
|> shouldEqual (Set.ofList list |> Set.toList)
let config = { Config.Default with MaxTest = 10000 }
Check.One(config, property)
Check.One(config, property)
[<Test>]
let ``toSeq vs toList`` () =
let property (list : int list) =
let rbt =
list
|> List.fold (fun tree i -> RedBlackTree.add i () tree) RedBlackTree.empty
rbt
|> RedBlackTree.toSeq
|> Seq.toList
|> shouldEqual (RedBlackTree.toListRev rbt |> List.rev)
let config = { Config.Default with MaxTest = 10000 }
Check.One(config, property)

View File

@@ -338,12 +338,46 @@ module RedBlackTree =
| RedBlackTree.RedRoot root -> foldRed folder state root
| RedBlackTree.BlackRoot root -> foldBlack folder state root
/// Convert the tree to a list, in sorted order.
let toList<'a, 'v when 'a : comparison> (tree : RedBlackTree<'a, 'v>) : ('a * 'v) list =
fold (fun ls a -> a :: ls) [] tree |> List.rev
/// Convert the tree to a list, in reverse sorted order.
let toListRev<'a, 'v when 'a : comparison> (tree : RedBlackTree<'a, 'v>) : ('a * 'v) list =
fold (fun ls a -> a :: ls) [] tree
let rec private toSeqBlack<'a, 'v, 'depth when 'a : comparison> (tree : BlackNode<'a, 'v, 'depth>) : ('a * 'v) seq =
seq {
match tree with
| BlackNode.Leaf ->
()
| BlackNode.BlackBlackNode (left, right, value) ->
yield! toSeqBlack left
yield (ValueAtDepth.value value)
yield! toSeqBlack right
| BlackNode.BlackRedNode (left, right, value) ->
yield! toSeqBlack left
yield (ValueAtDepth.value value)
yield! toSeqRed right
| BlackNode.RedBlackNode (left, right, value) ->
yield! toSeqRed left
yield (ValueAtDepth.value value)
yield! toSeqBlack right
| BlackNode.RedRedNode (left, right, value) ->
yield! toSeqRed left
yield (ValueAtDepth.value value)
yield! toSeqRed right
}
and private toSeqRed<'a, 'v, 'depth when 'a : comparison> (tree : RedNode<'a, 'v, 'depth>) : ('a * 'v) seq =
seq {
match tree with
| RedNode.RedNode (left, right, value) ->
yield! toSeqBlack left
yield (ValueAtDepth.value value)
yield! toSeqBlack right
}
let toSeq<'a, 'v when 'a : comparison> (tree : RedBlackTree<'a, 'v>) : ('a * 'v) seq =
fold (fun ls a -> seq { yield! ls ; yield a }) Seq.empty tree
match tree with
| RedBlackTree.RedRoot root -> toSeqRed root
| RedBlackTree.BlackRoot root -> toSeqBlack root
let rec private balanceFactorBlack<'a, 'v, 'depth when 'a : comparison> (node : BlackNode<'a, 'v, 'depth>) : int * int =
match node with

View File

@@ -16,8 +16,8 @@ module RSet =
| Some _ -> true
| None -> false
let toList<'a when 'a : comparison> (RSet s : RSet<'a>) : 'a list =
RedBlackTree.toList s
let toListRev<'a when 'a : comparison> (RSet s : RSet<'a>) : 'a list =
RedBlackTree.toListRev s
|> List.map fst
let toSeq<'a when 'a : comparison> (RSet s : RSet<'a>) : 'a seq =