Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 259
Good morning! Here's your coding interview problem for today.

This problem was asked by Two Sigma.

Ghost is a two-person word game where players alternate appending letters to a word. The first person who spells out a word, or creates a prefix for which there is no possible continuation, loses. Here is a sample game:
```
Player 1: g
Player 2: h
Player 1: o
Player 2: s
Player 1: t [loses]
```
Given a dictionary of words, determine the letters the first player should start with, such that with optimal play they cannot lose.

For example, if the dictionary is `["cat", "calf", "dog", "bear"]`, the only winning start letter would be `b`.

Pull request description:
Day259
Resolves #531.

Patch:
diff --git a/README.md b/README.md
index 2b80f07..f354034 100644
--- a/README.md
+++ b/README.md
@@ -270,6 +270,7 @@ problems from
 * [Day 256](https://github.com/vaskoz/dailycodingproblem-go/issues/528)
 * [Day 257](https://github.com/vaskoz/dailycodingproblem-go/issues/529)
 * [Day 258](https://github.com/vaskoz/dailycodingproblem-go/issues/530)
+* [Day 259](https://github.com/vaskoz/dailycodingproblem-go/issues/531)
 * [Day 260](https://github.com/vaskoz/dailycodingproblem-go/issues/533)
 * [Day 263](https://github.com/vaskoz/dailycodingproblem-go/issues/539)
 * [Day 266](https://github.com/vaskoz/dailycodingproblem-go/issues/542)
diff --git a/day259/problem.go b/day259/problem.go
new file mode 100644
index 0000000..201736f
--- /dev/null
+++ b/day259/problem.go
@@ -0,0 +1,30 @@
+package day259
+
+import "sort"
+
+// GhostWinningLetterPlayerOne determine the letters the
+// first player should start with, such that with optimal
+// play they cannot lose.
+func GhostWinningLetterPlayerOne(dict []string) []rune {
+	firstRuneAllEven := make(map[rune]bool)
+	for _, word := range dict {
+		runes := []rune(word)
+		isEvenLength := len(runes)%2 == 0
+		firstRune := runes[0]
+		if _, found := firstRuneAllEven[firstRune]; !isEvenLength {
+			firstRuneAllEven[firstRune] = false
+		} else if !found && isEvenLength {
+			firstRuneAllEven[firstRune] = true
+		}
+	}
+	var result []rune
+	for r, valid := range firstRuneAllEven {
+		if valid {
+			result = append(result, r)
+		}
+	}
+	sort.Slice(result, func(i, j int) bool {
+		return result[i] < result[j]
+	})
+	return result
+}


Test patch:
diff --git a/day259/problem_test.go b/day259/problem_test.go
new file mode 100644
index 0000000..3b1470a
--- /dev/null
+++ b/day259/problem_test.go
@@ -0,0 +1,32 @@
+package day259
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	dict   []string
+	result []rune
+}{
+	{[]string{"cat", "calf", "dog", "bear"}, []rune{'b'}},
+	{[]string{"cat", "calf", "dog", "bear", "pear", "pair"}, []rune{'b', 'p'}},
+}
+
+func TestGhostWinningLetterPlayerOne(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if result := GhostWinningLetterPlayerOne(tc.dict); !reflect.DeepEqual(result, tc.result) {
+			t.Errorf("Expected %v, got %v", string(tc.result), string(result))
+		}
+	}
+}
+
+func BenchmarkGhostWinningLetterPlayerOne(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			GhostWinningLetterPlayerOne(tc.dict)
+		}
+	}
+}