Day 18
This commit is contained in:
184
src/main/kotlin/com/basdado/adventofcode/Day18.kt
Normal file
184
src/main/kotlin/com/basdado/adventofcode/Day18.kt
Normal file
@@ -0,0 +1,184 @@
|
||||
package com.basdado.adventofcode
|
||||
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
const val DAY18_INPUT = "/day/18/input.txt"
|
||||
|
||||
fun main() {
|
||||
|
||||
val day = Day18()
|
||||
day.puzzle1()
|
||||
println("Puzzle 2 took " + measureTimeMillis { day.puzzle2() } + " ms")
|
||||
}
|
||||
|
||||
class Day18 {
|
||||
|
||||
fun puzzle1() {
|
||||
|
||||
val area = parseInput()
|
||||
|
||||
val afterTime = evaluateTime(area, 10)
|
||||
|
||||
val lumberCount = afterTime.area.count { it == AcreType.LUMBERYARD }
|
||||
val treeCount = afterTime.area.count { it == AcreType.TREES }
|
||||
|
||||
println(lumberCount * treeCount)
|
||||
}
|
||||
|
||||
fun puzzle2() {
|
||||
|
||||
val area = parseInput()
|
||||
|
||||
val afterTime = evaluateTime(area, 1000000000)
|
||||
|
||||
val lumberCount = afterTime.area.count { it == AcreType.LUMBERYARD }
|
||||
val treeCount = afterTime.area.count { it == AcreType.TREES }
|
||||
|
||||
println(lumberCount * treeCount)
|
||||
}
|
||||
|
||||
private fun evaluateTime(area: LumberArea, minutes: Int): LumberArea {
|
||||
|
||||
var oldArea = area.clone()
|
||||
|
||||
val seen = mutableMapOf(Pair(area, 0))
|
||||
|
||||
var minute = 1
|
||||
while(minute <= minutes) {
|
||||
|
||||
val newArea = LumberArea(area.width, area.height)
|
||||
|
||||
for (y in 0 until oldArea.height) {
|
||||
for (x in 0 until oldArea.width) {
|
||||
when (oldArea.get(x, y)) {
|
||||
AcreType.OPEN -> newArea.set(
|
||||
x, y,
|
||||
if (oldArea.countAdjacent(x, y, AcreType.TREES) >= 3)
|
||||
AcreType.TREES
|
||||
else
|
||||
AcreType.OPEN
|
||||
)
|
||||
AcreType.TREES -> newArea.set(
|
||||
x, y,
|
||||
if (oldArea.countAdjacent(x, y, AcreType.LUMBERYARD) >= 3)
|
||||
AcreType.LUMBERYARD
|
||||
else
|
||||
AcreType.TREES
|
||||
)
|
||||
AcreType.LUMBERYARD -> newArea.set(
|
||||
x, y,
|
||||
if (oldArea.countAdjacent(x, y, AcreType.LUMBERYARD) >= 1 && oldArea.countAdjacent(
|
||||
x,
|
||||
y,
|
||||
AcreType.TREES
|
||||
) >= 1
|
||||
) {
|
||||
AcreType.LUMBERYARD
|
||||
} else {
|
||||
AcreType.OPEN
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val repeatingMinute = seen[newArea]
|
||||
if (repeatingMinute != null) {
|
||||
val repeatLength = minute - repeatingMinute
|
||||
val cycleSkip = ((minutes - minute) / repeatLength) * repeatLength
|
||||
println("Found cycle of $repeatLength minutes between $minute and $repeatingMinute, skipping $cycleSkip")
|
||||
minute += cycleSkip
|
||||
seen.clear()
|
||||
}
|
||||
|
||||
seen[newArea] = minute
|
||||
|
||||
oldArea = newArea
|
||||
|
||||
minute++
|
||||
}
|
||||
return oldArea
|
||||
}
|
||||
|
||||
fun parseInput(): LumberArea {
|
||||
|
||||
val input = lines(DAY18_INPUT).collect(Collectors.toList())
|
||||
|
||||
val res = LumberArea(input[0].length, input.size)
|
||||
for (y in 0 until input.size) {
|
||||
for(x in 0 until input[y].length) {
|
||||
res.set(x, y, acreType(input[y][x]))
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun acreType(c: Char): AcreType = AcreType.values().find { it.char == c }!!
|
||||
|
||||
enum class AcreType(val char: kotlin.Char) {
|
||||
OPEN('.'), TREES('|'), LUMBERYARD('#')
|
||||
}
|
||||
class LumberArea(val width: Int, val height: Int, val area: Array<AcreType> = Array(width * height) { AcreType.OPEN }) {
|
||||
|
||||
private fun index(x: Int, y: Int): Int = y * width + x
|
||||
fun get(x: Int, y: Int): AcreType {
|
||||
return if (x !in 0 until width || y !in 0 until height)
|
||||
AcreType.OPEN
|
||||
else
|
||||
area[index(x, y)]
|
||||
}
|
||||
fun set(x: Int, y: Int, acre: AcreType) {
|
||||
area[index(x, y)] = acre
|
||||
}
|
||||
|
||||
fun countAdjacent(x: Int, y: Int, type: AcreType): Int {
|
||||
return (if (get(x + 1, y) == type) 1 else 0) +
|
||||
(if (get(x + 1, y + 1) == type) 1 else 0) +
|
||||
(if (get(x, y + 1) == type) 1 else 0) +
|
||||
(if (get(x - 1, y + 1) == type) 1 else 0) +
|
||||
(if (get(x - 1, y) == type) 1 else 0) +
|
||||
(if (get(x - 1, y - 1) == type) 1 else 0) +
|
||||
(if (get(x, y - 1) == type) 1 else 0) +
|
||||
(if (get(x + 1, y - 1) == type) 1 else 0)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
val res = StringBuilder()
|
||||
for(y in 0 until height) {
|
||||
for(x in 0 until width) {
|
||||
res.append(get(x, y).char)
|
||||
}
|
||||
res.append("\r\n")
|
||||
}
|
||||
return res.toString()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as LumberArea
|
||||
|
||||
if (width != other.width) return false
|
||||
if (height != other.height) return false
|
||||
if (!area.contentEquals(other.area)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = width
|
||||
result = 31 * result + height
|
||||
result = 31 * result + area.contentHashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
fun clone(): LumberArea {
|
||||
return LumberArea(width, height, area.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/main/resources/day/18/example.txt
Normal file
10
src/main/resources/day/18/example.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
.#.#...|#.
|
||||
.....#|##|
|
||||
.|..|...#.
|
||||
..|#.....#
|
||||
#.#|||#|#|
|
||||
...#.||...
|
||||
.|....|...
|
||||
||...#|.#|
|
||||
|.||||..|.
|
||||
...#.|..|.
|
||||
50
src/main/resources/day/18/input.txt
Normal file
50
src/main/resources/day/18/input.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
.|#.#|..#...|..##||...|#..##..#..|#|....#.#|.|....
|
||||
.||....#..#...|#....#.||....||...||...|..#|..||..|
|
||||
......|.|.#.#.#..|.....#.###.....#........|.||..#|
|
||||
..|.....||...#||#.#|#.....|##.|.|....|#....#|..#.#
|
||||
|...#.|..#|#.#....|.#.#.|.#...#..#|#.....##|#..#.|
|
||||
#....|#|......#.|||..#..#..||...#.#...|||##|..|#..
|
||||
.#||.|....|.......#|##...|.#.....#.##...|.|.#...#|
|
||||
....#|.|.|...##.......|#.....|..#......#...#|.#..#
|
||||
...#.|....#.|.#...|||......##..|#|||#..#...|.|#.#.
|
||||
.#..|...|..#.|##.#.#......#...||.||.#...|.#.#.#|..
|
||||
|...#.|||...#|.#||.......|.##.....|..||...####...|
|
||||
.##..|..##|...##.#...#...#.#|.|###...#............
|
||||
|.....||...#.......|.#..|#.....|.|#.|..||.##.|#|..
|
||||
.#..##|.#|.|..|.#..#.|.#..#|......##...#.#.......#
|
||||
...#.##.|..|.#.....#....#..#.............|.|##||..
|
||||
||.##.||.|.|..|..#.|.|.##|.|...|.#.|#.......#.|...
|
||||
..|#.##..#|.#|#.#...........|.|........#...#|...#|
|
||||
....|.#|..|.#|#|...|.|.#..#.....#|##|||##.#....#..
|
||||
...###.#.....#.||......#|#..##...|#....#....|#|.#.
|
||||
.##.|.##|.#.||....#|....|.#.|#.|....##..#.##|.....
|
||||
|...|...#|....#....#...#|#...|..#.#.|.|.....|.#|..
|
||||
.|.|.#.#.#|.#.|#....|.|###..#......|...|...#.|#...
|
||||
..|...||.|..##|...|..|#|...|......#.||.#...#..|#.|
|
||||
........|..#||..|....|.....|.|#..#....|#..|.#.....
|
||||
#.|.|#....#...|..|....|.#.....||.....|..|........#
|
||||
...||||....|.#.|....#..#....|###....|...#...##....
|
||||
|||........|.#|.|......||#.|.....|.||#|.##....#|..
|
||||
.....|#|#..||#...|##.|..||....####.|#.|..#....|.#.
|
||||
.||..#||....#.....#.#|.|....|.##|..|.#..|##....##.
|
||||
.|#.#|#|#|.....||..|.|.|.#......#..|.#..#..|.#||#.
|
||||
|.|#.......|..#|#|....|.#.#.#.|...|.......##.|||#|
|
||||
..|.....#...||.|....|##|...#..#.#.....|##|##.##...
|
||||
.|.|..##.#|..|.|#.......#....#||.|...||#...|......
|
||||
|.|##.#....|#..|....#..#..|##.|.##..#......#|##|..
|
||||
..#....#.|#...#.#...|.....|.||.#.#|.#.|###..|..#.#
|
||||
..|.##...........|..###.||.|.##.|....|.|.#|#.#.|#|
|
||||
..|....|.|#|...#|#...|.#......#.#||...|.#|...#.|#.
|
||||
..#.......|.||.....||.|....|#||..........#...|#...
|
||||
.|..#....|#|||#..##||..#|.......|..|###..|.#...|.|
|
||||
|..|.#|.#...#....|.....#.....#....#...|..|.|.#.|.#
|
||||
....###.#....|.#..#...#...###.|.|.....#|...#.....|
|
||||
..#....##.....##..|.#.||#.|.#|#||..|...#|..|.#....
|
||||
|#..#.#|||#.|#..#........#......||...#.|..#|....#|
|
||||
......#|...#.|...#...|.|...|#|#......#|.##.#|.|.#|
|
||||
#||.#......#.##......#..||.##|.|.||..|#....#..#...
|
||||
#.#...#.|.#|#||#.#......#....|##|.........##.#|...
|
||||
.....###...#||....|####..#|||...#..#|.|....#|..#..
|
||||
......|#..#.#.#..|.#|#||..||.|...#....##...|......
|
||||
...#...|..#..##.||.#.#.....|.###.....##|#||..#..#|
|
||||
.#..#||.#....||....|##..|||...|.||...#..##.#....#.
|
||||
Reference in New Issue
Block a user