-
Notifications
You must be signed in to change notification settings - Fork 0
/
day14.go
122 lines (109 loc) · 2.56 KB
/
day14.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
)
func day14() {
lines := getLines("input/14.txt")
grid := toByteGrid(lines)
rollNorth(grid)
part1 := countRocks(grid)
rollWest(grid)
rollSouth(grid)
rollEast(grid)
part2 := countRocks(grid)
previous := map[string]int{gridToString(grid): 1}
targetCycle := 1000000000
for cycle := 2; cycle <= targetCycle; cycle++ {
rollNorth(grid)
rollWest(grid)
rollSouth(grid)
rollEast(grid)
part2 = countRocks(grid)
hash := gridToString(grid)
if cycleStart, found := previous[hash]; found {
cycleLength := cycle - cycleStart
for ; cycle <= targetCycle && ((targetCycle-cycle)%cycleLength) != 0; cycle++ {
rollNorth(grid)
rollWest(grid)
rollSouth(grid)
rollEast(grid)
part2 = countRocks(grid)
}
break
}
previous[hash] = cycle
}
var result = part1
var result2 = part2
fmt.Println("Day 14 Part 1 Result: ", result)
fmt.Println("Day 14 Part 2 Result: ", result2)
}
func gridToString(grid [][]byte) string {
data := make([]byte, 0, len(grid)*len(grid[0]))
for _, line := range grid {
data = append(data, line...)
}
return string(data)
}
func countRocks(grid [][]byte) int {
result := 0
for row := len(grid) - 1; row >= 0; row-- {
for _, val := range grid[row] {
if val == 'O' {
result += len(grid) - row
}
}
}
return result
}
func rollNorth(grid [][]byte) {
for row := 0; row < len(grid); row++ {
for col, val := range grid[row] {
if val == 'O' {
for i := row - 1; i >= 0 && grid[i][col] == '.'; i-- {
grid[i+1][col], grid[i][col] = grid[i][col], grid[i+1][col]
}
}
}
}
}
func rollWest(grid [][]byte) {
for col := 0; col < len(grid[0]); col++ {
for row, line := range grid {
if line[col] == 'O' {
for i := col - 1; i >= 0 && grid[row][i] == '.'; i-- {
grid[row][i+1], grid[row][i] = grid[row][i], grid[row][i+1]
}
}
}
}
}
func rollSouth(grid [][]byte) {
for row := len(grid) - 1; row >= 0; row-- {
for col, val := range grid[row] {
if val == 'O' {
for i := row + 1; i < len(grid) && grid[i][col] == '.'; i++ {
grid[i-1][col], grid[i][col] = grid[i][col], grid[i-1][col]
}
}
}
}
}
func rollEast(grid [][]byte) {
for col := len(grid[0]) - 1; col >= 0; col-- {
for row, line := range grid {
if line[col] == 'O' {
for i := col + 1; i < len(grid[0]) && grid[row][i] == '.'; i++ {
grid[row][i-1], grid[row][i] = grid[row][i], grid[row][i-1]
}
}
}
}
}
func toByteGrid(grid []string) [][]byte {
bytes := make([][]byte, 0, len(grid))
for _, line := range grid {
bytes = append(bytes, []byte(line))
}
return bytes
}