Skip to content

Commit 0a63ff5

Browse files
committed
Add golang solution for 011 - trie implementation & test cases
1 parent 3b5530c commit 0a63ff5

File tree

3 files changed

+221
-23
lines changed

3 files changed

+221
-23
lines changed

001-050/011/c++/code.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
using namespace std;
1010

1111
struct Node {
12-
vector<int> indices;
12+
int index; // note: using only last index instead of complete list
1313
Node* next[26];
1414

1515
Node() {
16-
indices = vector<int>();
16+
index = -1;
1717
for (int i = 0; i < 26; i++) {
1818
next[i] = NULL;
1919
}
@@ -28,13 +28,14 @@ struct Node {
2828
if (!next[c - 'a']) next[c - 'a'] = new Node();
2929
return next[c - 'a'];
3030
}
31-
void Mark(int in) { indices.push_back(in); }
31+
void Mark(int in) { index = in; }
3232
};
3333

3434
void Traverse(Node* trie, vector<int>& ans) {
3535
if (trie == NULL) return;
36-
int n = trie->indices.size();
37-
for (int j = 0; j < n; j++) ans.push_back(trie->indices[j]);
36+
if (trie->index != -1) {
37+
ans.push_back(trie->index);
38+
}
3839
for (int i = 0; i < 26; i++) {
3940
Node* next = trie->next[i];
4041
if (next) Traverse(next, ans);

001-050/011/go/code.go

+71-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,75 @@
66
// TestSolution for test cases
77
package _011
88

9-
// Solution for 011
10-
func Solution() interface{} {
11-
return nil
9+
type Trie interface {
10+
// AddWords adds more words to the dictionary of Trie
11+
AddWords(words ...string)
12+
// Search will return list of words that can completed by
13+
// provided prefix, in the order they appeared in dictionary
14+
Search(prefix string) []string
15+
// Size of trie
16+
Size() int
17+
}
18+
19+
// Add will add the word, which was
20+
func NewTrie(words ...string) Trie {
21+
n := newNode()
22+
n.size = new(int)
23+
n.AddWords(words...)
24+
return n
25+
}
26+
27+
// node: implements trie data structure
28+
type node struct {
29+
next map[rune]*node // next represent subsequent level of words
30+
isWord bool // isWord marks the completion of a word
31+
size *int // size represents the size of the dictionary in the trie
32+
}
33+
34+
func newNode() *node {
35+
return &node{next: map[rune]*node{}}
36+
}
37+
38+
func (nd *node) Size() int {
39+
return *nd.size
40+
}
41+
42+
func (nd *node) AddWords(words ...string) {
43+
for _, wd := range words {
44+
cur := nd
45+
for _, r := range wd {
46+
if _, ok := cur.next[r]; !ok {
47+
cur.next[r] = newNode()
48+
}
49+
cur = cur.next[r]
50+
}
51+
if !cur.isWord {
52+
*nd.size++
53+
cur.isWord = true
54+
} // else word was already present in trie
55+
}
56+
}
57+
58+
func (nd *node) Search(prefix string) (out []string) {
59+
cur := nd
60+
for _, r := range prefix {
61+
if _, ok := cur.next[r]; !ok {
62+
return
63+
}
64+
cur = cur.next[r]
65+
}
66+
addWord := func(wd string) {
67+
out = append(out, wd)
68+
}
69+
cur.traverse(prefix, addWord)
70+
return out
71+
}
72+
73+
func (nd *node) traverse(pre string, addWord func(string)) {
74+
if nd.isWord {
75+
addWord(pre)
76+
}
77+
for r, it := range nd.next {
78+
it.traverse(pre+string(r), addWord)
79+
}
1280
}

001-050/011/go/code_test.go

+144-15
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,155 @@ package _011
66

77
import (
88
"reflect"
9+
"sort"
10+
"strconv"
911
"testing"
1012
)
1113

12-
func TestSolution(t *testing.T) {
13-
type args struct {
14+
type unitCase struct {
15+
prefix string
16+
response []string
17+
}
18+
19+
func runTests(t *testing.T, trie Trie, tests []unitCase) {
20+
for i, tt := range tests {
21+
t.Run(strconv.Itoa(i), func(t *testing.T) {
22+
got := trie.Search(tt.prefix)
23+
sort.Strings(got)
24+
if !reflect.DeepEqual(got, tt.response) {
25+
t.Errorf("trie.Search() = %v, want %v", got, tt.response)
26+
}
27+
})
1428
}
15-
type want struct {
29+
}
30+
31+
func TestTrie_SizeAndSearch(t *testing.T) {
32+
dict := []string{
33+
"deari", "deeli", "dog", "dear", "dearw", "deelw", "doge",
34+
"deare", "deele", "doga", "dogt", "deart", "deara", "doga",
35+
"dogy", "deary", "deely", "dogu", "dearu", "deelu", "world",
36+
"dogi", "deeld", "deelr", "deelo", "dogp", "deelt", "deel",
37+
"dearp", "deelp", "doga", "dogo", "dearo", "deela", "dears",
38+
"dogw", "deels", "dogd", "deard", "dream", "apple", "dogs",
39+
"deelt", "dear", "dogr", "dearr", "doga", "cream", "apple",
1640
}
17-
tests := []struct {
18-
name string
19-
args args
20-
want want
21-
}{
22-
// TODO: Add test cases.
41+
unique := 0
42+
mp := map[string]struct{}{}
43+
for _, wd := range dict {
44+
if _, ok := mp[wd]; !ok {
45+
unique++
46+
mp[wd] = struct{}{}
47+
}
2348
}
24-
for _, tt := range tests {
25-
t.Run(tt.name, func(t *testing.T) {
26-
if got := Solution(); !reflect.DeepEqual(got, tt.want) {
27-
t.Errorf("Solution() = %v, want %v", got, tt.want)
28-
}
29-
})
49+
trie := NewTrie(dict...)
50+
// size of dictionary == unique
51+
if got := trie.Size(); got != unique {
52+
t.Errorf("trie.Size() = %v, want %v", got, unique)
53+
}
54+
55+
tests := []unitCase{
56+
{
57+
prefix: "de",
58+
response: []string{
59+
"dear", "deara", "deard", "deare", "deari", "dearo", "dearp",
60+
"dearr", "dears", "deart", "dearu", "dearw", "deary", "deel",
61+
"deela", "deeld", "deele", "deeli", "deelo", "deelp", "deelr",
62+
"deels", "deelt", "deelu", "deelw", "deely",
63+
},
64+
},
65+
{
66+
prefix: "dea",
67+
response: []string{
68+
"dear", "deara", "deard", "deare", "deari", "dearo", "dearp",
69+
"dearr", "dears", "deart", "dearu", "dearw", "deary",
70+
},
71+
},
72+
{
73+
prefix: "dee",
74+
response: []string{
75+
"deel", "deela", "deeld", "deele", "deeli", "deelo", "deelp",
76+
"deelr", "deels", "deelt", "deelu", "deelw", "deely",
77+
},
78+
},
79+
{
80+
prefix: "a",
81+
response: []string{"apple"},
82+
},
83+
{
84+
prefix: "did",
85+
response: nil,
86+
},
87+
{
88+
prefix: "git",
89+
response: nil,
90+
},
3091
}
92+
runTests(t, trie, tests)
93+
}
94+
95+
func TestTrie_AddWords(t *testing.T) {
96+
dict := []string{"aa", "dog", "mock"}
97+
trie := NewTrie(dict...)
98+
// run before adding more words
99+
runTests(t, trie, []unitCase{
100+
{
101+
prefix: "a",
102+
response: []string{"aa"},
103+
},
104+
{
105+
prefix: "og",
106+
response: nil,
107+
},
108+
{
109+
prefix: "dog",
110+
response: []string{"dog"},
111+
},
112+
{
113+
prefix: "mock",
114+
response: []string{"mock"},
115+
},
116+
{
117+
prefix: "chock",
118+
response: nil,
119+
},
120+
{
121+
prefix: "mockery",
122+
response: nil,
123+
},
124+
})
125+
126+
// add more words
127+
trie.AddWords(
128+
"shock", "mockery", "mock",
129+
"ogy", "dog-cat", "shame", "kam",
130+
"apple", "shop", "mark",
131+
)
132+
133+
// run after adding more words
134+
runTests(t, trie, []unitCase{
135+
{
136+
prefix: "a",
137+
response: []string{"aa", "apple"},
138+
},
139+
{
140+
prefix: "og",
141+
response: []string{"ogy"},
142+
},
143+
{
144+
prefix: "dog",
145+
response: []string{"dog", "dog-cat"},
146+
},
147+
{
148+
prefix: "mock",
149+
response: []string{"mock", "mockery"},
150+
},
151+
{
152+
prefix: "chock",
153+
response: nil,
154+
},
155+
{
156+
prefix: "mockery",
157+
response: []string{"mockery"},
158+
},
159+
})
31160
}

0 commit comments

Comments
 (0)