Skip to content

Commit 0e41a85

Browse files
authored
Add files via upload
1 parent dd0884e commit 0e41a85

File tree

2 files changed

+257
-0
lines changed

2 files changed

+257
-0
lines changed

complist.go

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package complist
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"strconv"
7+
)
8+
9+
//IsSame checks whether two items have an identical collection of elements
10+
func IsSame(a, b interface{}) (bool, error) {
11+
if reflect.TypeOf(a) != reflect.TypeOf(b) {
12+
return false, fmt.Errorf("element type mismatch: %v doesn't match %v", reflect.TypeOf(a), reflect.TypeOf(b))
13+
}
14+
//Values to pass through the switch statement
15+
vala := reflect.ValueOf(a)
16+
valb := reflect.ValueOf(b)
17+
//only one item.Kind is needed since both need to be identical to reach this point
18+
switch vala.Kind() {
19+
case reflect.String:
20+
return IsSameString(vala.String(), valb.String()), nil
21+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
22+
return IsSameNumber(getIntDigits(int(vala.Uint())), getIntDigits(int(valb.Uint()))), nil
23+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
24+
return IsSameNumber(getIntDigits(int(vala.Int())), getIntDigits(int(valb.Int()))), nil
25+
case reflect.Float32, reflect.Float64:
26+
return false, fmt.Errorf("can't analyze floats")
27+
case reflect.Array:
28+
return IsSameArray(vala, valb), nil
29+
case reflect.Map:
30+
return IsSameMap(vala, valb), nil
31+
case reflect.Slice:
32+
return IsSameSlice(vala, valb), nil
33+
case reflect.Struct:
34+
return false, fmt.Errorf("can't analyze structs... yet")
35+
}
36+
return false, nil
37+
}
38+
39+
//IsSameString compares strings
40+
func IsSameString(a, b string) bool {
41+
al := len(a)
42+
bl := len(b)
43+
if al != bl {
44+
return false
45+
}
46+
//setting up memory maps for comparison
47+
ma := make(map[byte]int)
48+
mb := make(map[byte]int)
49+
//populating both maps
50+
for i := 0; i < al; i++ {
51+
ma[a[i]]++
52+
}
53+
for i := 0; i < bl; i++ {
54+
mb[b[i]]++
55+
}
56+
//comparing one map to the other. This is ok, since they're the same length.
57+
for k, v := range ma {
58+
if mb[k] != v {
59+
return false
60+
}
61+
}
62+
return true
63+
}
64+
65+
//IsSameNumber checks whether two numbers have the same collection of digits.
66+
func IsSameNumber(a, b []int) bool {
67+
al := len(a)
68+
bl := len(b)
69+
if al != bl {
70+
return false
71+
}
72+
//setting up memory maps for comparison
73+
ma := make(map[int]int)
74+
mb := make(map[int]int)
75+
//populating the maps
76+
for i := 0; i < al; i++ {
77+
ma[a[i]]++
78+
}
79+
for i := 0; i < bl; i++ {
80+
mb[b[i]]++
81+
}
82+
//comparing the two maps against each other.
83+
for k, v := range ma {
84+
if mb[k] != v {
85+
return false
86+
}
87+
}
88+
89+
return true
90+
}
91+
92+
//IsSameSlice compares two slices according to the collection of their elements
93+
func IsSameSlice(a, b reflect.Value) bool {
94+
al := a.Len()
95+
bl := b.Len()
96+
if al != bl {
97+
return false
98+
}
99+
//setting up memory maps for comparison
100+
ma := make(map[interface{}]int)
101+
mb := make(map[interface{}]int)
102+
//populating the maps
103+
for i := 0; i < al; i++ {
104+
ma[a.Index(i).Interface()]++
105+
}
106+
for i := 0; i < bl; i++ {
107+
mb[b.Index(i).Interface()]++
108+
}
109+
//comparing the two maps against each other.
110+
for k, v := range ma {
111+
if mb[k] != v {
112+
return false
113+
}
114+
}
115+
return true
116+
}
117+
118+
//IsSameMap compares two maps element by element.
119+
func IsSameMap(a, b reflect.Value) bool {
120+
//making sure both maps have the same number of elements.
121+
if a.Len() != b.Len() {
122+
return false
123+
}
124+
//only one map is needed for checking. Any discrepancies will fail the test.
125+
ak := a.MapKeys() //getting the keys for map 'a'.
126+
//Comparing the two maps with the key from map 'a'.
127+
for _, key := range ak {
128+
if a.MapIndex(key).Interface() != b.MapIndex(key).Interface() {
129+
return false
130+
}
131+
}
132+
return true
133+
}
134+
135+
//IsSameArray compares two arrays according to the collection of their elements
136+
func IsSameArray(a, b reflect.Value) bool {
137+
//setting up memory maps for comparison
138+
ma := make(map[interface{}]int)
139+
mb := make(map[interface{}]int)
140+
//populating the maps
141+
for i := 0; i < a.Len(); i++ {
142+
ma[a.Index(i).Interface()]++
143+
}
144+
for i := 0; i < b.Len(); i++ {
145+
mb[b.Index(i).Interface()]++
146+
}
147+
//comparing the two maps against each other.
148+
for k, v := range ma {
149+
if mb[k] != v {
150+
return false
151+
}
152+
}
153+
return true
154+
}
155+
156+
func getIntDigits(n int) []int {
157+
var ret []int
158+
//could've converted to string and then interpreted each digit, but this was more fun.
159+
if n < 10 {
160+
return append(ret, n)
161+
}
162+
ret = append(ret, n%10)
163+
n = n / 10
164+
165+
return append(ret, getIntDigits(n)...)
166+
}
167+
168+
func getUIntDigits(n uint) []uint {
169+
var ret []uint
170+
//Same as with int.
171+
if n < 10 {
172+
return append(ret, n)
173+
}
174+
ret = append(ret, n%10)
175+
n = n / 10
176+
177+
return append(ret, getUIntDigits(n)...)
178+
179+
}
180+
181+
//non-function code at this point. Floats act funny when you shift decimals around.
182+
func getFloat64Digits(n float64) []int {
183+
s := fmt.Sprint(n)
184+
var ret []rune
185+
for _, char := range s {
186+
if char >= '0' && char <= '9' {
187+
ret = append(ret, char)
188+
}
189+
}
190+
ss, _ := strconv.Atoi(string(ret))
191+
return getIntDigits(ss)
192+
}

complist_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package complist
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestIsSame(t *testing.T) {
9+
table := []struct {
10+
a interface{}
11+
b interface{}
12+
ans bool
13+
}{
14+
{"home", "ohme", true},
15+
{"home", "emoh", true},
16+
{"balaclava", "bllaacava", true},
17+
{"doggo", "odgog", true},
18+
{"anagram", "analytical", false},
19+
{"sitting", "stingin", false},
20+
{"string", "stirng", true},
21+
{"ocean", "Ocean", false},
22+
{"122345", "12345", false},
23+
{"122345", "1223345", false},
24+
{"12345", "54321", true},
25+
{int16(1234), int16(4321), true},
26+
{122345, 1223345, false},
27+
{12.2345, 1223.345, false},
28+
{12.23345, 12233.45, false},
29+
{float32(12.23), float32(122.3), false},
30+
{int64(122345), int64(12345), false},
31+
{int64(122345), int64(1235), false},
32+
{uint16(2345), uint16(5432), true},
33+
{int32(12345111), int32(54321111), true},
34+
{uint32(12345111), uint32(54321111), true},
35+
{uint64(12345111), uint64(54321111), true},
36+
{[]string{"a", "b", "c"}, []string{"a", "bc"}, false},
37+
{[]string{"a", "b", "c"}, []string{"a", "b", "c"}, true},
38+
{[]int{1, 1, 2}, []int{1, 2, 3}, false},
39+
{[]int{1, 1, 2}, []int{1, 2, 3, 4}, false},
40+
{[]int{1, 1, 1}, []int{1, 2, 3}, false},
41+
{[]float64{1.2, 2.37, 3}, []float64{1.2, 2.37, 3}, true},
42+
{map[int]int{1: 1, 2: 3, 3: 25}, map[int]int{1: 1, 2: 3, 3: 25}, true},
43+
{map[string]int{"1": 1, "2": 3, "3": 25}, map[string]int{"1": 1, "2": 3, "3": 25}, true},
44+
{map[string]int{"1": 1, "2": 3, "3": 25}, map[string]int{"1": 1, "3": 25, "2": 3}, true},
45+
{map[int]int{1: 1, 2: 3, 3: 25}, map[int]int{1: 1, 2: 3, 3: 25, 4: 13}, false},
46+
{map[string]int{"1": 1, "2": 3, "3": 25}, map[string]int{"1": 1, "2": 3, "3": 25, "4": 13}, false},
47+
{[3]int{1, 1, 2}, [3]int{1, 2, 3}, false},
48+
{[3]int{1, 1, 2}, [4]int{1, 2, 3, 4}, false},
49+
{[3]int{1, 1, 1}, [3]int{1, 2, 3}, false},
50+
{[3]int{1, 2, 3}, [3]int{1, 2, 3}, true},
51+
{[3]int{1, 2, 3}, [3]int{1, 3, 2}, true},
52+
{[3]string{"1", "string", "$#"}, [3]string{"string", "$#", "1"}, true},
53+
{[3]bool{true, true, false}, [3]bool{false, true, true}, true},
54+
}
55+
56+
for _, line := range table {
57+
issame, err := IsSame(line.a, line.b)
58+
if err != nil {
59+
fmt.Println("error encountered: ", err)
60+
}
61+
if issame != line.ans {
62+
t.Errorf("IsSame error for : %v & %v. Want %v, got %v", line.a, line.b, line.ans, issame)
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)