Skip to content

Commit

Permalink
Fixes #4 - Add immutable remove operation
Browse files Browse the repository at this point in the history
  • Loading branch information
xprazak2 committed Jun 22, 2021
1 parent 422d733 commit b93db3d
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
18 changes: 18 additions & 0 deletions trie/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,21 @@ func (trie *Trie) RemoveAtDepth(depth int, q key.Key) (reachedDepth int, removed
}
}
}

func Remove(trie *Trie, q key.Key) (*Trie) {
return RemoveAtDepth(0, trie, q)
}

func RemoveAtDepth(depth int, trie *Trie, q key.Key) (*Trie) {
switch {
case trie.IsEmptyLeaf() || trie.IsNonEmptyLeaf():
return &Trie{}
default:
dir := q.BitAt(depth)
copy := &Trie{}
copy.Branch[dir] = RemoveAtDepth(depth + 1, trie.Branch[dir], q)
copy.Branch[1 - dir] = trie.Branch[1 - dir]
copy.shrink()
return copy
}
}
62 changes: 62 additions & 0 deletions trie/remove_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package trie

import (
"testing"
"math/rand"
)

func TestImmutableRemoveIsImmutable(t *testing.T) {
for _, keySet := range testAddSamples {
trie := FromKeys(keySet.Keys)
for _, key := range keySet.Keys {
updated := Remove(trie, key)
if Equal(trie, updated) {
t.Fatalf("immuatble remove should not mutate trie, original: %v, updated: %v", trie, updated)
}
trie = updated
}
}
}

func TestMutableAndImmutableRemoveSame(t *testing.T) {
for _, keySet := range append(testAddSamples, randomTestAddSamples(100)...) {
mut := FromKeys(keySet.Keys)
immut := FromKeys(keySet.Keys)

for _, key := range keySet.Keys {
mut.Remove(key)
immut = Remove(immut, key)
if d := mut.CheckInvariant(); d != nil {
t.Fatalf("mutable trie invariant discrepancy: %v", d)
}
if d := immut.CheckInvariant(); d != nil {
t.Fatalf("immutable trie invariant discrepancy: %v", d)
}
if !Equal(mut, immut) {
t.Errorf("mutable trie %v differs from immutable trie %v", mut, immut)
}
}
}
}

func TestRemoveIsOrderIndependent(t *testing.T) {
for _, keySet := range append(testAddSamples, randomTestAddSamples(100)...) {
mut := FromKeys(keySet.Keys)
immut := FromKeys(keySet.Keys)

for j := 0; j < 100; j++ {
perm := rand.Perm(len(keySet.Keys))
for _, idx := range perm {
mut.Remove(keySet.Keys[idx])
immut = Remove(immut, keySet.Keys[idx])

if d := immut.CheckInvariant(); d != nil {
t.Fatalf("trie invariant discrepancy: %v", d)
}
if !Equal(mut, immut) {
t.Errorf("trie %v differs from trie %v", mut, immut)
}
}
}
}
}

0 comments on commit b93db3d

Please sign in to comment.