Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 395
Good morning! Here's your coding interview problem for today.

This problem was asked by Robinhood.

Given an array of strings, group anagrams together.

For example, given the following array:

`['eat', 'ate', 'apt', 'pat', 'tea', 'now']`
Return:
```
[['eat', 'ate', 'tea'],
 ['apt', 'pat'],
 ['now']]
```

Pull request description:
Day395
Resolves #793.

Patch:
diff --git a/README.md b/README.md
index 43dc9ed..5b3d870 100644
--- a/README.md
+++ b/README.md
@@ -387,4 +387,5 @@ problems from
 * [Day 392](https://github.com/vaskoz/dailycodingproblem-go/issues/787)
 * [Day 393](https://github.com/vaskoz/dailycodingproblem-go/issues/789)
 * [Day 394](https://github.com/vaskoz/dailycodingproblem-go/issues/791)
+* [Day 395](https://github.com/vaskoz/dailycodingproblem-go/issues/793)
 
diff --git a/day395/problem.go b/day395/problem.go
new file mode 100644
index 0000000..f24a15c
--- /dev/null
+++ b/day395/problem.go
@@ -0,0 +1,35 @@
+package day395
+
+import "sort"
+
+// GroupByAnagram returns a slice of slices of strings
+// grouped by their anagrams.
+func GroupByAnagram(words []string) [][]string {
+	m := make(map[string][]string)
+	pos := make(map[string]int)
+	posI := 0
+
+	for _, word := range words {
+		ana := []rune(word)
+		sort.Slice(ana, func(i, j int) bool {
+			return ana[i] < ana[j]
+		})
+
+		anaKey := string(ana)
+
+		if _, seen := pos[anaKey]; !seen {
+			pos[anaKey] = posI
+			posI++
+		}
+
+		m[anaKey] = append(m[anaKey], word)
+	}
+
+	res := make([][]string, len(m))
+
+	for k, v := range m {
+		res[pos[k]] = v
+	}
+
+	return res
+}


Test patch:
diff --git a/day395/problem_test.go b/day395/problem_test.go
new file mode 100644
index 0000000..69dcf3a
--- /dev/null
+++ b/day395/problem_test.go
@@ -0,0 +1,39 @@
+package day395
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	words    []string
+	expected [][]string
+}{
+	{
+		[]string{"eat", "ate", "apt", "pat", "tea", "now"},
+		[][]string{
+			{"eat", "ate", "tea"},
+			{"apt", "pat"},
+			{"now"},
+		},
+	},
+}
+
+func TestGroupByAnagram(t *testing.T) {
+	t.Parallel()
+
+	for _, tc := range testcases {
+		if res := GroupByAnagram(tc.words); !reflect.DeepEqual(res, tc.expected) {
+			t.Errorf("Expected %v, got %v", tc.expected, res)
+		}
+	}
+}
+
+func BenchmarkGroupByAnagram(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			GroupByAnagram(tc.words)
+		}
+	}
+}