Files
advent-of-code/src/aoc2023/Day13.kt
T

143 lines
4.1 KiB
Kotlin

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<String>): Int {
val tmpList = ArrayList<String>()
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<String>): Int {
val tmpList = ArrayList<String>()
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()
}