Skip to content
Merged
Show file tree
Hide file tree
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
70 changes: 70 additions & 0 deletions src/main/kotlin/me/peckb/aoc/_2024/calendar/day22/Day22.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package me.peckb.aoc._2024.calendar.day22

import arrow.core.Tuple4
import javax.inject.Inject
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory

class Day22 @Inject constructor(
private val generatorFactory: InputGeneratorFactory,
) {
fun partOne(filename: String) = generatorFactory.forFile(filename).readAs(::secretNumber) { input ->
input.sumOf { number ->
(0 until 2000).fold(number) { n, _ -> nextNumber(n) }
}
}

fun partTwo(filename: String) = generatorFactory.forFile(filename).readAs(::secretNumber) { input ->
val data = input.toList()

val solutions = mutableMapOf<Tuple4<Long, Long, Long, Long>, Long>()

data.forEach { number->
val buyerNumbers = sequence {
var n = number
while (true) {
yield(n)
n = nextNumber(n)
}
}

val mySequences = mutableSetOf<Tuple4<Long, Long, Long, Long>>()

buyerNumbers
.map { it % 10 }
.windowed(5)
.take(2000)
.forEach { (a, b, c, d, e) ->
val k = Tuple4(b - a, c - b, d - c, e - d)
if (k !in mySequences) {
solutions.merge(k, e, Long::plus)
mySequences.add(k)
}
}
}

solutions.values.max()
}

private fun nextNumber(number: Long): Long {
var n = number

// step one
val a = n * 64 // Calculate the result of multiplying the secret number by 64.
n = n xor a // Then, mix this result into the secret number.
n %= 16_777_216 // Finally, prune the secret number.

// step two
val b = n / 32 // Calculate the result of dividing the secret number by 32.
n = n xor b // Then, mix this result into the secret number.
n %= 16_777_216 // Finally, prune the secret number.

// step three
val c = n * 2048 // Calculate the result of multiplying the secret number by 2048.
n = n xor c // Then, mix this result into the secret number.
n %= 16_777_216 // Finally, prune the secret number.

return n
}

private fun secretNumber(line: String) = line.toLong()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## [Day 22: Monkey Market](https://adventofcode.com/2024/day/22)
2 changes: 2 additions & 0 deletions src/test/kotlin/me/peckb/aoc/_2024/TestDayComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import me.peckb.aoc._2024.calendar.day18.Day18Test
import me.peckb.aoc._2024.calendar.day19.Day19Test
import me.peckb.aoc._2024.calendar.day20.Day20Test
import me.peckb.aoc._2024.calendar.day21.Day21Test
import me.peckb.aoc._2024.calendar.day22.Day22Test
import javax.inject.Singleton
import me.peckb.aoc.DayComponent
import me.peckb.aoc.InputModule
Expand Down Expand Up @@ -50,4 +51,5 @@ internal interface TestDayComponent : DayComponent {
fun inject(day19Test: Day19Test)
fun inject(day20Test: Day20Test)
fun inject(day21Test: Day21Test)
fun inject(day22Test: Day22Test)
}
32 changes: 32 additions & 0 deletions src/test/kotlin/me/peckb/aoc/_2024/calendar/day22/Day22Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package me.peckb.aoc._2024.calendar.day22

import javax.inject.Inject

import me.peckb.aoc._2024.DaggerTestDayComponent
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

internal class Day22Test {
@Inject
lateinit var day22: Day22

@BeforeEach
fun setup() {
DaggerTestDayComponent.create().inject(this)
}

@Test
fun testDay22PartOne() {
assertEquals(16039090236, day22.partOne(DAY_22))
}

@Test
fun testDay22PartTwo() {
assertEquals(1808, day22.partTwo(DAY_22))
}

companion object {
private const val DAY_22: String = "advent-of-code-input/2024/day22.input"
}
}
Loading