package aoc2023 import CharGrid import println import readInput /* --- Day 13: Point of Incidence --- https://adventofcode.com/2023/day/13 */ fun main() { val inlineTestInput = """ #.##..##. ..#.##.#. ##......# ##......# ..#.##.#. ..##..##. #.#.##.#. #...##..# #....#..# ..##..### #####.##. #####.##. ..##..### #....#..# """ 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 ((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 = mirrored(vertSA, grid.width) if (vref > 0) { result += vref } else { result += mirrored(horzSA, grid.height) * 100 } tmpList.clear() } } return result } fun part2(input: List): Int { 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: val testInput = inlineTestInput.trim().reader().readLines() //val testInput = readInput("aoc2023/Day13_test") val testInputPart1Result = part1(testInput) println("Part 1 Test: $testInputPart1Result") val testInputPart2Result = part2(testInput) println("Part 2 Test: $testInputPart2Result") check(testInputPart1Result == 405) check(testInputPart2Result == 400) val input = readInput("aoc2023/Day13") part1(input).println() part2(input).println() }