Skip to content

Commit

Permalink
Add AOC2024 day 21, part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
FWDekker committed Dec 22, 2024
1 parent a2ebc6c commit 9290319
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 16 deletions.
227 changes: 227 additions & 0 deletions aoc/src/main/kotlin/com/fwdekker/aoc/y2024/Day21.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package com.fwdekker.aoc.y2024

import com.fwdekker.aoc.Day
import com.fwdekker.std.collections.NeverNullMap
import com.fwdekker.std.collections.neverNull
import com.fwdekker.std.foldSelfIndexed
import com.fwdekker.std.maths.cartesian


// See https://adventofcode.com/2024/day/21
class Day21(sample: Int? = null) : Day(year = 2024, day = 21, sample = sample) {
private val codes = input.lines()
private val numpad = mapOf(
'A' to mapOf(
'A' to listOf(""),
'0' to listOf("<"),
'1' to listOf("^<<", "<^<"),
'2' to listOf("^<", "<^"),
'3' to listOf("^"),
'4' to listOf("^^<<", "^<^<", "^<<^", "<^^<", "<^<^"),
'5' to listOf("^^<", "^<^", "<^^"),
'6' to listOf("^^"),
'7' to listOf("^^^<<", "^^<^<", "^^<<^", "^<^^<", "^<^<^", "^<<^^", "<^^^<", "<^^<^", "<^<^^"),
'8' to listOf("^^^<", "^^<^", "^<^^", "<^^^"),
'9' to listOf("^^^"),
),
'0' to mapOf(
'A' to listOf(">"),
'0' to listOf(""),
'1' to listOf("^<"),
'2' to listOf("^"),
'3' to listOf("^>", ">^"),
'4' to listOf("^^<", "^<^"),
'5' to listOf("^^"),
'6' to listOf("^^>", "^>^", ">^^"),
'7' to listOf("^^^<", "^^<^", "^<^^"),
'8' to listOf("^^^"),
'9' to listOf("^^^>", "^^>^", "^>^^", ">^^^"),
),
'1' to mapOf(
'A' to listOf(">>v", ">v>"),
'0' to listOf(">v"),
'1' to listOf(""),
'2' to listOf(">"),
'3' to listOf(">>"),
'4' to listOf("^"),
'5' to listOf(">^", "^>"),
'6' to listOf(">>^", ">^>", "^>>"),
'7' to listOf("^^"),
'8' to listOf("^^>", "^>^", ">^^"),
'9' to listOf("^^>>", "^>^>", "^>>^", ">^^>", ">^>^", ">>^^"),
),
'2' to mapOf(
'A' to listOf("v>", ">v"),
'0' to listOf("v"),
'1' to listOf("<"),
'2' to listOf(""),
'3' to listOf(">"),
'4' to listOf("^<", "<^"),
'5' to listOf("^"),
'6' to listOf("^>", ">^"),
'7' to listOf("^^<", "^<^", "<^^"),
'8' to listOf("^^"),
'9' to listOf("^^>", "^>^", ">^^"),
),
'3' to mapOf(
'A' to listOf("v"),
'0' to listOf("v<", "<v"),
'1' to listOf("<<"),
'2' to listOf("<"),
'3' to listOf(""),
'4' to listOf("^<<", "<^<", "<<^"),
'5' to listOf("^<", "<^"),
'6' to listOf("^"),
'7' to listOf("^^<<", "^<^<", "^<<^", "<^^<", "<^<^", "<<^^"),
'8' to listOf("^^<", "^<^", "<^^"),
'9' to listOf("^^"),
),
'4' to mapOf(
'A' to listOf("v>v>", "v>>v", ">vv>", ">v>v", ">>vv"),
'0' to listOf("v>v", ">vv"),
'1' to listOf("v"),
'2' to listOf("v>", ">v"),
'3' to listOf("v>>", ">v>", ">>v"),
'4' to listOf(""),
'5' to listOf(">"),
'6' to listOf(">>"),
'7' to listOf("^"),
'8' to listOf("^>", ">^"),
'9' to listOf("^>>", ">^>", ">>^"),
),
'5' to mapOf(
'A' to listOf("vv>", "v>v", ">vv"),
'0' to listOf("vv"),
'1' to listOf("v<", "<v"),
'2' to listOf("v"),
'3' to listOf("v>", ">v"),
'4' to listOf("<"),
'5' to listOf(""),
'6' to listOf(">"),
'7' to listOf("^<", "<^"),
'8' to listOf("^"),
'9' to listOf("^>", ">^"),
),
'6' to mapOf(
'A' to listOf("vv"),
'0' to listOf("vv<", "v<v", "<vv"),
'1' to listOf("v<<", "<v<", "<<v"),
'2' to listOf("v<", "<v"),
'3' to listOf("v"),
'4' to listOf("<<"),
'5' to listOf("<"),
'6' to listOf(""),
'7' to listOf("^<<", "<^<", "<<^"),
'8' to listOf("^<", "<^"),
'9' to listOf("^"),
),
'7' to mapOf(
'A' to listOf("vv>v>", "vv>>v", "v>vv>", "v>v>v", "v>>vv", ">vvv>", ">vv>v", ">v>vv", ">>vvv"),
'0' to listOf("vv>v", "v>vv", ">vvv"),
'1' to listOf("vv"),
'2' to listOf("vv>", "v>v", ">vv"),
'3' to listOf("vv>>", "v>v>", "v>>v", ">vv>", ">v>v", ">>vv"),
'4' to listOf("v"),
'5' to listOf("v>", ">v"),
'6' to listOf("v>>", ">v>", ">>v"),
'7' to listOf(""),
'8' to listOf(">"),
'9' to listOf(">>"),
),
'8' to mapOf(
'A' to listOf("vvv>", "vv>v", "v>vv", ">vvv"),
'0' to listOf("vvv"),
'1' to listOf("vv<", "v<v", "<vv"),
'2' to listOf("vv"),
'3' to listOf("vv>", "v>v", ">vv"),
'4' to listOf("v<", "<v"),
'5' to listOf("v"),
'6' to listOf("v>", ">v"),
'7' to listOf("<"),
'8' to listOf(""),
'9' to listOf(">"),
),
'9' to mapOf(
'A' to listOf("vvv"),
'0' to listOf("vvv<", "vv<v", "v<vv", "<vvv"),
'1' to listOf("vv<<", "v<v<", "v<<v", "<vv<", "<v<v", "<<vv"),
'2' to listOf("vv<", "v<v", "<vv"),
'3' to listOf("vv"),
'4' to listOf("v<<", "<v<", "<<v"),
'5' to listOf("v<", "<v"),
'6' to listOf("v"),
'7' to listOf("<<"),
'8' to listOf("<"),
'9' to listOf(""),
),
).mapValues { (_, values) -> values.mapValues { (_, value) -> value.map { it + 'A' } }.neverNull() }.neverNull()
private val keypad = mapOf(
'A' to mapOf(
'A' to listOf(""),
'^' to listOf("<"),
'<' to listOf("v<<", "<v<"),
'v' to listOf("v<", "<v"),
'>' to listOf("v"),
),
'^' to mapOf(
'A' to listOf(">"),
'^' to listOf(""),
'<' to listOf("v<"),
'v' to listOf("v"),
'>' to listOf("v>", ">v"),
),
'<' to mapOf(
'A' to listOf(">^>", ">>^"),
'^' to listOf(">^"),
'<' to listOf(""),
'v' to listOf(">"),
'>' to listOf(">>"),
),
'v' to mapOf(
'A' to listOf("^>", ">^"),
'^' to listOf("^"),
'<' to listOf("<"),
'v' to listOf(""),
'>' to listOf(">"),
),
'>' to mapOf(
'A' to listOf("^"),
'^' to listOf("^<", "<^"),
'<' to listOf("<<"),
'v' to listOf("<"),
'>' to listOf(""),
),
).mapValues { (_, values) -> values.mapValues { (_, value) -> value.map { it + 'A' } }.neverNull() }.neverNull()

private val codeToKeysCache = mutableMapOf<String, List<String>>()


override fun part1() = calculateComplexity(2)

override fun part2() = calculateComplexity(2)


private fun codeToKeys(pad: NeverNullMap<Char, NeverNullMap<Char, List<String>>>, code: String): List<String> =
codeToKeysCache.getOrPut(code) {
"A$code"
.zipWithNext { from, to -> pad[from][to] }
.reduce { acc, paths -> acc.cartesian(paths).map { it.first + it.second }.toList() }
}

private fun calculateComplexity(robotsInBetween: Int) =
codes
.sumOf { code ->
listOf(code)
.foldSelfIndexed(robotsInBetween + 1) { idx, acc ->
acc.flatMap { codeToKeys(if (idx == 0) numpad else keypad, it) }.allMinOf { it.length }
}
.minOf { it.length }
.let { code.dropLast(1).toLong() * it }
}

private fun <T, R : Comparable<R>> List<T>.allMinOf(selector: (T) -> R): List<T> =
minOf(selector).let { min -> filter { selector(it) == min } }
}


fun main() = Day21().run()
6 changes: 3 additions & 3 deletions aoc/src/main/kotlin/com/fwdekker/aoc/y2024/Day6.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import com.fwdekker.std.grid.canMove
import com.fwdekker.std.grid.coordsOf
import com.fwdekker.std.grid.get
import com.fwdekker.std.grid.toChart
import com.fwdekker.std.read


class Day6(resource: String = resource(2024, 6)) : Day() {
private val chart = read(resource).toChart()
// See https://adventofcode.com/2024/day/6
class Day6(sample: Int? = null) : Day(year = 2024, day = 6, sample = sample) {
private val chart = input.toChart()
private val start = chart.coordsOf('^')


Expand Down
2 changes: 1 addition & 1 deletion aoc/src/main/resources
15 changes: 15 additions & 0 deletions aoc/src/test/kotlin/com/fwdekker/aoc/y2024/Day21Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.fwdekker.aoc.y2024

import com.fwdekker.std.ChallengeTest
import io.kotest.core.annotation.Tags


@Tags("2024")
object Day21Test : ChallengeTest(
::Day21,
listOf(
case(part = 1, sample = 1) to 126384L,
case(part = 1) to 246990L,
// case(part = 2) to 0L,
)
)
18 changes: 8 additions & 10 deletions aoc/src/test/kotlin/com/fwdekker/aoc/y2024/Day6Test.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package com.fwdekker.aoc.y2024

import com.fwdekker.aoc.Day
import com.fwdekker.aoc.DayTest
import com.fwdekker.std.ChallengeTest
import io.kotest.core.annotation.Tags


/**
* Tests for [Day6].
*/
object Day6Test : DayTest(
@Tags("2024")
object Day6Test : ChallengeTest(
::Day6,
listOf(
Triple(Day.resource(2024, 6, sample = 1), Day::part1, 41),
Triple(Day.resource(2024, 6, sample = 1), Day::part2, 6),
Triple(Day.resource(2024, 6), Day::part1, 5080),
Triple(Day.resource(2024, 6), Day::part2, 1919),
case(part = 1, sample = 1) to 41,
case(part = 2, sample = 1) to 6,
case(part = 1) to 5080,
case(part = 2) to 1919,
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ fun <T> Iterable<T>.cyclic(): Sequence<T> = asSequence().cyclic()
*/
fun <T> Sequence<T>.allDistinct(): Boolean {
val seen = mutableSetOf<T>()
return none { seen.add(it) }
return all { seen.add(it) }
}

fun <T> Iterable<T>.allDistinct(): Boolean = asSequence().allDistinct()
Expand All @@ -223,7 +223,7 @@ fun <T> Sequence<T>.noneDistinct(): Boolean {
return drop(1).all { it == first }
}

fun <T> Iterable<T>.noneDistinct(): Boolean = asSequence().allDistinct()
fun <T> Iterable<T>.noneDistinct(): Boolean = asSequence().noneDistinct()


/**
Expand Down

0 comments on commit 9290319

Please sign in to comment.