diff --git a/input/2021/day14-sample1.txt b/input/2021/day14-sample1.txt new file mode 100644 index 0000000..b5594dd --- /dev/null +++ b/input/2021/day14-sample1.txt @@ -0,0 +1,18 @@ +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 diff --git a/input/2021/day14.txt b/input/2021/day14.txt new file mode 100644 index 0000000..e84aae5 --- /dev/null +++ b/input/2021/day14.txt @@ -0,0 +1,102 @@ +SNPVPFCPPKSBNSPSPSOF + +CF -> N +NK -> B +SF -> B +HV -> P +FN -> S +VV -> F +FO -> F +VN -> V +PV -> P +FF -> P +ON -> S +PB -> S +PK -> P +OO -> P +SP -> F +VF -> H +OV -> C +BN -> P +OH -> H +NC -> F +BH -> N +CS -> C +BC -> N +OF -> N +SN -> B +FP -> F +FV -> K +HP -> H +VB -> P +FH -> F +HF -> P +BB -> O +HH -> S +PC -> O +PP -> B +VS -> B +HC -> H +NS -> N +KF -> S +BO -> V +NP -> S +NF -> K +BS -> O +KK -> O +VC -> V +KP -> K +CK -> P +HN -> F +KN -> H +KH -> N +SB -> S +NO -> K +HK -> H +BF -> V +SV -> B +CV -> P +CO -> P +FC -> O +CP -> H +CC -> N +CN -> P +SK -> V +SS -> V +VH -> B +OS -> N +FB -> H +NB -> N +SC -> K +NV -> H +HO -> S +SO -> P +PH -> C +VO -> O +OB -> O +FK -> S +PN -> P +VK -> O +NH -> N +OC -> B +BP -> O +PF -> F +KB -> K +KV -> B +PO -> N +NN -> K +CH -> O +KC -> P +OP -> V +VP -> F +OK -> P +FS -> K +CB -> S +HB -> N +KS -> O +BK -> C +BV -> O +SH -> H +PS -> N +HS -> K +KO -> N diff --git a/src/main/scala/de.qwertyuiop.aoc/2021/day11.scala b/src/main/scala/de.qwertyuiop.aoc/2021/day11.scala index f5ff801..efd6d41 100644 --- a/src/main/scala/de.qwertyuiop.aoc/2021/day11.scala +++ b/src/main/scala/de.qwertyuiop.aoc/2021/day11.scala @@ -44,7 +44,7 @@ object Octopodes: if flashing.isEmpty then (f.view.mapValues(v => if v > 9 then 0 else v).toMap, flashed.size + flashing.size) else - val neighs = flashing.toVector.flatMap(_.neighbours).occurrences + val neighs = flashing.toVector.flatMap(_.neighbours).occurrences.mapValuesS(_.toInt) val newF = f.map((coord, v) => coord -> ( if v > 9 || flashing.contains(coord) then 12 else (v + neighs.getOrElse(coord, 0)).min(11) diff --git a/src/main/scala/de.qwertyuiop.aoc/2021/day14.scala b/src/main/scala/de.qwertyuiop.aoc/2021/day14.scala index 506abd4..8065e8d 100644 --- a/src/main/scala/de.qwertyuiop.aoc/2021/day14.scala +++ b/src/main/scala/de.qwertyuiop.aoc/2021/day14.scala @@ -3,4 +3,30 @@ package de.qwertyuiop.aoc.`2021` import de.qwertyuiop.aoc.lib.* import cats.*, cats.implicits.given -def day14(using InputSource): Unit = ??? +def day14(using InputSource): Unit = + val (template :: "" :: rulesRaw) = input() + val rules = rulesRaw.flatMap(_.splitOnce(" -> ").map((pair, target) => pair -> (s"${pair.head}$target", s"$target${pair.tail}"))).toMap + + + def solve(part: Int, steps: Int) = + val occurrences = growPolymer(template, rules)(steps) + val max = occurrences.maxBy(_._2) + val min = occurrences.minBy(_._2) + println(s"Most common: ${max}") + println(s"Least common: ${min}") + println(s"Solution Part $part: ${max._2 - min._2}") + + solve(1,10) + solve(2,40) + +def growPolymer(start: String, rules: Map[String, (String, String)])(maxSteps: Int): Map[Char, Long] = + def growRec(pairs: Map[String, Long])(steps: Int): Map[String, Long] = + if steps == 0 then pairs + else + growRec( + pairs.toVector.foldMap{(pair, count) => val (a, b) = rules(pair); Map(a -> count, b -> count) } + )(steps - 1) + + val pairCounts = growRec(start.sliding(2).toVector.occurrences)(maxSteps) + ++ Map(start.head.toString -> 1L, start.last.toString -> 1L) + pairCounts.toVector.foldMap((pair, count) => Map(pair.head -> count)) diff --git a/src/main/scala/de.qwertyuiop.aoc/lib/extensions.scala b/src/main/scala/de.qwertyuiop.aoc/lib/extensions.scala index c613daa..27e7b46 100644 --- a/src/main/scala/de.qwertyuiop.aoc/lib/extensions.scala +++ b/src/main/scala/de.qwertyuiop.aoc/lib/extensions.scala @@ -10,7 +10,7 @@ extension [A](input: List[A])(using CanEqual[A,A]) h #:: (if keepSeparator then tail else t).split(separator) extension [A](iterable: Iterable[A]) - def occurrences: Map[A, Int] = iterable.groupMapReduce(identity)(_ => 1)(_ + _) + def occurrences: Map[A, Long] = iterable.groupMapReduce(identity)(_ => 1L)(_ + _) /* Using -Yexplicit-nulls isn't really ready for use with the java standard * library. e.g. String doesn't have `@NotNull` annotations for its methods