-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.go
100 lines (83 loc) · 2.02 KB
/
main.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
package main
import (
"bufio"
"io"
"strconv"
aoc "github.com/teivah/advent-of-code"
)
func fs1(input io.Reader) int {
perimeter, positions := parse(input, parseFromInstructions)
return calculateArea(perimeter, positions)
}
func fs2(input io.Reader) int {
perimeter, positions := parse(input, parseFromColor)
return calculateArea(perimeter, positions)
}
func parse(input io.Reader, parseFunc func(string) (aoc.Direction, int)) (int, []aoc.Position) {
var positions []aoc.Position
pos := aoc.Position{}
perimeter := 0
scanner := bufio.NewScanner(input)
for scanner.Scan() {
line := scanner.Text()
dir, count := parseFunc(line)
pos = pos.Move(dir, count)
perimeter += count
positions = append(positions, pos)
}
return perimeter, positions
}
func parseFromInstructions(line string) (aoc.Direction, int) {
del := aoc.NewDelimiter(line, " ")
direction := del.GetString(0)
count := del.GetInt(1)
var dir aoc.Direction
switch direction {
case "R":
dir = aoc.Right
case "D":
dir = aoc.Down
case "L":
dir = aoc.Left
case "U":
dir = aoc.Up
default:
panic(direction)
}
return dir, count
}
func parseFromColor(line string) (aoc.Direction, int) {
del := aoc.NewDelimiter(line, " ")
s := del.GetString(2)
color := s[2 : len(s)-1]
distance := color[:5]
count, err := strconv.ParseInt(distance, 16, 64)
if err != nil {
panic(err)
}
var dir aoc.Direction
switch color[5] {
case '0':
dir = aoc.Right
case '1':
dir = aoc.Down
case '2':
dir = aoc.Left
case '3':
dir = aoc.Up
default:
panic(color)
}
return dir, int(count)
}
func calculateArea(perimeter int, positions []aoc.Position) int {
// Source: https://stackoverflow.com/a/717367 (EDIT section)
n := len(positions)
positions = append(positions, aoc.Position{Row: positions[0].Row, Col: positions[0].Col})
positions = append(positions, aoc.Position{Row: positions[1].Row, Col: positions[1].Col})
area := 0
for i := 1; i <= n; i++ {
area += positions[i].Col * (positions[i+1].Row - positions[i-1].Row)
}
return area/2 + perimeter/2 + 1
}