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())
}