package main import ( "bufio" "container/heap" "fmt" "os" "github.com/davecgh/go-spew/spew" ) func waitEnter() { fmt.Printf("Press ENTER to continue\n") bufio.NewReader(os.Stdin).ReadBytes('\n') } func sliceEqual(a, b []int) bool { if len(a) != len(b) { return false } for t := range a { if a[t] != b[t] { return false } } return true } func abs(a int) int { if a < 0 { a = -a } return a } func max(a, b int) int { if a > b { return a } return b } func manhattan(a, b Point) int { return abs(a.X-b.X) + abs(a.Y-b.Y) + abs(a.Z-b.Z) } type Point struct { X, Y, Z int } type NanoBot struct { Pos Point R int } type Puzzle struct { bots []NanoBot } func NewPuzzle(filepath string) *Puzzle { p := Puzzle{ bots: make([]NanoBot, 0, 400), } input, err := os.Open(filepath) if err != nil { panic(err.Error()) } scanner := bufio.NewScanner(input) for scanner.Scan() { var x, y, z, r int fmt.Sscanf(scanner.Text(), "pos=<%d,%d,%d>, r=%d", &x, &y, &z, &r) p.bots = append(p.bots, NanoBot{ Pos: Point{ X: x, Y: y, Z: z, }, R: r, }) } if err := scanner.Err(); err != nil { panic(err.Error()) } input.Close() return &p } func (p *Puzzle) FindStrongestBot() *NanoBot { var bot *NanoBot largest := 0 for t, b := range p.bots { if b.R > largest { largest = b.R bot = &p.bots[t] } } return bot } func (p *Puzzle) DetectInRangeBot(bot *NanoBot) []*NanoBot { bots := make([]*NanoBot, 0, 400) for t, b := range p.bots { if manhattan(bot.Pos, b.Pos) <= bot.R { bots = append(bots, &p.bots[t]) } } return bots } func (p *Puzzle) FindMostOverlapDist() int { pq := make(PriorityQueue, 0, len(p.bots)*2) for _, b := range p.bots { d := abs(b.Pos.X) + abs(b.Pos.Y) + abs(b.Pos.Z) pq = append(pq, &Item{ value: 1, priority: max(0, d-b.R), }) pq = append(pq, &Item{ value: -1, priority: d + b.R + 1, }) } heap.Init(&pq) var result, count, maxCount int for pq.Len() > 0 { item := heap.Pop(&pq).(*Item) dist, e := item.priority, item.value count += e if count > maxCount { result = dist maxCount = count } } return result + 1 } func main() { // Test1 t := NewPuzzle("test1.txt") bot := t.FindStrongestBot() spew.Dump(bot) inRange := t.DetectInRangeBot(bot) spew.Dump(inRange) fmt.Println("In range:", len(inRange)) // Test2 t = NewPuzzle("test2.txt") bot = t.FindStrongestBot() spew.Dump(bot) fmt.Printf("Overlapping dist: %+v\n", t.FindMostOverlapDist()) // Puzzle1 p := NewPuzzle("input.txt") fmt.Println("In range:", len(p.DetectInRangeBot(p.FindStrongestBot()))) fmt.Printf("Overlapping dist: %+v\n", p.FindMostOverlapDist()) }