Current section

Files

Jump to
inplace test adt bitset_test.exs
Raw

test/adt/bitset_test.exs

defmodule InPlace.BitSetTest do
use ExUnit.Case
alias InPlace.BitSet
test "basic operations" do
lb = -100
ub = 100
bitset = BitSet.new(lb, ub)
assert BitSet.size(bitset) == 0
assert catch_throw(BitSet.put(bitset, ub + 1)) == :value_out_of_bounds
assert catch_throw(BitSet.put(bitset, lb - 1)) == :value_out_of_bounds
rand_val = Enum.random(lb..ub)
BitSet.put(bitset, rand_val)
assert BitSet.size(bitset) == 1
assert BitSet.member?(bitset, rand_val)
BitSet.delete(bitset, rand_val)
assert BitSet.size(bitset) == 0
refute BitSet.member?(bitset, rand_val)
end
test "min and max" do
lb = -100
ub = 100
bitset = BitSet.new(lb, ub)
refute BitSet.min(bitset) || BitSet.max(bitset)
[val1, val2, val3] = Enum.take_random(lb..ub, 3) |> Enum.sort()
BitSet.put(bitset, val1)
assert BitSet.min(bitset) == val1 && BitSet.max(bitset) == val1
BitSet.put(bitset, val2)
assert BitSet.min(bitset) == val1 && BitSet.max(bitset) == val2
BitSet.delete(bitset, val1)
BitSet.put(bitset, val3)
assert BitSet.min(bitset) == val2 && BitSet.max(bitset) == val3
BitSet.delete(bitset, val2)
BitSet.delete(bitset, val3)
refute BitSet.min(bitset) || BitSet.max(bitset)
end
test "traversal" do
lb = -100
ub = 100
bitset = BitSet.new(lb, ub)
rand_values = Enum.take_random(lb..ub, Enum.random(2..(ub - lb)))
Enum.each(rand_values, fn val -> BitSet.put(bitset, val) end)
sorted_rand_values = Enum.sort(rand_values)
assert Enum.all?(0..length(rand_values) - 2,
fn idx -> BitSet.next(bitset, Enum.at(sorted_rand_values, idx)) == Enum.at(sorted_rand_values, idx + 1) end)
end
test "iteration" do
lb = -100
ub = 100
bitset = BitSet.new(lb, ub)
iterator_fun = fn value, acc -> [value | acc] end
assert Enum.empty?(BitSet.iterate(bitset, [], iterator_fun))
rand_values = Enum.take_random(lb..ub, Enum.random(2..ub - lb))
Enum.each(rand_values, fn val -> BitSet.put(bitset, val) end)
assert Enum.sort(rand_values, :desc) == BitSet.iterate(bitset, [], iterator_fun)
end
test "subset?" do
set1 = BitSet.new(-10, 10)
set2 = BitSet.new(-10, 10)
assert BitSet.subset?(set1, set2)
BitSet.put(set1, Enum.random(-10..10))
refute BitSet.subset?(set1, set2)
assert BitSet.subset?(set2, set1)
end
test "equal?" do
set1 = BitSet.new(1, 10)
set2 = BitSet.new(-10, 10)
assert BitSet.equal?(set1, set2)
Enum.each(1..10, fn val ->
BitSet.put(set1, val)
BitSet.put(set2, val)
end)
assert BitSet.equal?(set1, set2)
s = Enum.random([set1, set2])
BitSet.delete(s, Enum.random(1..10))
refute BitSet.equal?(set1, set2)
end
test "disjoint?" do
set1 = BitSet.new(-10, 10)
set2 = BitSet.new(-10, 10)
assert BitSet.disjoint?(set1, set2)
{even_values, odd_values} = Enum.split_with(-10..10, fn x -> rem(x, 2) == 0 end)
Enum.each(even_values, fn val -> BitSet.put(set1, val) end)
Enum.each(odd_values, fn val -> BitSet.put(set2, val) end)
assert BitSet.disjoint?(set1, set2)
BitSet.put(set1, Enum.random(odd_values))
refute BitSet.disjoint?(set1, set2)
end
test "intersection" do
lb = -1000
ub = 1000
set1 = BitSet.new(lb, ub)
set2 = BitSet.new(lb, ub)
intersection = BitSet.intersection(set1, set2)
assert BitSet.empty?(intersection)
{even_values, odd_values} = Enum.split_with(lb..ub, fn x -> rem(x, 2) == 0 end)
Enum.each(even_values, fn val -> BitSet.put(set1, val) end)
Enum.each(odd_values, fn val -> BitSet.put(set2, val) end)
intersection = BitSet.intersection(set1, set2)
assert BitSet.empty?(intersection)
## Add some odd values to "even values" set,
## and some even values to "odd values" set.
random_evens = Enum.take_random(even_values, 500)
random_odds = Enum.take_random(odd_values, 500)
Enum.each(random_odds, fn v -> BitSet.put(set1, v) end)
Enum.each(random_evens, fn v -> BitSet.put(set2, v) end)
intersection = BitSet.intersection(set1, set2)
assert BitSet.to_list(intersection) == (random_evens ++ random_odds) |> Enum.sort()
end
test "union" do
lb = -1000
ub = 1000
set1 = BitSet.new(lb, ub)
set2 = BitSet.new(lb, ub)
union = BitSet.union(set1, set2)
assert BitSet.empty?(union)
{even_values, odd_values} = Enum.split_with(lb..ub, fn x -> rem(x, 2) == 0 end)
Enum.each(even_values, fn val -> BitSet.put(set1, val) end)
Enum.each(odd_values, fn val -> BitSet.put(set2, val) end)
union = BitSet.union(set1, set2)
assert BitSet.to_list(union) == Enum.to_list(lb..ub)
end
test "difference" do
set = BitSet.new(-10, 10)
Enum.each(-10..10, fn val -> BitSet.put(set, val) end)
even_set = BitSet.filter(set, fn x -> rem(x, 2) == 0 end)
odd_set = BitSet.filter(set, fn x -> rem(x, 2) in [-1, 1] end)
assert BitSet.equal?(
BitSet.difference(set, even_set),
odd_set)
assert BitSet.empty?(BitSet.difference(even_set, set))
assert BitSet.empty?(BitSet.difference(odd_set, set))
end
test "symmetric difference" do
set1 = BitSet.new(-10, 10)
set2 = BitSet.new(-10, 10)
symdiff_set = BitSet.symmetric_difference(set1, set2)
assert BitSet.empty?(symdiff_set)
{even_values, odd_values} = Enum.split_with(-10..10, fn x -> rem(x, 2) == 0 end)
Enum.each(even_values, fn val -> BitSet.put(set1, val) end)
Enum.each(odd_values, fn val -> BitSet.put(set2, val) end)
symdiff_set = BitSet.symmetric_difference(set1, set2)
assert BitSet.to_list(symdiff_set) == Enum.to_list(-10..10)
## Example from `h MapSet.symmetric_difference
s1 = BitSet.new(1, 3)
s2 = BitSet.new(2, 4)
Enum.each([1, 2, 3], fn val -> BitSet.put(s1, val) end)
Enum.each([2, 3, 4], fn val -> BitSet.put(s2, val) end)
assert BitSet.symmetric_difference(s1, s2) |> BitSet.to_list() == [1, 4]
end
test "filter" do
set = BitSet.new(-10, 10)
Enum.each(-10..10, fn val -> BitSet.put(set, val) end)
{even_values, odd_values} = Enum.split_with(-10..10, fn x -> rem(x, 2) == 0 end)
even_set = BitSet.filter(set, fn x -> rem(x, 2) == 0 end)
odd_set = BitSet.filter(set, fn x -> rem(x, 2) in [-1, 1] end)
assert BitSet.to_list(even_set) == even_values
assert BitSet.to_list(odd_set) == odd_values
end
end