diff --git a/src/main/kotlin/no/rodland/advent_2024/Day12.kt b/src/main/kotlin/no/rodland/advent_2024/Day12.kt new file mode 100644 index 0000000..dad9f86 --- /dev/null +++ b/src/main/kotlin/no/rodland/advent_2024/Day12.kt @@ -0,0 +1,84 @@ +package no.rodland.advent_2024 + +import no.rodland.advent.Day +import no.rodland.advent.Pos + +// template generated: 12/12/2024 +// Fredrik Rødland 2024 + +class Day12(val input: List) : Day, Array>> { + + private val parsed = input.parse() + private val grid = parsed.first + private val rotated = parsed.second + + data class Region(val c: Char, val positions: Set) { + operator fun contains(pos: Pos): Boolean = pos in positions + fun area() = positions.size + fun neighbours() = positions.flatMap { it.neighbourCellsUDLR() }.filterNot { it in positions } + fun perimeter(): Int = neighbours().size + } + + override fun partOne(): Int { + return findAllRegions().sumOf { + it.area() * it.perimeter() + } + } + + private fun findAllRegions(): List { + val visited = mutableSetOf() + return grid.flatMapIndexed { y, row -> + row.mapIndexed { x, c -> + val pos = Pos(x, y) + if (pos !in visited) { + Region(c, grid.getRegion(pos, visited)) + } else { + null + } + }.filterNotNull() + } + } + + @Suppress("ConvertCallChainIntoSequence") + private fun Array.getRegion(pos: Pos, visited: MutableSet): Set { + return (setOf(pos) + pos.neighbourCellsUDLR() + .filter { it !in visited } + .filter { it in grid } + .filter { grid[it] == grid[pos] } + .onEach { visited.add(it) } + .flatMap { getRegion(it, visited) } + .toList()).toSet() + } + + + override fun partTwo(): Int { + return 2 + } + + operator fun Grid.contains(pos: Pos): Boolean = pos.x >= 0 && pos.x < this[0].size && pos.y >= 0 && pos.y < this.size + + operator fun Grid.get(pos: Pos): Char = this[pos.y][pos.x] + + override fun List.parse(): Pair, Array> { + val upright = indices.map { y -> indices.map { x -> this[y][x] }.toCharArray() }.toTypedArray() + val rotated = indices.map { y -> indices.map { x -> this[x][y] }.toCharArray() }.toTypedArray() + return upright to rotated + } + + + override val day = "12".toInt() + +// private fun Grid.fences(): Int { +// flatMap { row -> +// val windowed = row.toList().windowed(2).map { (c1, c2) -> +// if (c1 == c2) 0 else 2 +// } +// windowed +// } +// return 2 +// } + + +} + + diff --git a/src/test/kotlin/no/rodland/advent_2024/Day12Test.kt b/src/test/kotlin/no/rodland/advent_2024/Day12Test.kt new file mode 100644 index 0000000..cd7fa18 --- /dev/null +++ b/src/test/kotlin/no/rodland/advent_2024/Day12Test.kt @@ -0,0 +1,83 @@ +package no.rodland.advent_2024 + +import no.rodland.advent.* +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import readFile + +// +// run: download_aoc_input.sh to download input +// + +@Suppress("ClassName") +@DisableSlow +internal class Day12Test { + private val data12 = "2024/input_12.txt".readFile() + private val test12 = "2024/input_12_test.txt".readFile() + + private val resultTestOne = 1930 + private val resultTestTwo = 2 + private val resultOne = 1424472 + private val resultTwo = 2 + + val test = defaultTestSuiteParseOnInit( + Day12(data12), + Day12(test12), + resultTestOne, + resultOne, + resultTestTwo, + resultTwo, + { Day12(data12) }, + { Day12(test12) }, + numTestPart1 = 5 + ) + + @Nested + inner class Init { + @Test + fun `12,-,example,1`() { + report(AOCTest({ "123".toInt() }, Unit, 123, 5, "12".toInt(), Part.TWO, false, "example")) + } + + @Test + fun `12,-,example,2`() { + report(test.initTest.copy()) + } + + @Test + fun `12,-,test,init`() { + report(test.initTest) + } + + @Test + fun `12,-,live,init`() { + report(test.initLive) + } + } + + @Nested + inner class `Part 1` { + @Test + fun `12,1,test`() { + report(test.testPart1) + } + + @Test + fun `12,1,live,1`() { + report(test.livePart1) + } + } + + @Nested + inner class `Part 2` { + @Test + fun `12,2,test`() { + report(test.testPart2) + } + + @Test + fun `12,2,live,1`() { + report(test.livePart2) + } + } +} diff --git a/src/test/resources/2024/input_12_test.txt b/src/test/resources/2024/input_12_test.txt index e69de29..0b328f1 100644 --- a/src/test/resources/2024/input_12_test.txt +++ b/src/test/resources/2024/input_12_test.txt @@ -0,0 +1,10 @@ +RRRRIICCFF +RRRRIICCCF +VVRRRCCFFF +VVRCCCJFFF +VVVVCJJCFE +VVIVCCJJEE +VVIIICJJEE +MIIIIIJJEE +MIIISIJEEE +MMMISSJEEE \ No newline at end of file