Skip to content

Commit 926ab32

Browse files
committed
Day 4
1 parent 70153b4 commit 926ab32

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

src/main/kotlin/common/datastructures/Grid.kt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private val neighsYDiags = listOf(0, 1, 1, 1, 0, -1, -1, -1)
1111
data class Dir(val dRow: Int, val dCol: Int)
1212
fun Dir.toPoint() = Point(dCol, dRow)
1313
val directions: List<Dir> = (0..3).map { i -> Dir(neighsY[i], neighsX[i]) }
14+
val directionsWithDiagonals: List<Dir> = neighsYDiags.zip(neighsXDiags) { y, x -> Dir(y, x) }
1415

1516
class Grid<T>(val rows: List<List<Cell<T>>>) {
1617
constructor(rows: Int, cols: Int, constructor: (row: Int, col: Int) -> T) : this(Array(rows) { row ->

src/main/kotlin/y24/Day4.kt

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package y24
2+
3+
import common.puzzle.solvePuzzle
4+
import common.puzzle.Input
5+
import common.puzzle.Puzzle
6+
import common.datastructures.*
7+
import common.ext.*
8+
import common.util.*
9+
import java.util.*
10+
import kotlin.math.*
11+
import kotlin.system.exitProcess
12+
13+
14+
fun main() = solvePuzzle(year = 2024, day = 4) { Day4(it) }
15+
16+
class Day4(val input: Input) : Puzzle {
17+
18+
override fun solveLevel1(): Any {
19+
val grid = Grid(input.lines.size, input.lines[0].length) { r, c ->
20+
input.lines[r][c]
21+
}
22+
23+
return grid.cells()
24+
.sumOf { cell ->
25+
grid.countAt(cell.row, cell.col)
26+
}
27+
}
28+
29+
private fun Grid<Char>.countAt(row: Int, col: Int, text: String = "XMAS"): Int {
30+
return directionsWithDiagonals.count { dir ->
31+
var r = row
32+
var c = col
33+
text.all { ch ->
34+
if (!withinBounds(r, c)) return@count false
35+
val matches = this[r][c].value == ch
36+
37+
r += dir.dRow
38+
c += dir.dCol
39+
matches
40+
}
41+
}
42+
}
43+
44+
private fun Grid<Char>.isXMas(row: Int, col: Int): Boolean {
45+
if (this[row][col].value != 'A') return false
46+
47+
if (row == 0 || row == numRows - 1 || col == 0 || col == numCols - 1) return false
48+
49+
return setOf(this[row - 1][col - 1].value, this[row + 1][col + 1].value) == setOf('M', 'S') &&
50+
setOf(this[row - 1][col + 1].value, this[row + 1][col - 1].value) == setOf('M', 'S')
51+
}
52+
53+
override fun solveLevel2(): Any {
54+
val grid = Grid(input.lines.size, input.lines[0].length) { r, c ->
55+
input.lines[r][c]
56+
}
57+
58+
return grid.cells()
59+
.count { cell ->
60+
grid.isXMas(cell.row, cell.col)
61+
}
62+
}
63+
}

src/test/kotlin/y24/Day4Test.kt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package y24
2+
3+
import common.puzzle.Input
4+
import org.junit.jupiter.api.Assertions.assertEquals
5+
import org.junit.jupiter.api.Test
6+
7+
internal class Day4Test {
8+
private val sample = Input("""
9+
MMMSXXMASM
10+
MSAMXMSMSA
11+
AMXSXMAAMM
12+
MSAMASMSMX
13+
XMASAMXAMM
14+
XXAMMXXAMA
15+
SMSMSASXSS
16+
SAXAMASAAA
17+
MAMMMXMMMM
18+
MXMXAXMASX
19+
""".trimIndent())
20+
21+
private val day = Day4(sample)
22+
23+
@Test
24+
fun solveLevel1() {
25+
assertEquals(18, day.solveLevel1())
26+
}
27+
28+
@Test
29+
fun solveLevel2() {
30+
assertEquals(9, day.solveLevel2())
31+
}
32+
}

0 commit comments

Comments
 (0)