-
Notifications
You must be signed in to change notification settings - Fork 0
/
11.go
154 lines (130 loc) · 2.71 KB
/
11.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package main
import (
"fmt"
"io/ioutil"
"strings"
)
type position struct {
x, y int
}
type seatLayout struct {
rowLength, colLength int
grid map[position]bool
}
type seatingRule struct {
stayWhile int
occupiedSeatsSeenFrom occupiedSeatsSeenFunc
}
type occupiedSeatsSeenFunc = func(position, *seatLayout) int
var rule01 = seatingRule{3, rule01Func}
var rule02 = seatingRule{4, rule02Func}
var newLine = "\r\n"
var directions = []position{
{-1, -1},
{-1, 0},
{-1, 1},
{0, -1},
{0, 1},
{1, -1},
{1, 0},
{1, 1},
}
func main() {
tiles := prepareInput(parseInput())
seats := makeSeats(tiles)
for c := 1; c > 0; {
c = changeSeats(&seats, rule01)
}
fmt.Println("01")
fmt.Println(seats.occupied())
seats = makeSeats(tiles)
for c := 1; c > 0; {
c = changeSeats(&seats, rule02)
}
fmt.Println("02")
fmt.Println(seats.occupied())
}
func changeSeats(seats *seatLayout, rule seatingRule) int {
newGrid := make(map[position]bool)
changes := 0
for pos, occ := range seats.grid {
switch occs := rule.occupiedSeatsSeenFrom(pos, seats); {
case occs == 0 && !occ:
changes++
newGrid[pos] = true
case occs > rule.stayWhile && occ:
changes++
newGrid[pos] = false
default:
newGrid[pos] = occ
}
}
seats.grid = newGrid
return changes
}
func rule02Func(pos position, seats *seatLayout) int {
occs := 0
directions:
for _, ver := range directions {
for i, j := pos.x+ver.x, pos.y+ver.y; i < seats.rowLength && i >= 0 && j < seats.colLength && j >= 0; i, j = i+ver.x, j+ver.y {
if occ, ok := seats.grid[position{i, j}]; ok {
if occ {
occs++
}
continue directions
}
}
}
return occs
}
func rule01Func(pos position, seats *seatLayout) int {
occs := 0
for _, ver := range directions {
if occ, ok := seats.grid[position{pos.x + ver.x, pos.y + ver.y}]; ok {
if occ {
occs++
}
}
}
return occs
}
func makeSeats(tiles [][]string) seatLayout {
seatmap := make(map[position]bool)
rowLen := len(tiles)
colLen := len(tiles[0])
for i, row := range tiles {
for j, tile := range row {
if isSeat(tile) {
seatmap[position{i, j}] = false
}
}
}
return seatLayout{rowLen, colLen, seatmap}
}
func isSeat(tile string) bool {
return tile == "L" || tile == "#"
}
func (seats *seatLayout) occupied() int {
count := 0
for _, s := range seats.grid {
if s {
count++
}
}
return count
}
func parseInput() []byte {
input, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
return input
}
func prepareInput(input []byte) [][]string {
lines := strings.Split(strings.TrimSpace(string(input)), newLine)
tiles := make([][]string, len(lines))
for i, l := range lines {
tiles[i] = strings.Split(l, "")
}
return tiles
}