-
Notifications
You must be signed in to change notification settings - Fork 1
/
Tests.elm
153 lines (142 loc) · 6.6 KB
/
Tests.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
module Tests exposing (BasicUnion(..), all, intFromUnion, union)
import Expect
import Fuzz exposing (Fuzzer, int, list, tuple)
import Heap exposing (biggest, by, smallest, thenBy, using)
import Test exposing (Test, describe, fuzz, test)
type BasicUnion
= AnInt Int
union : Fuzzer BasicUnion
union =
Fuzz.map AnInt int
intFromUnion : BasicUnion -> Int
intFromUnion (AnInt i) =
i
all : Test
all =
describe "Heap"
[ describe "Basics"
[ test "Can create an empty heap with no items" <|
\() ->
Expect.equal Nothing <| Heap.peek <| Heap.empty smallest
, fuzz int "Can insert an element and pop it" <|
\i ->
Heap.singleton smallest i
|> Heap.pop
|> Maybe.map (Tuple.mapSecond Heap.isEmpty)
|> Expect.equal (Just ( i, True ))
, fuzz (tuple ( int, int )) "Can insert two elements and pop lower one" <|
\( i, j ) ->
Heap.singleton smallest i
|> Heap.push j
|> Heap.pop
|> Maybe.map (Tuple.mapSecond Heap.isEmpty)
|> Expect.equal (Just ( Basics.min i j, False ))
, fuzz (list int) "Can insert elements and peek lowest one" <|
\xs ->
List.foldl Heap.push (Heap.empty smallest) xs
|> Heap.peek
|> Expect.equal (List.minimum xs)
, fuzz (list int) "Can get all inserted elements in order" <|
\xs ->
Heap.fromList smallest xs
|> Heap.toList
|> Expect.equal (List.sort xs)
, fuzz (tuple ( list int, list int )) "Can merge two heaps" <|
\( xs, ys ) ->
Heap.fromList smallest xs
|> Heap.mergeInto (Heap.fromList smallest ys)
|> Heap.toList
|> Expect.equal (Heap.toList <| Heap.fromList smallest <| xs ++ ys)
, describe "Size"
[ test "Can count size of empty heap" <|
\() ->
Heap.empty smallest
|> Heap.size
|> Expect.equal 0
, fuzz int "Can count size of singleton heap" <|
Heap.singleton smallest
>> Heap.mergeInto (Heap.empty smallest)
>> Heap.size
>> Expect.equal 1
, fuzz (list int) "Can count size of heap" <|
\xs ->
Heap.fromList smallest xs
|> Heap.size
|> Expect.equal (List.length xs)
]
]
, describe "Non-comparable values"
[ fuzz (tuple ( list int, list int )) "Can create heaps of non-comparable values with custom hashing function" <|
\( xs, ys ) ->
let
hashingFn =
.list >> List.sum
in
Heap.singleton (smallest |> by hashingFn) { list = xs }
|> Heap.push { list = ys }
|> Heap.peek
|> Maybe.map (.list >> List.sum)
|> Expect.equal (Just <| min (List.sum xs) (List.sum ys))
, fuzz (tuple ( list int, list int )) "Can create heaps of non-comparable values with two custom hashing functions" <|
\( xs, ys ) ->
let
hash a =
if List.isEmpty a.list then
0
else
1
hash2 a =
List.maximum a.list |> Maybe.withDefault 0
in
Heap.empty (smallest |> by hash |> thenBy hash2)
|> Heap.push { list = xs }
|> Heap.push { list = ys }
|> Heap.peek
|> Maybe.andThen (.list >> List.maximum)
|> Expect.equal (Maybe.map2 min (List.maximum xs) (List.maximum ys))
, test "Can create heaps of non-comparable values with custom compare function" <|
\() ->
let
closestToZero : (Int -> Int -> Int) -> (Int -> Int -> Int) -> Basics.Order
closestToZero a b =
compare (abs <| a 1 2) (abs <| b 1 2)
in
[ (+), (-), (*) ]
|> Heap.fromList (smallest |> using closestToZero)
|> Heap.peek
|> Maybe.map (\fn -> fn 1 2)
|> Expect.equal (Just -1)
, fuzz (tuple ( list union, list union )) "Can merge heaps of non-comparable values" <|
\( xs, ys ) ->
let
opts =
smallest |> by intFromUnion
in
List.foldl Heap.push (Heap.empty opts) xs
|> Heap.mergeInto (Heap.fromList opts ys)
|> Heap.toList
|> Expect.equal (List.sortBy intFromUnion (xs ++ ys))
]
, describe "Max heaps"
[ fuzz (list int) "Max heaps produce the reverse of Min heaps" <|
\ints ->
Heap.fromList biggest ints
|> Heap.toListReverse
|> Expect.equal (Heap.fromList smallest ints |> Heap.toList)
, fuzz (list int) "Max heaps have biggest value first" <|
\ints ->
Heap.fromList biggest ints
|> Heap.peek
|> Expect.equal (List.maximum ints)
]
, describe "Duplicate values"
[ test "Duplicate values are preserved" <|
\() -> Expect.equal (Heap.toList (Heap.fromList smallest [ 1, 2, 1, 3 ])) [ 1, 1, 2, 3 ]
]
, describe "Tail recursion"
[ test "toListUnordered is tail recursive" <|
\() -> Expect.equal (List.length <| Heap.toListUnordered (Heap.fromList biggest (List.range 1 100000))) 100000
, test "toList is tail recursive" <|
\() -> Expect.equal (List.length <| Heap.toList (Heap.fromList biggest (List.range 1 100000))) 100000
]
]