package main import ( "bufio" "fmt" "math" "os" "strings" ) func abs(t int) int { if t < 0 { return -t } return t } type Point struct { ID byte X int Y int Inf bool } func (p *Point) Equal(x, y int) bool { return (p.X == x && p.Y == y) } func (p *Point) Distance(x, y int) int { return abs(p.X-x) + abs(p.Y-y) } func (p Point) String() string { var inf string if p.Inf { inf = " INF" } return fmt.Sprintf("%c %dx%d%s", p.ID, p.X, p.Y, inf) } type Puzzle struct { Points []Point MaxX, MaxY int } func (p *Puzzle) Add(x, y int) { p.Points = append(p.Points, Point{ ID: byte('"' + len(p.Points)), X: x, Y: y, }) if x > p.MaxX { p.MaxX = x } if y > p.MaxY { p.MaxY = y } } func (p *Puzzle) Solution1() int { size := (p.MaxY + 2) * (p.MaxX + 2) grid := make([]byte, size) for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { i := (y * (p.MaxX + 2)) + x c := byte('.') if x == 0 || x == p.MaxX+1 || y == 0 || y == p.MaxY+1 { c = 219 } for _, point := range p.Points { if point.Equal(x, y) { c = point.ID break } } grid[i] = c } } dist := make([]int, len(p.Points)) for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { skip := false for t, point := range p.Points { if point.Equal(x, y) { skip = true break } dist[t] = point.Distance(x, y) } if skip { continue } var id byte shortest := math.MaxInt32 for t, d := range dist { if d < shortest { shortest = d id = p.Points[t].ID } } matches := 0 for _, d := range dist { if d == shortest { matches++ } } i := (y * (p.MaxX + 2)) + x if grid[i] == 219 { for t := range p.Points { if p.Points[t].ID == id { p.Points[t].Inf = true break } } } else { if matches > 1 { id = '!' } grid[i] = id } } } /* for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { i := (y * (p.MaxX + 2)) + x fmt.Printf("%c", grid[i]) } fmt.Printf("\n") } */ largest := 0 for _, point := range p.Points { if point.Inf { continue } count := 0 for _, c := range grid { if c == point.ID { count++ } } if count > largest { largest = count } } return largest } func (p *Puzzle) Solution2() int { size := (p.MaxY + 2) * (p.MaxX + 2) grid := make([]byte, size) for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { i := (y * (p.MaxX + 2)) + x c := byte('.') if x == 0 || x == p.MaxX+1 || y == 0 || y == p.MaxY+1 { c = 219 } for _, point := range p.Points { if point.Equal(x, y) { c = point.ID break } } grid[i] = c } } drawn := 0 for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { total := 0 for _, point := range p.Points { total += point.Distance(x, y) } i := (y * (p.MaxX + 2)) + x if grid[i] == 219 { continue } else { if total < 10000 { grid[i] = '#' drawn++ } } } } /*for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { i := (y * (p.MaxX + 2)) + x fmt.Printf("%c", grid[i]) } fmt.Printf("\n") }*/ return drawn } func (p Puzzle) String() string { output := strings.Builder{} output.WriteString(fmt.Sprintf("%dx%d\n", p.MaxX, p.MaxY)) for y := 0; y < p.MaxY+2; y++ { for x := 0; x < p.MaxX+2; x++ { c := byte('.') for _, point := range p.Points { if point.Equal(x, y) { c = point.ID break } } output.WriteByte(c) } output.WriteByte('\n') } return output.String() } func main() { input, err := os.Open("input.txt") if err != nil { panic(err.Error()) } defer input.Close() scanner := bufio.NewScanner(input) p := Puzzle{ Points: make([]Point, 0, 1024), } for scanner.Scan() { var x, y int fmt.Sscanf(scanner.Text(), "%d,%d", &x, &y) p.Add(x, y) } if err := scanner.Err(); err != nil { panic(err.Error()) } fmt.Println(p.Solution1()) fmt.Println(p.Solution2()) }