summaryrefslogtreecommitdiff
path: root/day8/main.go
blob: 11b0d09df2b0025022c98727863cc6a8431e5a8c (plain)
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
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type Position struct {
	X, Y int
}

func ByteToAntenna(b byte) int {
	if b >= '0' && b <= '9' {
		return int(b - '0')
	} else if b >= 'a' && b <= 'z' {
		return int(b - 'a' + 10)
	} else if b >= 'A' && b <= 'Z' {
		return int(b - 'A' + 36)
	} else {
		return -1
	}
}

func IsInMap(p Position, w, h int) bool {
	if p.X < 0 || p.X >= w {
		return false
	}
	if p.Y < 0 || p.Y >= h {
		return false
	}
	return true
}

func ComputeAntinodes(a, b Position, w, h int, first, repeats int) (antinodes []Position) {
	dx := b.X - a.X
	dy := b.Y - a.Y

	for i := first; i <= repeats; i++ {
		n1, n2 := Position{a.X - dx*i, a.Y - dy*i}, Position{b.X + dx*i, b.Y + dy*i}
		n1InMap := IsInMap(n1, w, h)
		n2InMap := IsInMap(n2, w, h)

		if n1InMap {
			antinodes = append(antinodes, n1)
		}

		if n2InMap {
			antinodes = append(antinodes, n2)
		}

		if !n1InMap && !n2InMap {
			break
		}
	}

	return
}

func main() {
	{
		width, height, antinodes := readData("example.txt")
		fmt.Println(countAntinodes(width, height, antinodes, 1, 1))
		fmt.Println(countAntinodes(width, height, antinodes, 0, 999))
	}
	{
		width, height, antinodes := readData("data.txt")
		fmt.Println(countAntinodes(width, height, antinodes, 1, 1))
		fmt.Println(countAntinodes(width, height, antinodes, 0, 999))
	}
}

func countAntinodes(width, height int, antennas map[int][]Position, first, repeats int) (count int) {
	marked := make([][]bool, height)
	for y := 0; y < height; y++ {
		marked[y] = make([]bool, width)
	}

	for _, positions := range antennas {
		for i := 0; i < len(positions)-1; i++ {
			for j := i + 1; j < len(positions); j++ {
				for _, p := range ComputeAntinodes(positions[i], positions[j], width, height, first, repeats) {
					marked[p.Y][p.X] = true
				}
			}
		}
	}

	for y := 0; y < height; y++ {
		for x := 0; x < len(marked[y]); x++ {
			if marked[y][x] {
				count++
			}
		}
	}

	return
}

func readData(fileName string) (width, height int, antennas map[int][]Position) {
	fp, err := os.Open(fileName)
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(fp)
	antennas = make(map[int][]Position)

	y := 0
	for ; scanner.Scan(); y++ {
		line := strings.TrimSpace(scanner.Text())
		width = len(line)

		for x := 0; x < width; x++ {
			antenna := ByteToAntenna(line[x])
			if antenna >= 0 {
				antennas[antenna] = append(antennas[antenna], Position{x, y})
			}
		}
	}

	height = y

	return
}