From 9a8b316122ebac552e2502050f94346686ff7063 Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Thu, 12 Dec 2024 08:12:56 +0100 Subject: [PATCH] Day 12 Part 2 not correct. --- src/Utils.kt | 5 +- src/aoc2024/Day12.kt | 122 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/aoc2024/Day12.kt diff --git a/src/Utils.kt b/src/Utils.kt index f4ca8a2..30c0a12 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -196,6 +196,9 @@ class CharGrid { fun matchRelative(c: Int, r: Int, relposes: Iterable, predicate: (char: Char) -> Boolean): List = relposes.filter { predicate(get(c + it.dc, r + it.dr)) } + fun matchAbsoluteRelPos(pos: RelPos, relposes: Iterable, predicate: (char: Char) -> Boolean): List = + relposes.map { pos.translate(it) }.filter { predicate(get(it)) } + fun marchMatching(pos: RelPos, relposes: Iterable, predicate: (char: Char) -> Boolean): List = relposes.map { pos.translate(it) }.filter { predicate(get(it)) } @@ -215,7 +218,7 @@ class CharGrid { val topBottom = CharArray(width + 2) { borderChar } return CharGrid(Array(height + 2) { if (it == 0 || it == height + 1) topBottom else - CharArray(width + 2) { r -> if (r == 0 || r == width + 1) borderChar else get(it - 1, r - 1) } + CharArray(width + 2) { r -> if (r == 0 || r == width + 1) borderChar else get(r - 1, it - 1) } }, borderChar) } diff --git a/src/aoc2024/Day12.kt b/src/aoc2024/Day12.kt new file mode 100644 index 0000000..5ee77bd --- /dev/null +++ b/src/aoc2024/Day12.kt @@ -0,0 +1,122 @@ +package aoc2024 + +import CharGrid +import RelPos +import println +import readInput + +/* +--- Day 12: Garden Groups --- +https://adventofcode.com/2024/day/12 +*/ +fun main() { + + val inlineTestInput = """ +RRRRIICCFF +RRRRIICCCF +VVRRRCCFFF +VVRCCCJFFF +VVVVCJJCFE +VVIVCCJJEE +VVIIICJJEE +MIIIIIJJEE +MIIISIJEEE +MMMISSJEEE + """ + + fun part1(input: List): Int { + val grid = CharGrid(input) + var sum = 0 + for (p in grid.generateGridPos()) { + val c = grid[p] + if (c != '.') { + val areaPos = HashSet() + val fence = HashSet() + var newPos = setOf(p) + while (newPos.isNotEmpty()) { + val newSeeds = HashSet() + for (np in newPos) { + areaPos.add(np) + grid[np] = c.lowercaseChar() + newSeeds.addAll(grid.matchAbsoluteRelPos(np, CharGrid.PLUS_POS) { it == c }) + fence.addAll(grid.matchRelative(np.dc, np.dr, CharGrid.PLUS_POS) { it.uppercaseChar() != c } + .map { RelPos(np.dc * 2 + it.dc, np.dr * 2 + it.dr) }) + } + newPos = newSeeds + } + areaPos.forEach { grid[it] = '.' } + sum += areaPos.size * fence.size + } + } + return sum + } + + fun part2(input: List): Int { + val grid = CharGrid(input) + var sum = 0 + for (p in grid.generateGridPos()) { + val c = grid[p] + if (c != '.') { + println("$p: $c") + val areaPos = HashSet() + val fence = HashSet() + var newPos = setOf(p) + while (newPos.isNotEmpty()) { + val newSeeds = HashSet() + for (np in newPos) { + areaPos.add(np) + grid[np] = c.lowercaseChar() + newSeeds.addAll(grid.matchAbsoluteRelPos(np, CharGrid.PLUS_POS) { it == c }) + fence.addAll(grid.matchRelative(np.dc, np.dr, CharGrid.BOX_POS) { it.uppercaseChar() != c } + .map { RelPos(np.dc * 2 + it.dc, np.dr * 2 + it.dr) }) + } + newPos = newSeeds + } + var turns = 0 + while (fence.isNotEmpty()) { + val f1 = fence.first() + var dir = CharGrid.PLUS_POS.find { fence.contains(f1.translate(it)) } + if (dir == null) { + fence.remove(f1) + turns += 2 + break + } + + // 851006 too low + // 852491 too high + val initDir = dir + var rp = f1 + while (fence.isNotEmpty()) { + fence.remove(rp) + if (fence.contains(rp.translate(dir!!))) { + rp = rp.translate(dir) + } else { + dir = CharGrid.PLUS_POS.find { fence.contains(rp.translate(it)) } ?: break + rp = rp.translate(dir) + turns++ + } + } + if (initDir != dir) turns++ + } + println("$c Area: ${areaPos.size} Fence: ${fence.size} Discount: $turns = ${areaPos.size * turns}") + areaPos.forEach { grid[it] = '.' } + sum += areaPos.size * turns + } + } + return sum + } + + // test if implementation meets criteria from the description, like: + val testInput = inlineTestInput.trim().reader().readLines() + //val testInput = readInput("aoc2024/Day12_test") + val testInputPart1Result = part1(testInput) + println("Part 1 Test: $testInputPart1Result") + val testInputPart2Result = part2(testInput) + println("Part 2 Test: $testInputPart2Result") + check(testInputPart1Result == 1930) + check(testInputPart2Result == 1206) + + val input = readInput("aoc2024/Day12") + part1(input).println() + part2(input).println() +}