Skip to content

Commit 348eb2e

Browse files
committed
Solution 2025-02 (Gift Shop)
1 parent d8a6627 commit 348eb2e

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package de.ronny_h.aoc.year2025.day02
2+
3+
import de.ronny_h.aoc.AdventOfCode
4+
5+
fun main() = GiftShop().run(32976912643, 54446379122)
6+
7+
class GiftShop : AdventOfCode<Long>(2025, 2) {
8+
override fun part1(input: List<String>): Long =
9+
input.parseIdRanges()
10+
.filterInvalidIds(Long::isSequenceRepeatedTwice)
11+
.sum()
12+
13+
override fun part2(input: List<String>): Long =
14+
input.parseIdRanges()
15+
.filterInvalidIds(Long::isSequenceRepeatedAtLeastTwice)
16+
.sum()
17+
}
18+
19+
private fun List<LongRange>.filterInvalidIds(isInvalid: (Long) -> Boolean): List<Long> =
20+
flatMap { range ->
21+
range.filter { isInvalid(it) }
22+
}
23+
24+
fun Long.isSequenceRepeatedTwice(): Boolean {
25+
val id = "$this"
26+
if (id.length % 2 != 0) {
27+
return false
28+
}
29+
val first = id.take(id.length / 2)
30+
val second = id.substring(id.length / 2)
31+
return first == second
32+
}
33+
34+
fun Long.isSequenceRepeatedAtLeastTwice(): Boolean {
35+
val id = "$this"
36+
for (size in 1..id.length / 2) {
37+
if (id.length % size != 0) {
38+
continue
39+
}
40+
val subsequences = buildList {
41+
id.windowed(size, size) {
42+
add(it)
43+
}
44+
}
45+
if (subsequences.all { it == subsequences.first() }) {
46+
return true
47+
}
48+
}
49+
return false
50+
}
51+
52+
fun List<String>.parseIdRanges() = first()
53+
.split(",")
54+
.map { range ->
55+
val (from, to) = range
56+
.split("-")
57+
.map(String::toLong)
58+
from..to
59+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package de.ronny_h.aoc.year2025.day02
2+
3+
import de.ronny_h.aoc.extensions.asList
4+
import io.kotest.core.spec.style.StringSpec
5+
import io.kotest.data.forAll
6+
import io.kotest.data.row
7+
import io.kotest.matchers.shouldBe
8+
9+
class GiftShopTest : StringSpec({
10+
11+
val input = """
12+
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124
13+
""".asList()
14+
15+
"id ranges can be parsed" {
16+
val input = listOf("11-22,95-115,998-1012,1188511880-1188511890")
17+
input.parseIdRanges() shouldBe listOf(11L..22L, 95L..115L, 998L..1012L, 1188511880L..1188511890L)
18+
}
19+
20+
"isSequenceRepeatedTwice" {
21+
forAll(
22+
row(11L, true),
23+
row(22L, true),
24+
row(123L, false),
25+
row(1234L, false),
26+
row(1188511885L, true),
27+
) { id, isInvalid ->
28+
id.isSequenceRepeatedTwice() shouldBe isInvalid
29+
}
30+
}
31+
32+
"isSequenceRepeatedAtLeastTwice" {
33+
forAll(
34+
row(11L, true),
35+
row(22L, true),
36+
row(111L, true),
37+
row(123L, false),
38+
row(1234L, false),
39+
row(1111111L, true),
40+
row(123123123L, true),
41+
row(1188511885L, true),
42+
) { id, isInvalid ->
43+
id.isSequenceRepeatedAtLeastTwice() shouldBe isInvalid
44+
}
45+
}
46+
47+
"part 1: the sum of all invalid IDs with sequences repeated exactly twice" {
48+
GiftShop().part1(input) shouldBe 1227775554L
49+
}
50+
51+
"part 2: the sum of all invalid IDs with sequences repeated at least twice" {
52+
GiftShop().part2(input) shouldBe 4174379265L
53+
}
54+
})

0 commit comments

Comments
 (0)