Skip to content

Day 11 complete. #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/kotlin/common/aocreader/aocreader.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common.aocreader

import java.net.HttpURLConnection
2 changes: 1 addition & 1 deletion src/main/kotlin/common/collectionops/collectionops.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Advent of Code
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common.collectionops
18 changes: 0 additions & 18 deletions src/main/kotlin/common/input.kt

This file was deleted.

3 changes: 3 additions & 0 deletions src/main/kotlin/common/intpos2d/intpos2d.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common.intpos2d

typealias IntPos2D = Pair<Int, Int>
2 changes: 1 addition & 1 deletion src/main/kotlin/common/parsing/parsing.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Advent of Code
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common.parsing
12 changes: 12 additions & 0 deletions src/main/kotlin/common/runner/timed.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common.runner

inline fun <T> timedFunction(functionName: String, block: () -> T): T {
val startTime = System.nanoTime()
val result = block()
val endTime = System.nanoTime()
println("$functionName: $result (${(endTime - startTime) / 1_000_000.0} ms)")
return result
}
2 changes: 1 addition & 1 deletion src/main/kotlin/common/stringops.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Advent of Code
// Advent of Code 2024
// By Sebastian Raaphorst, 2024.

package common
10 changes: 3 additions & 7 deletions src/main/kotlin/day01/day01.kt
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ package day01
import common.aocreader.fetchAdventOfCodeInput
import common.parsing.parseColumns
import common.collectionops.toFrequencyMap
import common.runner.timedFunction
import kotlin.math.abs

fun answer1(input: String): Int =
@@ -25,12 +26,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 1)

println("--- Day 1: Historian Hysteria ---")

// Answer 1: 2031679
println("Part 1: ${answer1(input)}")

// Answer 2: 19678534
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 2031679
timedFunction("Part 2") { answer2(input) } // 19678534
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day02/day02.kt
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ package day02
import common.aocreader.fetchAdventOfCodeInput
import common.collectionops.allListDrops
import common.parsing.parseGrid
import common.runner.timedFunction

private const val Lower = 1
private const val Upper = 3
@@ -30,12 +31,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 2)

println("--- Day 2: Red-Nosed Reports ---")

// Answer 1: 379
println("Part 1: ${answer1(input)}")

// Answer 2: 430
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 379
timedFunction("Part 2") { answer2(input) } // 430
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day03/day03.kt
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
package day03

import common.aocreader.fetchAdventOfCodeInput
import common.runner.timedFunction

/**
* We want to turn off processing for substrings of the form:
@@ -31,12 +32,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 3)

println("--- Day 3: Mull It Over ---")

// Answer 1: 173785482
println("Part 1: ${answer1(input)}")

// Answer 2: 83158140
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 173785482
timedFunction("Part 2") { answer2(input) } // 83158140
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day04/day04.kt
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ package day04
import common.aocreader.fetchAdventOfCodeInput
import common.countSubstrings
import common.collectionops.*
import common.runner.timedFunction

private const val XMAS = "XMAS"

@@ -60,12 +61,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 4)

println("--- Day 4: Ceres Search ---")

// Answer 1: 2370
println("Part 1: ${answer1(input)}")

// Answer 2: 1908
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 2370
timedFunction("Part 2") { answer2(input) } // 1908
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day05/day05.kt
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ package day05

import common.aocreader.fetchAdventOfCodeInput
import common.collectionops.middle
import common.runner.timedFunction

private typealias OrderingRules = Map<Int, Set<Int>>
private typealias Updates = List<Int>
@@ -96,12 +97,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 5)

println("--- Day 5: Print Queue ---")

// Part 1: 4281
println("Part 1: ${answer1(input)}")

// Part 2: 5466
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 4281
timedFunction("Part 2") { answer2(input) } // 5466
}
13 changes: 3 additions & 10 deletions src/main/kotlin/day06/day06.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Advent of Code 2024, Day 06.
// By Sebastian Raaphorst, 2024.

// NOTE: Trying to use pure FP in this question made part 2 run extremely slowly.
// Mutable data structures are needed to avoid having to continuously copy structures.

package day06

import common.aocreader.fetchAdventOfCodeInput
import common.intpos2d.*
import common.runner.timedFunction

private typealias Orientation = Pair<Direction, IntPos2D>

@@ -84,12 +82,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 6)

println("--- Day 6: Guard Gallivant ---")

// Part 1: 5208
println("Part 1: ${answer1(input)}")

// Part 2: 1972
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 5208
timedFunction("Part 2") { answer2(input) } // 1972
}
12 changes: 3 additions & 9 deletions src/main/kotlin/day07/day07.kt
Original file line number Diff line number Diff line change
@@ -4,9 +4,8 @@
package day07

import common.aocreader.fetchAdventOfCodeInput
import common.day
import common.parsing.WhitespaceParser
import common.readInput
import common.runner.timedFunction
import java.math.BigInteger

data class Equation(val total: BigInteger, val numbers: List<BigInteger>) {
@@ -61,12 +60,7 @@ fun answer2(input: String): BigInteger =

fun main() {
val input = fetchAdventOfCodeInput(2024, 7)

println("--- Day 7: Bridge Repair ---")

// Part 1: 2437272016585
println("Part 1: ${answer1(input)}")

// Part 2: 162987117690649
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 2437272016585
timedFunction("Part 2") { answer2(input) } // 162987117690649
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day08/day08.kt
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ package day08

import common.aocreader.fetchAdventOfCodeInput
import common.intpos2d.*
import common.runner.timedFunction

private typealias Frequency = Char
private typealias AntennaMap = Map<Frequency, Set<IntPos2D>>
@@ -83,12 +84,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 8)

println("--- Day 8: Resonant Collinearity ---")

// Part 1: 376
println("Part 1: ${answer1(input)}")

// Part 2: 1352
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 376
timedFunction("Part 2") { answer2(input) } // 1352
}
10 changes: 3 additions & 7 deletions src/main/kotlin/day09/day09.kt
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
package day09

import common.aocreader.fetchAdventOfCodeInput
import common.runner.timedFunction
import java.math.BigInteger

private typealias Range = LongRange
@@ -190,12 +191,7 @@ fun answer2(input: String): BigInteger =

fun main() {
val input = fetchAdventOfCodeInput(2024, 9)

println("--- Day 9: Disk Fragmenter ---")

// Part 1: 6384282079460
println("Part 1: ${answer1(input)}")

// Part 2: 6408966547049
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 6384282079460
timedFunction("Part 2") { answer2(input) } // 6408966547049
}
12 changes: 4 additions & 8 deletions src/main/kotlin/day10/day10.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Advent of Code 2024, Day 09.
// Advent of Code 2024, Day 10.
// By Sebastian Raaphorst, 2024.

package day10

import common.aocreader.fetchAdventOfCodeInput
import common.intpos2d.*
import common.runner.timedFunction

private typealias Trail = List<IntPos2D>
private typealias Trails = Set<List<IntPos2D>>
@@ -57,12 +58,7 @@ fun answer2(input: String): Int =

fun main() {
val input = fetchAdventOfCodeInput(2024, 10)

println("--- Day 10: Hoof It ---")

// Part 1: 719
println("Part 1: ${answer1(input)}")

// Part 2: 1530
println("Part 2: ${answer2(input)}")
timedFunction("Part 1") { answer1(input) } // 719
timedFunction("Part 2") { answer2(input) } // 1530
}
66 changes: 66 additions & 0 deletions src/main/kotlin/day11/day11.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Advent of Code 2024, Day 11.
// By Sebastian Raaphorst, 2024.

package day11

import common.aocreader.fetchAdventOfCodeInput
import common.parsing.WhitespaceParser
import common.runner.timedFunction
import day11.StoneRules.cacheSize
import java.util.concurrent.ConcurrentHashMap


private fun parse(input: String): MutableMap<Long, Long> =
input.split(WhitespaceParser)
.map(String::toLong)
.groupingBy { it }
.eachCount()
.mapValues { it.value.toLong() }
.toMutableMap()

// The key is that the order of the stones have no relevance.
private object StoneRules {
private val memoization: MutableMap<Long, List<Long>> = ConcurrentHashMap()

private fun rule(stone: Long): List<Long> = memoization.computeIfAbsent(stone) {
when {
it == 0L -> listOf(1L)
it.toString().length % 2 == 0 -> {
val middle = it.toString().length / 2
listOf(
it.toString().substring(0, middle).toLong(),
it.toString().substring(middle).toLong()
)
}
else -> listOf(it * 2024)
}
}

fun blink(stones: Map<Long, Long>): MutableMap<Long, Long> =
stones.flatMap { (stone, count) ->
rule(stone).map { transformed -> transformed to count }
}.groupingBy { it.first }
.fold(0L) { acc, (_, count) -> acc + count }
.toMutableMap()

fun cacheSize(): Int = memoization.size
}

private fun answer(input: String, blinks: Int): Long =
(1..blinks).fold(parse(input)) { stones, _ -> StoneRules.blink(stones) }
.values.sum()

fun answer1(input: String): Long =
answer(input, 25)

fun answer2(input: String): Long =
answer(input, 75)

fun main() {
val input = fetchAdventOfCodeInput(2024, 11)
println("--- Day 11: Plutonian Pebbles ---")
timedFunction("Part 1") { answer1(input) }
println("\tCache size: ${cacheSize()}")
timedFunction("Part 2") { answer2(input) }
println("\tCache size: ${cacheSize()}")
}
1 change: 0 additions & 1 deletion src/test/kotlin/day04/day04.kt
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ class Day04Test {
MAMMMXMMMM
MXMXAXMASX
""".trimIndent()

}

@Test
21 changes: 21 additions & 0 deletions src/test/kotlin/day11/day11.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Advent of Code 2024, Day 11.
// By Sebastian Raaphorst, 2024.

package day11

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

// Note: no problem 2 test today.
class Day11Test {
private companion object {
val input =
"""
125 17
""".trimIndent().trim()
}

@Test
fun `Problem 1 example`() =
assertEquals(55312L, answer1(input))
}