-
Notifications
You must be signed in to change notification settings - Fork 1
/
Day23.kt
66 lines (46 loc) · 1.96 KB
/
Day23.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
* Copyright (c) 2018 by Todd Ginsberg
*/
/**
* Advent of Code 2018, Day 23 - Experimental Emergency Teleportation
*
* Problem Description: http://adventofcode.com/2018/day/23
* Blog Post/Commentary: https://todd.ginsberg.com/post/advent-of-code/2018/day23/
*/
package com.ginsberg.advent2018
import kotlin.math.abs
class Day23(rawInput: List<String>) {
private val swarm: List<Nanobot> = rawInput.map { Nanobot.of(it) }
fun solvePart1(): Int {
val fattestBot = swarm.maxBy { it.radius }!!
return swarm.count { fattestBot.inRange(it) }
}
fun solvePart2(): Int {
val neighbors: Map<Nanobot, Set<Nanobot>> = swarm.map { bot ->
Pair(bot, swarm.filterNot { it == bot }.filter { bot.withinRangeOfSharedPoint(it) }.toSet())
}.toMap()
val clique: Set<Nanobot> = BronKerbosch(neighbors).largestClique()
return clique.map { it.location.distanceTo(Point3d.origin) - it.radius }.max()!!
}
private data class Nanobot(val location: Point3d, val radius: Int) {
fun inRange(other: Nanobot): Boolean =
location.distanceTo(other.location) <= radius
fun withinRangeOfSharedPoint(other: Nanobot): Boolean =
location.distanceTo(other.location) <= radius + other.radius
companion object {
private val digitsRegex = """^pos=<(-?\d+),(-?\d+),(-?\d+)>, r=(\d+)$""".toRegex()
fun of(input: String): Nanobot =
digitsRegex.find(input)?.let {
val (x, y, z, r) = it.destructured
Nanobot(Point3d(x.toInt(), y.toInt(), z.toInt()), r.toInt())
} ?: throw IllegalArgumentException("Cannot parse $input")
}
}
private data class Point3d(val x: Int, val y: Int, val z: Int) {
fun distanceTo(other: Point3d): Int =
abs(x - other.x) + abs(y - other.y) + abs(z - other.z)
companion object {
val origin = Point3d(0, 0, 0)
}
}
}