Day 5
This commit is contained in:
126
src/main/kotlin/com/basdado/adventofcode/Day5.kt
Normal file
126
src/main/kotlin/com/basdado/adventofcode/Day5.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.basdado.adventofcode
|
||||
|
||||
import kotlin.math.abs
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
fun main() {
|
||||
|
||||
val day = Day5()
|
||||
println("Puzzle 1 time: " + measureTimeMillis { day.puzzle1() } + " ms")
|
||||
println("Puzzle 2 time: " + measureTimeMillis { day.puzzle2() } + " ms")
|
||||
|
||||
}
|
||||
|
||||
class Day5 {
|
||||
|
||||
fun puzzle1() {
|
||||
|
||||
val polymer = constructPolymerFromString(lines("/day/5/input.txt").findFirst().get())
|
||||
polymer.react()
|
||||
println(polymer.length())
|
||||
}
|
||||
|
||||
fun puzzle2() {
|
||||
|
||||
val fullPolymerString = lines("/day/5/input.txt").findFirst().get()
|
||||
println(fullPolymerString.chars()
|
||||
.distinct().boxed()
|
||||
.map { it.toChar() }.map { it.toString() }
|
||||
.map { it.toUpperCase() }
|
||||
.distinct()
|
||||
.mapToInt { constructPolymerFromString(fullPolymerString.replace(it.toString(), "", true)).react().length() }
|
||||
.min()!!
|
||||
)
|
||||
}
|
||||
|
||||
fun constructPolymerFromString(str: String): Polymer {
|
||||
|
||||
val polymer = Polymer()
|
||||
if (!str.isBlank()) {
|
||||
|
||||
polymer.firstUnit = Unit(str[0])
|
||||
|
||||
var previousUnit = polymer.firstUnit!!
|
||||
for (i in 1 until str.length) {
|
||||
val newUnit = Unit(str[i], previous = previousUnit)
|
||||
previousUnit.next = newUnit
|
||||
previousUnit = newUnit
|
||||
}
|
||||
}
|
||||
return polymer
|
||||
}
|
||||
|
||||
class Polymer (var firstUnit: Unit? = null) {
|
||||
|
||||
fun react(): Polymer {
|
||||
|
||||
if (firstUnit == null) {
|
||||
return this
|
||||
}
|
||||
|
||||
var curUnit = firstUnit!!
|
||||
do {
|
||||
if (curUnit.reactsWithNext()) {
|
||||
if (curUnit.previous == null) {
|
||||
// This is the first unit in the chain, so we update the polymer
|
||||
firstUnit = curUnit.next?.next
|
||||
if (firstUnit == null) {
|
||||
break
|
||||
}
|
||||
firstUnit!!.previous = null
|
||||
curUnit = firstUnit!!
|
||||
} else {
|
||||
val nextAfterReaction = curUnit.next?.next
|
||||
curUnit = curUnit.previous!! // one step back
|
||||
nextAfterReaction?.previous = curUnit
|
||||
curUnit.next = nextAfterReaction
|
||||
}
|
||||
} else {
|
||||
curUnit = curUnit.next!!
|
||||
}
|
||||
} while(curUnit.hasNext())
|
||||
return this
|
||||
}
|
||||
|
||||
fun length(): Int {
|
||||
if (firstUnit == null) {
|
||||
return 0
|
||||
}
|
||||
var curUnit = firstUnit!!
|
||||
var length = 0
|
||||
do {
|
||||
length++
|
||||
curUnit = curUnit.next!!
|
||||
} while(curUnit.hasNext())
|
||||
// Don't forget to count the last character
|
||||
length++
|
||||
return length
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
if (firstUnit == null) {
|
||||
return ""
|
||||
}
|
||||
|
||||
val res = StringBuilder()
|
||||
var curUnit = firstUnit!!
|
||||
do {
|
||||
res.append(curUnit.char)
|
||||
curUnit = curUnit.next!!
|
||||
} while (curUnit.hasNext())
|
||||
res.append(curUnit.char)
|
||||
return res.toString()
|
||||
}
|
||||
}
|
||||
|
||||
data class Unit (val char: Char, var next: Unit? = null, var previous: Unit? = null) {
|
||||
fun reactsWithNext(): Boolean = reactsWith(next)
|
||||
fun reactsWithPrevious(): Boolean = reactsWith(previous)
|
||||
fun reactsWith(unit: Unit?): Boolean = if (unit == null) false else abs(char.minus(unit.char)) == 32
|
||||
fun hasNext(): Boolean = next != null
|
||||
fun hasPrevious(): Boolean = previous != null
|
||||
override fun toString(): String {
|
||||
return "" + char
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/main/resources/day/5/input.txt
Normal file
1
src/main/resources/day/5/input.txt
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user