2018-12-16 07:26:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2019-11-07 21:43:14 +00:00
|
|
|
inp := StdinToStringSlice()
|
|
|
|
fmt.Printf("# Part 1\nIn Range of Strongest: %d\n", StrongestReachable(NewBots(inp)))
|
|
|
|
// Part 2: 94270682 is too low
|
|
|
|
// 94481123 is too low
|
|
|
|
fmt.Printf("# Part 2\nClosest Success: %d\n", ClosestSuccess(NewBots(inp)))
|
2018-12-16 07:26:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
func StrongestReachable(bots Bots) int {
|
|
|
|
var largestRadius, count int
|
|
|
|
var largestPos Coordinate
|
|
|
|
for c, rs := range bots {
|
|
|
|
for _, r := range rs {
|
|
|
|
if r > largestRadius {
|
|
|
|
largestPos = c
|
|
|
|
largestRadius = r
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for c, rs := range bots {
|
|
|
|
if largestPos.Distance(c) <= largestRadius {
|
|
|
|
count += len(rs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count
|
2018-12-16 07:26:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
func ClosestSuccess(bots Bots) int {
|
|
|
|
var cur, topLeft, bottomRight Coordinate
|
|
|
|
zoom := 1 << (strconv.IntSize - 2)
|
2018-12-16 07:26:17 +00:00
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
for {
|
|
|
|
zoomedBots := make(Bots)
|
|
|
|
best := struct {
|
|
|
|
pos Coordinate
|
|
|
|
count int
|
|
|
|
}{}
|
2018-12-16 07:26:17 +00:00
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
for c, rs := range bots {
|
|
|
|
for _, r := range rs {
|
|
|
|
zc := Coordinate{c.X / zoom, c.Y / zoom, c.Z / zoom}
|
|
|
|
zoomedBots[zc] = append(zoomedBots[zc], r/zoom)
|
|
|
|
}
|
2018-12-16 07:26:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
for cur.X = topLeft.X; cur.X <= bottomRight.X; cur.X++ {
|
|
|
|
for cur.Y = topLeft.Y; cur.Y <= bottomRight.Y; cur.Y++ {
|
|
|
|
for cur.Z = topLeft.Z; cur.Z <= bottomRight.Z; cur.Z++ {
|
|
|
|
c := zoomedBots.HaveInRange(cur)
|
2018-12-16 07:26:17 +00:00
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
// skip less bots
|
|
|
|
if c < best.count {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// skip same amount of bots but Distance from Zero is the same or more
|
|
|
|
if c == best.count && Zero.Distance(cur) >= Zero.Distance(best.pos) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// more bots or same and closer to Zero
|
|
|
|
best.pos, best.count = cur, c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-16 07:26:17 +00:00
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
// zoom in
|
|
|
|
topLeft.X, topLeft.Y, topLeft.Z = (best.pos.X-1)<<1, (best.pos.Y-1)<<1, (best.pos.Z-1)<<1
|
|
|
|
bottomRight.X, bottomRight.Y, bottomRight.Z = (best.pos.X+1)<<1, (best.pos.Y+1)<<1, (best.pos.Z+1)<<1
|
|
|
|
zoom >>= 1
|
2018-12-16 07:26:17 +00:00
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
if zoom == 0 {
|
|
|
|
return Zero.Distance(best.pos)
|
|
|
|
}
|
2018-12-16 07:26:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-07 21:43:14 +00:00
|
|
|
func StdinToStringSlice() []string {
|
2018-12-16 07:26:17 +00:00
|
|
|
var input []string
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
for scanner.Scan() {
|
|
|
|
input = append(input, scanner.Text())
|
|
|
|
}
|
|
|
|
return input
|
|
|
|
}
|