Skip to content
Open
Show file tree
Hide file tree
Changes from 22 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.gradle/
/.idea/
/build/
/src/test/kotlin/*/input
19 changes: 18 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.7.10"
application
id("com.diffplug.spotless") version "6.12.0"
}

group = "de.thomas-popp"
Expand All @@ -13,9 +14,25 @@ repositories {
}

dependencies {
implementation("org.jgrapht", "jgrapht-core", "1.5.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
testImplementation(kotlin("test"))
}

spotless { // if you are using build.gradle.kts, instead of 'spotless {' use:
// configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
// by default the target is every '.kt' and '.kts` file in the java sourcesets
ktfmt() // has its own section below
// ktlint() // has its own section below
// diktat() // has its own section below
// prettier() // has its own section below
}
kotlinGradle {
ktlint() // or ktfmt() or prettier()
}
}

tasks.test {
useJUnitPlatform()
}
Expand All @@ -26,4 +43,4 @@ tasks.withType<KotlinCompile> {

application {
mainClass.set("MainKt")
}
}
1 change: 0 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@

rootProject.name = "aoc_2022"

11 changes: 6 additions & 5 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
fun main(args: Array<String>) {
println("Hello World!")
println("Hello World!")

// Try adding program arguments via Run/Debug configuration.
// Learn more about running applications: https://www.jetbrains.com/help/idea/running-applications.html.
println("Program arguments: ${args.joinToString()}")
}
// Try adding program arguments via Run/Debug configuration.
// Learn more about running applications:
// https://www.jetbrains.com/help/idea/running-applications.html.
println("Program arguments: ${args.joinToString()}")
}
59 changes: 29 additions & 30 deletions src/test/kotlin/day1/Day1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,41 @@ import kotlin.test.assertEquals

internal class Day1 {

@Test
fun sampleSilver(){
val elves = create_elves(read_puzzle_input("sample_silver"))
assertEquals(24000, elves.map { it.sum() }.max())
}

@Test
fun sampleGold(){
val elves = create_elves(read_puzzle_input("sample_silver"))
assertEquals(45000, elves.map { it.sum() }.sortedDescending().take(3).sum())
}

@Test
fun silver() {
val elves = create_elves(read_puzzle_input("input_silver"))
assertEquals(69795, elves.map { it.sum() }.max())
}

@Test
fun gold(){
val elves = create_elves(read_puzzle_input("input_silver"))
assertEquals(208437, elves.map { it.sum() }.sortedDescending().take(3).sum())
}
@Test
fun sampleSilver() {
val elves = create_elves(read_puzzle_input("sample_silver"))
assertEquals(24000, elves.map { it.sum() }.max())
}

@Test
fun sampleGold() {
val elves = create_elves(read_puzzle_input("sample_silver"))
assertEquals(45000, elves.map { it.sum() }.sortedDescending().take(3).sum())
}

@Test
fun silver() {
val elves = create_elves(read_puzzle_input("input_silver"))
assertEquals(69795, elves.map { it.sum() }.max())
}

@Test
fun gold() {
val elves = create_elves(read_puzzle_input("input_silver"))
assertEquals(208437, elves.map { it.sum() }.sortedDescending().take(3).sum())
}
}

data class Elv(val snacks: List<Int>)

fun Elv.sum(): Int {
return snacks.sum()
return snacks.sum()
}

fun create_elves( raw : String): List<Elv> {
return raw.split("\n\n").map { Elv(it.split("\n").map { it.toInt() } )}
fun create_elves(raw: String): List<Elv> {
return raw.split("\n\n").map { Elv(it.split("\n").map { it.toInt() }) }
}

fun read_puzzle_input( filename : String): String {
return File("src/test/kotlin/day1/$filename")
.readText(Charsets.UTF_8)
}
fun read_puzzle_input(filename: String): String {
return File("src/test/kotlin/day1/$filename").readText(Charsets.UTF_8)
}
225 changes: 225 additions & 0 deletions src/test/kotlin/day10/Day10.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package day10

import java.io.File
import java.lang.UnsupportedOperationException
import java.util.*
import kotlin.math.abs
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import org.junit.jupiter.api.Test

class Day10 {
@Test
fun sampleSilver() {
val cpu = CPU(parseCommands("sample"))

cpu.cycle()
assertEquals(1, cpu.getRegister())

cpu.cycle()
assertEquals(1, cpu.getRegister())

cpu.cycle()
assertEquals(4, cpu.getRegister())

cpu.cycle()
assertEquals(4, cpu.getRegister())

cpu.cycle()
assertEquals(-1, cpu.getRegister())

assertFalse(cpu.cycle())
}

@Test
fun sampleSilverLarge() {
val cpu = CPU(parseCommands("large"))

val history =
(0..220).map {
cpu.cycle()
cpu.getRegister()
}

assertEquals(21, history[18])
assertEquals(19, history[58])
assertEquals(18, history[98])
assertEquals(21, history[138])
assertEquals(16, history[178])
assertEquals(18, history[218])

val solution =
history
.withIndex()
.filterIndexed { index, _ ->
index == 18 ||
index == 58 ||
index == 98 ||
index == 138 ||
index == 178 ||
index == 218
}
.fold(0) { acc, i -> acc.plus((i.index + 2) * i.value) }

assertEquals(13140, solution)
}

@Test
fun silver() {
val cpu = CPU(parseCommands("input"))

val history =
(0..220).map {
cpu.cycle()
cpu.getRegister()
}

val solution =
history
.withIndex()
.filterIndexed { index, _ ->
index == 18 ||
index == 58 ||
index == 98 ||
index == 138 ||
index == 178 ||
index == 218
}
.fold(0) { acc, i -> acc.plus((i.index + 2) * i.value) }

assertEquals(13740, solution)
}

@Test
fun gold() {
val cpu = CPU(parseCommands("input"))

val sprite = "###....................................."
var spriteForEachCycle =
(0..250).map {
cpu.cycle()
moveSprite(sprite, cpu.getRegister() - 1)
}

spriteForEachCycle = listOf(sprite) + spriteForEachCycle

val line1 =
(0..39)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }
val line2 =
(40..79)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }
val line3 =
(80..119)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }
val line4 =
(120..159)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }
val line5 =
(160..199)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }
val line6 =
(200..239)
.mapIndexed { idx, it -> spriteForEachCycle[it][idx] }
.fold("") { acc, c -> acc.plus(c) }

assertEquals(line1, "####.#..#.###..###..####.####..##..#....")
assertEquals(line2, "...#.#..#.#..#.#..#.#....#....#..#.#....")
assertEquals(line3, "..#..#..#.#..#.#..#.###..###..#....#....")
assertEquals(line4, ".#...#..#.###..###..#....#....#....#....")
assertEquals(line5, "#....#..#.#....#.#..#....#....#..#.#....")
assertEquals(line6, "####..##..#....#..#.#....####..##..####.")
}
}

fun moveSprite(sprite: String, modifier: Int): String {
return if (modifier > 0) {
(".".repeat(modifier) + sprite).substring(0..39)
} else if (modifier < 0) {
sprite.substring(abs(modifier)) + (".".repeat(abs(modifier)))
} else {
sprite
}
}

enum class CommandType(val cycles: Int) {
NOOP(1),
ADDX(2);

companion object {
fun fromString(command: String): CommandType {
return when (command) {
"noop" -> NOOP
"addx" -> ADDX
else -> throw UnsupportedOperationException()
}
}
}
}

class Command(pair: Pair<CommandType, Optional<Int>>) {
private var type = pair.first
private var optional = pair.second
private var cycle = 0

fun cycle(): Boolean {
cycle += 1
return type.cycles == cycle
}

fun execute(register: Int): Int {
if (optional.isPresent) {
return register.plus(optional.get())
}
return register
}
}

class CPU(private val commandQueue: List<Command>) {
private var register: Int = 1
private var cycle: Long = 0
private var commandIndex: Int = 0

fun cycle(): Boolean {
if (commandQueue.size == commandIndex) {
return false
}
cycle++

val currentCommand = commandQueue[commandIndex]

if (currentCommand.cycle()) {
commandIndex += 1
register = currentCommand.execute(register)
}
return true
}

fun getRegister(): Int {
return register
}
}

private fun parseCommands(filename: String): List<Command> {
return File("src/test/kotlin/day10/$filename")
.readLines()
.map {
val split = it.split(" ")
split.first() to split.last()
}
.map { (command, value) ->
val optionalValue = value.toIntOrNull()
Command(
CommandType.fromString(command) to
if (optionalValue == null) {
Optional.empty()
} else {
Optional.of(optionalValue)
})
}
}
Loading