123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- package main
- import (
- "bufio"
- "errors"
- "fmt"
- "io"
- "log"
- "os"
- )
- func trim(s string) string {
- if len(s) > 0 && s[len(s)-1] == '\n' {
- return s[:len(s)-1]
- }
- return s
- }
- func main() {
- r := bufio.NewReader(os.Stdin)
- width := 0
- height := 0
- antennae := make(map[byte][]Coord)
- positions := make(map[Coord]struct{})
- line := make([]byte, 0, 4096)
- // Read map
- x, y := 0, 0
- for {
- b, err := r.ReadByte()
- if errors.Is(err, io.EOF) {
- break
- }
- if err != nil {
- log.Fatalf("While reading input: %v", err)
- }
- if b == '\n' {
- x = 0
- y++
- if width == 0 {
- width = len(line)
- }
- continue
- }
- if width == 0 {
- line = append(line, b)
- }
- switch {
- case b == '.':
- case '0' <= b || b <= '9' ||
- 'a' <= b || b <= 'z' ||
- 'A' <= b || b <= 'Z':
- if _, ok := antennae[b]; !ok {
- antennae[b] = make([]Coord, 0, 8)
- }
- coord := Coord{x, y}
- antennae[b] = append(antennae[b], coord)
- default:
- log.Fatalf("Unrecognized map input %q", b)
- }
- x++
- }
- height = y
- if x > 0 {
- height++
- }
- // Calculate antinodes
- for k, as := range antennae {
- if len(as) < 2 {
- continue
- }
- fmt.Fprintf(os.Stderr, "debug: frequency %q: %#v\n", k, as)
- is := [2]int{0, 1}
- for is[0]+is[1] <= 2*len(as)-3 {
- p1 := as[is[0]]
- p2 := as[is[1]]
- d := Coord{p1.X - p2.X, p1.Y - p2.Y}
- a1 := Coord{p1.X + d.X, p1.Y + d.Y}
- a2 := Coord{p2.X - d.X, p2.Y - d.Y}
- if inBounds(a1, 0, width-1, 0, height-1) {
- positions[a1] = struct{}{}
- }
- if inBounds(a2, 0, width-1, 0, height-1) {
- positions[a2] = struct{}{}
- }
- if is[1]+1 == len(as) {
- is[0]++
- is[1] = is[0] + 1
- continue
- }
- is[1]++
- }
- }
- fmt.Fprintf(os.Stderr, "positions: %#v\n", positions)
- fmt.Printf("%d\n", len(positions))
- }
- func inBounds(c Coord, x0, x1, y0, y1 int) bool {
- if x0 <= c.X && c.X <= x1 &&
- y0 <= c.Y && c.Y <= y1 {
- return true
- }
- return false
- }
- type Coord struct {
- X, Y int
- }
- func IndexOf(c Coord, width int) int {
- return c.X + c.Y*width
- }
- func CoordOf(idx, width int) Coord {
- if width == 0 {
- return Coord{idx, 0}
- }
- x := idx % width
- y := idx / width
- return Coord{x, y}
- }
|