~macaptain/advent-of-code

19d78083d43c19d965196be42e384362a08c4738 — Michael Captain 2 years ago a9dfeef
Complete 2021 Day 14
A src/main/advent2021/Day14.kt => src/main/advent2021/Day14.kt +62 -0
@@ 0,0 1,62 @@
package advent2021

fun solve14a(lines: List<String>): Int {
    val template = lines.first()
    val rules = lines.drop(2).associate { line ->
        val (lhs, rhs) = line.split(" -> ")
        val rhsInserted = lhs[0] + rhs
        lhs to rhsInserted
    }
    val pairInsertion = generateSequence(template) { polymer ->
        polymer.windowed(2, 1).map {
            rules[it] ?: it.first()
        }.joinToString("") + polymer.last()
    }
    val tenthStepElementCount = pairInsertion.elementAt(10).groupingBy { it }.eachCount()
    return tenthStepElementCount.values.maxOf { it } - tenthStepElementCount.values.minOf { it }
}

private fun pairCountToCharCount(pairCount: Map<String, Long>, template: String): Map<Char, Long> {
    val doubledCharCount = mutableMapOf<Char, Long>()
    pairCount.forEach { (k, v) ->
        doubledCharCount.merge(k[0], v, Long::plus)
        doubledCharCount.merge(k[1], v, Long::plus)
    }
    return doubledCharCount.mapValues { (k, v) ->
        when (k) {
            template.first() -> (v + 1) / 2
            template.last() -> (v + 1) / 2
            else -> v / 2
        }
    }
}

fun solve14b(lines: List<String>): Long {
    val template = lines.first()
    val rules = lines.drop(2).associate { line ->
        val (lhs, rhs) = line.split(" -> ")
        lhs to Pair(lhs[0] + rhs, rhs + lhs[1])
    }
    val initialPairMap = template.windowed(2, 1).groupingBy { it }.eachCount().map { (k, v) -> k to v.toLong() }.toMap()
    val pairMapSequence = generateSequence(initialPairMap) { pairMap ->
        val newPairCount = mutableMapOf<String, Long>()
        pairMap.forEach { (oldPair, count) ->
            val newPairs = rules.getValue(oldPair)
            newPairCount.merge(newPairs.first, count, Long::plus)
            newPairCount.merge(newPairs.second, count, Long::plus)
            newPairCount.merge(oldPair, -count, Long::plus)
        }
        (pairMap.keys + newPairCount.keys).associateWith { pair ->
            pairMap.getOrDefault(pair, 0) + newPairCount.getOrDefault(pair, 0)
        }
    }
    val fortiethStepElementCount = pairMapSequence.elementAt(40)
    val charCount = pairCountToCharCount(fortiethStepElementCount, template)
    return charCount.values.maxOf { it } - charCount.values.minOf { it }
}

fun main() {
    val input = input("day14")
    println(solve14a(input)) // 2590
    println(solve14b(input)) // 2875665202438
}
\ No newline at end of file

A src/main/resources/advent2021/day14_input.txt => src/main/resources/advent2021/day14_input.txt +102 -0
@@ 0,0 1,102 @@
OHFNNCKCVOBHSSHONBNF

SV -> O
KP -> H
FP -> B
VP -> V
KN -> S
KS -> O
SB -> K
BS -> K
OF -> O
ON -> S
VS -> F
CK -> C
FB -> K
CH -> K
HS -> H
PO -> F
NP -> N
FH -> C
FO -> O
FF -> C
CO -> K
NB -> V
PP -> S
BB -> N
HH -> B
KK -> H
OP -> K
OS -> V
KV -> F
VH -> F
OB -> S
CN -> H
SF -> K
SN -> P
NF -> H
HB -> V
VC -> S
PS -> P
NK -> B
CV -> P
BC -> S
NH -> K
FN -> P
SH -> F
FK -> P
CS -> O
VV -> H
OC -> F
CC -> N
HK -> N
FS -> P
VF -> B
SS -> V
PV -> V
BF -> V
OV -> C
HO -> F
NC -> F
BN -> F
HC -> N
KO -> P
KH -> F
BV -> S
SK -> F
SC -> F
VN -> V
VB -> V
BH -> O
CP -> K
PK -> K
PB -> K
FV -> S
HN -> K
PH -> B
VK -> B
PC -> H
BO -> H
SP -> V
NS -> B
OH -> N
KC -> H
HV -> F
HF -> B
HP -> S
CB -> P
PN -> S
BK -> K
PF -> N
SO -> P
CF -> B
VO -> C
OO -> K
FC -> F
NV -> F
OK -> K
NN -> O
NO -> O
BP -> O
KB -> O
KF -> O

A src/test/advent2021/Day14KtTest.kt => src/test/advent2021/Day14KtTest.kt +39 -0
@@ 0,0 1,39 @@
package advent2021

import org.junit.jupiter.api.Test

import org.junit.jupiter.api.Assertions.*

internal class Day14KtTest {

    val lines = listOf(
        "NNCB",
        "",
        "CH -> B",
        "HH -> N",
        "CB -> H",
        "NH -> C",
        "HB -> C",
        "HC -> B",
        "HN -> C",
        "NN -> C",
        "BH -> H",
        "NC -> B",
        "NB -> B",
        "BN -> B",
        "BB -> N",
        "BC -> B",
        "CC -> N",
        "CN -> C"
    )

    @Test
    fun example14a() {
        assertEquals(1588, solve14a(lines))
    }

    @Test
    fun example14b() {
        assertEquals(2188189693529L, solve14b(lines))
    }
}
\ No newline at end of file