package main import ( "bufio" "fmt" "log" "os" ) type Point struct { x, y int } func (p *Point) key() string { return fmt.Sprintf("%d_%d", p.y, p.x) } func readInput(file *os.File) (map[byte][]Point, [][]byte) { scanner := bufio.NewScanner(file) var matrix [][]byte groups := make(map[byte][]Point) var y int for scanner.Scan() { line := scanner.Text() if line == "" { break } matrix = append(matrix, []byte(line)) for x := range line { if line[x] != '.' { groups[line[x]] = append(groups[line[x]], Point{x: x, y: y}) } } y++ } return groups, matrix } func abs(a int) int { if a < 0 { return -a } return a } func checkAntinode(antinode Point, matrix [][]byte, key byte) bool { if antinode.x < 0 || antinode.y < 0 || antinode.y >= len(matrix) || antinode.x >= len(matrix[0]) { return false } return true } func getAntinodes(groups map[byte][]Point, matrix [][]byte, multi bool) map[string]Point { antinodes := make(map[string]Point) for key, items := range groups { edge := len(items) for i := range items { for j := i + 1; j < edge; j++ { deltaX := items[j].x - items[i].x deltaY := items[j].y - items[i].y firstAntinode := Point{x: items[i].x - deltaX, y: items[i].y - deltaY} for checkAntinode(firstAntinode, matrix, key) { antinodes[firstAntinode.key()] = firstAntinode if multi { firstAntinode = Point{x: firstAntinode.x - deltaX, y: firstAntinode.y - deltaY} } else { firstAntinode = Point{x: -1, y: -1} } } secondAntinode := Point{x: items[j].x + deltaX, y: items[j].y + deltaY} for checkAntinode(secondAntinode, matrix, key) { antinodes[secondAntinode.key()] = secondAntinode if multi { secondAntinode = Point{x: secondAntinode.x + deltaX, y: secondAntinode.y + deltaY} } else { secondAntinode = Point{x: -1, y: -1} } } } } } return antinodes } func part2(groups map[byte][]Point, matrix [][]byte) int { antinodes := getAntinodes(groups, matrix, true) for _, items := range groups { if len(items) > 1 { for _, item := range items { antinodes[item.key()] = item } } } return len(antinodes) } func main() { if len(os.Args) < 2 { log.Fatal("You need to specify a file!") } filePath := os.Args[1] file, err := os.Open(filePath) if err != nil { log.Fatalf("Failed to open %s!\n", filePath) } groups, matrix := readInput(file) fmt.Println("Part1:", len(getAntinodes(groups, matrix, false))) fmt.Println("Part2:", part2(groups, matrix)) }