Skip to content

Commit aa677e3

Browse files
authored
Merge pull request #19 from sraaphorst/D11
Day 11 complete.
2 parents e09fde7 + 0c03871 commit aa677e3

File tree

20 files changed

+139
-98
lines changed

20 files changed

+139
-98
lines changed

src/main/kotlin/common/aocreader/aocreader.kt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Advent of Code 2024
2+
// By Sebastian Raaphorst, 2024.
3+
14
package common.aocreader
25

36
import java.net.HttpURLConnection

src/main/kotlin/common/collectionops/collectionops.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Advent of Code
1+
// Advent of Code 2024
22
// By Sebastian Raaphorst, 2024.
33

44
package common.collectionops

src/main/kotlin/common/input.kt

-18
This file was deleted.

src/main/kotlin/common/intpos2d/intpos2d.kt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Advent of Code 2024
2+
// By Sebastian Raaphorst, 2024.
3+
14
package common.intpos2d
25

36
typealias IntPos2D = Pair<Int, Int>

src/main/kotlin/common/parsing/parsing.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Advent of Code
1+
// Advent of Code 2024
22
// By Sebastian Raaphorst, 2024.
33

44
package common.parsing
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Advent of Code 2024
2+
// By Sebastian Raaphorst, 2024.
3+
4+
package common.runner
5+
6+
inline fun <T> timedFunction(functionName: String, block: () -> T): T {
7+
val startTime = System.nanoTime()
8+
val result = block()
9+
val endTime = System.nanoTime()
10+
println("$functionName: $result (${(endTime - startTime) / 1_000_000.0} ms)")
11+
return result
12+
}

src/main/kotlin/common/stringops.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Advent of Code
1+
// Advent of Code 2024
22
// By Sebastian Raaphorst, 2024.
33

44
package common

src/main/kotlin/day01/day01.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package day01
66
import common.aocreader.fetchAdventOfCodeInput
77
import common.parsing.parseColumns
88
import common.collectionops.toFrequencyMap
9+
import common.runner.timedFunction
910
import kotlin.math.abs
1011

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

2627
fun main() {
2728
val input = fetchAdventOfCodeInput(2024, 1)
28-
2929
println("--- Day 1: Historian Hysteria ---")
30-
31-
// Answer 1: 2031679
32-
println("Part 1: ${answer1(input)}")
33-
34-
// Answer 2: 19678534
35-
println("Part 2: ${answer2(input)}")
30+
timedFunction("Part 1") { answer1(input) } // 2031679
31+
timedFunction("Part 2") { answer2(input) } // 19678534
3632
}

src/main/kotlin/day02/day02.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package day02
66
import common.aocreader.fetchAdventOfCodeInput
77
import common.collectionops.allListDrops
88
import common.parsing.parseGrid
9+
import common.runner.timedFunction
910

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

3132
fun main() {
3233
val input = fetchAdventOfCodeInput(2024, 2)
33-
3434
println("--- Day 2: Red-Nosed Reports ---")
35-
36-
// Answer 1: 379
37-
println("Part 1: ${answer1(input)}")
38-
39-
// Answer 2: 430
40-
println("Part 2: ${answer2(input)}")
35+
timedFunction("Part 1") { answer1(input) } // 379
36+
timedFunction("Part 2") { answer2(input) } // 430
4137
}

src/main/kotlin/day03/day03.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package day03
55

66
import common.aocreader.fetchAdventOfCodeInput
7+
import common.runner.timedFunction
78

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

3233
fun main() {
3334
val input = fetchAdventOfCodeInput(2024, 3)
34-
3535
println("--- Day 3: Mull It Over ---")
36-
37-
// Answer 1: 173785482
38-
println("Part 1: ${answer1(input)}")
39-
40-
// Answer 2: 83158140
41-
println("Part 2: ${answer2(input)}")
36+
timedFunction("Part 1") { answer1(input) } // 173785482
37+
timedFunction("Part 2") { answer2(input) } // 83158140
4238
}

src/main/kotlin/day04/day04.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package day04
66
import common.aocreader.fetchAdventOfCodeInput
77
import common.countSubstrings
88
import common.collectionops.*
9+
import common.runner.timedFunction
910

1011
private const val XMAS = "XMAS"
1112

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

6162
fun main() {
6263
val input = fetchAdventOfCodeInput(2024, 4)
63-
6464
println("--- Day 4: Ceres Search ---")
65-
66-
// Answer 1: 2370
67-
println("Part 1: ${answer1(input)}")
68-
69-
// Answer 2: 1908
70-
println("Part 2: ${answer2(input)}")
65+
timedFunction("Part 1") { answer1(input) } // 2370
66+
timedFunction("Part 2") { answer2(input) } // 1908
7167
}

src/main/kotlin/day05/day05.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package day05
55

66
import common.aocreader.fetchAdventOfCodeInput
77
import common.collectionops.middle
8+
import common.runner.timedFunction
89

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

9798
fun main() {
9899
val input = fetchAdventOfCodeInput(2024, 5)
99-
100100
println("--- Day 5: Print Queue ---")
101-
102-
// Part 1: 4281
103-
println("Part 1: ${answer1(input)}")
104-
105-
// Part 2: 5466
106-
println("Part 2: ${answer2(input)}")
101+
timedFunction("Part 1") { answer1(input) } // 4281
102+
timedFunction("Part 2") { answer2(input) } // 5466
107103
}

src/main/kotlin/day06/day06.kt

+3-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
// Advent of Code 2024, Day 06.
22
// By Sebastian Raaphorst, 2024.
33

4-
// NOTE: Trying to use pure FP in this question made part 2 run extremely slowly.
5-
// Mutable data structures are needed to avoid having to continuously copy structures.
6-
74
package day06
85

96
import common.aocreader.fetchAdventOfCodeInput
107
import common.intpos2d.*
8+
import common.runner.timedFunction
119

1210
private typealias Orientation = Pair<Direction, IntPos2D>
1311

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

8583
fun main() {
8684
val input = fetchAdventOfCodeInput(2024, 6)
87-
8885
println("--- Day 6: Guard Gallivant ---")
89-
90-
// Part 1: 5208
91-
println("Part 1: ${answer1(input)}")
92-
93-
// Part 2: 1972
94-
println("Part 2: ${answer2(input)}")
86+
timedFunction("Part 1") { answer1(input) } // 5208
87+
timedFunction("Part 2") { answer2(input) } // 1972
9588
}

src/main/kotlin/day07/day07.kt

+3-9
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
package day07
55

66
import common.aocreader.fetchAdventOfCodeInput
7-
import common.day
87
import common.parsing.WhitespaceParser
9-
import common.readInput
8+
import common.runner.timedFunction
109
import java.math.BigInteger
1110

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

6261
fun main() {
6362
val input = fetchAdventOfCodeInput(2024, 7)
64-
6563
println("--- Day 7: Bridge Repair ---")
66-
67-
// Part 1: 2437272016585
68-
println("Part 1: ${answer1(input)}")
69-
70-
// Part 2: 162987117690649
71-
println("Part 2: ${answer2(input)}")
64+
timedFunction("Part 1") { answer1(input) } // 2437272016585
65+
timedFunction("Part 2") { answer2(input) } // 162987117690649
7266
}

src/main/kotlin/day08/day08.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package day08
55

66
import common.aocreader.fetchAdventOfCodeInput
77
import common.intpos2d.*
8+
import common.runner.timedFunction
89

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

8485
fun main() {
8586
val input = fetchAdventOfCodeInput(2024, 8)
86-
8787
println("--- Day 8: Resonant Collinearity ---")
88-
89-
// Part 1: 376
90-
println("Part 1: ${answer1(input)}")
91-
92-
// Part 2: 1352
93-
println("Part 2: ${answer2(input)}")
88+
timedFunction("Part 1") { answer1(input) } // 376
89+
timedFunction("Part 2") { answer2(input) } // 1352
9490
}

src/main/kotlin/day09/day09.kt

+3-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package day09
55

66
import common.aocreader.fetchAdventOfCodeInput
7+
import common.runner.timedFunction
78
import java.math.BigInteger
89

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

191192
fun main() {
192193
val input = fetchAdventOfCodeInput(2024, 9)
193-
194194
println("--- Day 9: Disk Fragmenter ---")
195-
196-
// Part 1: 6384282079460
197-
println("Part 1: ${answer1(input)}")
198-
199-
// Part 2: 6408966547049
200-
println("Part 2: ${answer2(input)}")
195+
timedFunction("Part 1") { answer1(input) } // 6384282079460
196+
timedFunction("Part 2") { answer2(input) } // 6408966547049
201197
}

src/main/kotlin/day10/day10.kt

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
// Advent of Code 2024, Day 09.
1+
// Advent of Code 2024, Day 10.
22
// By Sebastian Raaphorst, 2024.
33

44
package day10
55

66
import common.aocreader.fetchAdventOfCodeInput
77
import common.intpos2d.*
8+
import common.runner.timedFunction
89

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

5859
fun main() {
5960
val input = fetchAdventOfCodeInput(2024, 10)
60-
6161
println("--- Day 10: Hoof It ---")
62-
63-
// Part 1: 719
64-
println("Part 1: ${answer1(input)}")
65-
66-
// Part 2: 1530
67-
println("Part 2: ${answer2(input)}")
62+
timedFunction("Part 1") { answer1(input) } // 719
63+
timedFunction("Part 2") { answer2(input) } // 1530
6864
}

src/main/kotlin/day11/day11.kt

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Advent of Code 2024, Day 11.
2+
// By Sebastian Raaphorst, 2024.
3+
4+
package day11
5+
6+
import common.aocreader.fetchAdventOfCodeInput
7+
import common.parsing.WhitespaceParser
8+
import common.runner.timedFunction
9+
import day11.StoneRules.cacheSize
10+
import java.util.concurrent.ConcurrentHashMap
11+
12+
13+
private fun parse(input: String): MutableMap<Long, Long> =
14+
input.split(WhitespaceParser)
15+
.map(String::toLong)
16+
.groupingBy { it }
17+
.eachCount()
18+
.mapValues { it.value.toLong() }
19+
.toMutableMap()
20+
21+
// The key is that the order of the stones have no relevance.
22+
private object StoneRules {
23+
private val memoization: MutableMap<Long, List<Long>> = ConcurrentHashMap()
24+
25+
private fun rule(stone: Long): List<Long> = memoization.computeIfAbsent(stone) {
26+
when {
27+
it == 0L -> listOf(1L)
28+
it.toString().length % 2 == 0 -> {
29+
val middle = it.toString().length / 2
30+
listOf(
31+
it.toString().substring(0, middle).toLong(),
32+
it.toString().substring(middle).toLong()
33+
)
34+
}
35+
else -> listOf(it * 2024)
36+
}
37+
}
38+
39+
fun blink(stones: Map<Long, Long>): MutableMap<Long, Long> =
40+
stones.flatMap { (stone, count) ->
41+
rule(stone).map { transformed -> transformed to count }
42+
}.groupingBy { it.first }
43+
.fold(0L) { acc, (_, count) -> acc + count }
44+
.toMutableMap()
45+
46+
fun cacheSize(): Int = memoization.size
47+
}
48+
49+
private fun answer(input: String, blinks: Int): Long =
50+
(1..blinks).fold(parse(input)) { stones, _ -> StoneRules.blink(stones) }
51+
.values.sum()
52+
53+
fun answer1(input: String): Long =
54+
answer(input, 25)
55+
56+
fun answer2(input: String): Long =
57+
answer(input, 75)
58+
59+
fun main() {
60+
val input = fetchAdventOfCodeInput(2024, 11)
61+
println("--- Day 11: Plutonian Pebbles ---")
62+
timedFunction("Part 1") { answer1(input) }
63+
println("\tCache size: ${cacheSize()}")
64+
timedFunction("Part 2") { answer2(input) }
65+
println("\tCache size: ${cacheSize()}")
66+
}

src/test/kotlin/day04/day04.kt

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class Day04Test {
2121
MAMMMXMMMM
2222
MXMXAXMASX
2323
""".trimIndent()
24-
2524
}
2625

2726
@Test

0 commit comments

Comments
 (0)