Skip to content

Commit 09dd4b7

Browse files
Merge pull request #7 from anurag-prakash-singh/up-to-gam-of-life
Up to game-of-life
2 parents 22ccd90 + e5bbb71 commit 09dd4b7

7 files changed

+766
-0
lines changed

alien-dictionary.go

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
func slicesMatch(a, b []rune) bool {
9+
if len(a) != len(b) {
10+
return false
11+
}
12+
13+
for i := 0; i < len(a); i++ {
14+
if a[i] != b[i] {
15+
return false
16+
}
17+
}
18+
19+
return true
20+
}
21+
22+
func max(a, b int) int {
23+
if a > b {
24+
return a
25+
}
26+
27+
return b
28+
}
29+
30+
func runeExists(runes []rune, r rune) bool {
31+
for _, c := range runes {
32+
if c == r {
33+
return true
34+
}
35+
}
36+
37+
return false
38+
}
39+
40+
func topologicalOrder(starting rune, adjMat map[rune][]rune, visitedInPriorTraversal, visited map[rune]bool, orderSoFar string) (string, error) {
41+
if visited[starting] {
42+
return "", errors.New("already visited " + string(starting))
43+
}
44+
45+
visited[starting] = true
46+
47+
adjs := adjMat[starting]
48+
49+
// if !ok || len(adjs) == 0 {
50+
// return orderSoFar + string(starting), nil
51+
// }
52+
53+
for _, a := range adjs {
54+
if !visitedInPriorTraversal[a] {
55+
var err error
56+
orderSoFar, err = topologicalOrder(a, adjMat, visitedInPriorTraversal, visited, orderSoFar)
57+
58+
if err != nil {
59+
return "", err
60+
}
61+
}
62+
}
63+
64+
return orderSoFar + string(starting), nil
65+
}
66+
67+
func reverse(s string) string {
68+
runes := []rune(s)
69+
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
70+
runes[i], runes[j] = runes[j], runes[i]
71+
}
72+
return string(runes)
73+
}
74+
75+
func alienOrder(words []string) string {
76+
inEdges := make(map[rune]int)
77+
alphabet := make(map[rune]bool)
78+
wordChars := make([][]rune, len(words))
79+
maxWordLen := 0
80+
81+
for i, str := range words {
82+
wordChars[i] = []rune(str)
83+
84+
if len(str) > maxWordLen {
85+
maxWordLen = len(str)
86+
}
87+
88+
for _, c := range wordChars[i] {
89+
inEdges[c] = 0
90+
alphabet[c] = true
91+
}
92+
}
93+
94+
adjMat := make(map[rune][]rune)
95+
96+
for letterOffset := 0; letterOffset < maxWordLen; letterOffset++ {
97+
for wordOffset := 0; wordOffset < len(words); wordOffset++ {
98+
if len(words[wordOffset]) <= letterOffset {
99+
continue
100+
}
101+
102+
wordChar := wordChars[wordOffset][letterOffset]
103+
_, ok := adjMat[wordChar]
104+
105+
if !ok {
106+
adjMat[wordChar] = []rune{}
107+
}
108+
109+
if wordOffset == 0 {
110+
continue
111+
}
112+
113+
if letterOffset > 0 && (letterOffset >= len(wordChars[wordOffset-1]) || !slicesMatch(wordChars[wordOffset][0:letterOffset], wordChars[wordOffset-1][0:letterOffset])) {
114+
continue
115+
}
116+
117+
preChar := wordChars[wordOffset-1][letterOffset]
118+
119+
if !runeExists(adjMat[preChar], wordChar) && preChar != wordChar {
120+
adjMat[preChar] = append(adjMat[preChar], wordChar)
121+
inEdges[wordChar]++
122+
}
123+
}
124+
}
125+
126+
// for k, v := range adjMat {
127+
// fmt.Printf("%c -> %s\n", k, string(v))
128+
// }
129+
130+
visitedInPriorTraversal := make(map[rune]bool)
131+
orderSoFar := ""
132+
133+
for k, _ := range alphabet {
134+
if inEdges[k] > 0 {
135+
// We only want to start traversing from root characters
136+
continue
137+
}
138+
139+
if !visitedInPriorTraversal[k] {
140+
var err error
141+
visited := map[rune]bool{}
142+
orderSoFar, err = topologicalOrder(k, adjMat, visitedInPriorTraversal, visited, orderSoFar)
143+
144+
for visitedK, visitedV := range visited {
145+
visitedInPriorTraversal[visitedK] = visitedV
146+
}
147+
148+
if orderSoFar == "" || err != nil {
149+
return ""
150+
}
151+
}
152+
}
153+
154+
return reverse(orderSoFar)
155+
}
156+
157+
func tests() {
158+
testCases := [][]string{
159+
[]string{"z", "x"},
160+
[]string{"wrt", "wrf", "er", "ett", "rftt"},
161+
[]string{"wrt", "wrfb", "wrff", "er", "ett", "rftt"},
162+
[]string{"z", "x", "z"},
163+
[]string{"abc"},
164+
[]string{"a"},
165+
[]string{""},
166+
[]string{"ab", "d", "b"},
167+
}
168+
169+
for i, tc := range testCases {
170+
result := alienOrder(tc)
171+
172+
fmt.Printf("testcase %d: result: %s\n", i, result)
173+
}
174+
}
175+
176+
func main() {
177+
tests()
178+
}

game-of-life.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func getOrig(n int) int {
6+
if n < 10 {
7+
return n
8+
}
9+
10+
if n == 10 {
11+
return 0
12+
}
13+
14+
return 1
15+
}
16+
17+
func getNew(n int) int {
18+
if n < 10 {
19+
return n
20+
}
21+
22+
if n == 10 {
23+
return 1
24+
}
25+
26+
return 0
27+
}
28+
29+
func countLiveNeighbors(board [][]int, atR, atC int) int {
30+
dirR := []int{-1, -1, -1, 0, 0, 1, 1, 1}
31+
dirC := []int{-1, 0, 1, -1, 1, -1, 0, 1}
32+
numRows := len(board)
33+
numCols := len(board[0])
34+
numLiveNeighbors := 0
35+
36+
for i := 0; i < len(dirR); i++ {
37+
nbrR, nbrC := atR+dirR[i], atC+dirC[i]
38+
39+
if nbrR < 0 || nbrR >= numRows || nbrC < 0 || nbrC >= numCols {
40+
continue
41+
}
42+
43+
numLiveNeighbors += getOrig(board[nbrR][nbrC])
44+
}
45+
46+
return numLiveNeighbors
47+
}
48+
49+
func gameOfLife(board [][]int) {
50+
numRows := len(board)
51+
numCols := len(board[0])
52+
53+
for i := 0; i < numRows; i++ {
54+
for j := 0; j < numCols; j++ {
55+
numLiveNeighbors := countLiveNeighbors(board, i, j)
56+
57+
if numLiveNeighbors < 2 {
58+
if board[i][j] == 1 {
59+
board[i][j] = 11
60+
}
61+
} else if numLiveNeighbors < 4 {
62+
// 2 or 3
63+
if numLiveNeighbors == 3 && getOrig(board[i][j]) == 0 {
64+
board[i][j] = 10
65+
}
66+
} else {
67+
// more than 3
68+
if getOrig(board[i][j]) == 1 {
69+
board[i][j] = 11
70+
}
71+
}
72+
}
73+
}
74+
75+
for i := 0; i < numRows; i++ {
76+
for j := 0; j < numCols; j++ {
77+
board[i][j] = getNew(board[i][j])
78+
}
79+
}
80+
}
81+
82+
func test1() {
83+
board := [][]int{
84+
[]int{0, 1, 0},
85+
[]int{0, 0, 1},
86+
[]int{1, 1, 1},
87+
[]int{0, 0, 0},
88+
}
89+
90+
gameOfLife(board)
91+
92+
fmt.Printf("new board: %v\n", board)
93+
}
94+
95+
func main() {
96+
test1()
97+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func min(a, b int) int {
6+
if a < b {
7+
return a
8+
}
9+
10+
return b
11+
}
12+
13+
func findMinInsertions(str string) int {
14+
chars := []rune(str)
15+
n := len(str)
16+
dp := make([][]int, n)
17+
18+
for i := 0; i < n; i++ {
19+
dp[i] = make([]int, n)
20+
}
21+
22+
for i := 0; i < n; i++ {
23+
}
24+
25+
for l := 2; l <= n; l++ {
26+
for lo := 0; lo <= n-l; lo++ {
27+
hi := lo + l - 1
28+
29+
if chars[lo] == chars[hi] {
30+
if hi == lo+1 {
31+
dp[lo][hi] = 0
32+
} else {
33+
dp[lo][hi] = dp[lo+1][hi-1]
34+
}
35+
} else {
36+
dp[lo][hi] = 1 + min(dp[lo+1][hi], dp[lo][hi-1])
37+
}
38+
}
39+
}
40+
41+
return dp[0][n-1]
42+
}
43+
44+
type testCase struct {
45+
str string
46+
expectedResult int
47+
}
48+
49+
func tests() {
50+
testCases := []testCase{
51+
testCase{str: "ab", expectedResult: 1},
52+
testCase{str: "aa", expectedResult: 0},
53+
testCase{str: "abcd", expectedResult: 3},
54+
testCase{str: "abcda", expectedResult: 2},
55+
testCase{str: "abcde", expectedResult: 4},
56+
}
57+
58+
for i, tc := range testCases {
59+
result := findMinInsertions(tc.str)
60+
61+
if result != tc.expectedResult {
62+
fmt.Printf("Test %d FAILED. Expected %d, got %d\n", i, tc.expectedResult, result)
63+
} else {
64+
fmt.Printf("Test %d PASSED\n", i)
65+
}
66+
}
67+
}
68+
69+
func main() {
70+
tests()
71+
}

0 commit comments

Comments
 (0)