diff --git a/src/aoc2023/Day13.kt b/src/aoc2023/Day13.kt index 8a34f2a..b2a93c5 100644 --- a/src/aoc2023/Day13.kt +++ b/src/aoc2023/Day13.kt @@ -3,7 +3,6 @@ package aoc2023 import CharGrid import println import readInput -import kotlin.math.min /* --- Day 13: Point of Incidence --- @@ -78,66 +77,62 @@ fun main() { #....#..# """ + fun mirrored(bits: IntArray, size: Int): Int { + for (p1 in 0 until size - 1) { + var p2 = 0 + var match = true + while (p1 >= p2 && p1 + p2 + 1 < size) { + if (bits[p1 - p2] != bits[p1 + p2 + 1]) { + match = false + break + } + p2++ + } + if (match) return p1 + 1 + } + return 0 + } + + fun smudged(bits: IntArray, size: Int): Int { + for (p1 in 0 until size - 1) { + var smudges = 0 + var p2 = 0 + while (p1 >= p2 && p1 + p2 + 1 < size) { + smudges += (bits[p1 - p2] xor bits[p1 + p2 + 1]).countOneBits() + if (smudges > 1) break + p2++ + } + if (smudges == 1) return p1 + 1 + } + return 0 + } + fun part1(input: List): Int { val tmpList = ArrayList() var result = 0 - for (i in input) { + for ((idx, i) in input.withIndex()) { if (i.isNotBlank()) { tmpList.add(i) - } else { + } + if (i.isBlank() || (idx == input.lastIndex && tmpList.isNotEmpty())) { val grid = CharGrid(tmpList) val vertSA = IntArray(grid.width) - val vertSARev = IntArray(grid.width) val horzSA = IntArray(grid.height) - val horzSARev = IntArray(grid.height) for (c in 0 until grid.width) { for (r in 0 until grid.height) { - val revR = grid.height - 1 - r vertSA[c] = vertSA[c] * 2 + (if (grid[c, r] == '#') 1 else 0) - vertSARev[c] = vertSARev[c] * 2 + if (grid[c, revR] == '#') 1 else 0 } } for (r in 0 until grid.height) { for (c in 0 until grid.width) { - val revC = grid.width - 1 - c horzSA[r] = horzSA[r] * 2 + if (grid[c, r] == '#') 1 else 0 - horzSARev[r] = horzSARev[r] * 2 + if (grid[revC, r] == '#') 1 else 0 } } - - var href = 0 - for (sh in 1 until grid.height-1) { - val mask = ((1 shl grid.height) - 1) shr sh - var found = false - for (c in 0 until grid.width) { - if ((vertSA[c] shr sh) and mask != vertSARev[c] and mask) { - found = false - break - } - } - if (found) { - href = sh - } - } - - var vref = 0 - for (sh in 1 until grid.width-1) { - val width = min(sh, grid.width-sh) - val mask = (1 shl width) - 1 - var found = false - for (r in 0 until grid.height) { - if (((horzSA[r] shr ((sh-width).coerceAtLeast(0))) and mask) != ((horzSARev[r] shr (grid.width-width).coerceAtMost(0)) and mask)) { - found = false - break - } - } - if (found) { - vref = sh - } - } - for(r in 0 until grid.height) - { - println(horzSA[r].toString(2).padStart(grid.width, '0') + " " + horzSARev[r].toString(2).padStart(grid.width, '0')) + val vref = mirrored(vertSA, grid.width) + if (vref > 0) { + result += vref + } else { + result += mirrored(horzSA, grid.height) * 100 } tmpList.clear() @@ -147,7 +142,37 @@ fun main() { } fun part2(input: List): Int { - return 0 + val tmpList = ArrayList() + var result = 0 + for ((idx, i) in input.withIndex()) { + if (i.isNotBlank()) { + tmpList.add(i) + } + if (i.isBlank() || (idx == input.lastIndex && tmpList.isNotEmpty())) { + val grid = CharGrid(tmpList) + val vertSA = IntArray(grid.width) + val horzSA = IntArray(grid.height) + for (c in 0 until grid.width) { + for (r in 0 until grid.height) { + vertSA[c] = vertSA[c] * 2 + (if (grid[c, r] == '#') 1 else 0) + } + } + for (r in 0 until grid.height) { + for (c in 0 until grid.width) { + horzSA[r] = horzSA[r] * 2 + if (grid[c, r] == '#') 1 else 0 + } + } + val vref = smudged(vertSA, grid.width) + if (vref > 0) { + result += vref + } else { + result += smudged(horzSA, grid.height) * 100 + } + + tmpList.clear() + } + } + return result } // test if implementation meets criteria from the description, like: @@ -157,8 +182,8 @@ fun main() { println("Part 1 Test: $testInputPart1Result") val testInputPart2Result = part2(testInput) println("Part 2 Test: $testInputPart2Result") - check(testInputPart1Result == 0) - check(testInputPart2Result == 0) + check(testInputPart1Result == 405) + check(testInputPart2Result == 400) val input = readInput("aoc2023/Day13") part1(input).println()