From 4bf79c0e89632a20b057e63f101a079cf9f11c45 Mon Sep 17 00:00:00 2001
From: chrisly42 <chrisly@platon42.de>
Date: Wed, 4 Dec 2024 06:38:33 +0100
Subject: [PATCH] Added some utility functions to CharGrid.

---
 src/Utils.kt         | 30 ++++++++++++++++++++++++++++++
 src/aoc2024/Day04.kt | 27 ++++++---------------------
 2 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/src/Utils.kt b/src/Utils.kt
index 4e9e9b0..349a3a4 100644
--- a/src/Utils.kt
+++ b/src/Utils.kt
@@ -159,6 +159,36 @@ class CharGrid {
             relposes.map { get(c + it.dc, r + it.dr) }
         }
 
+    fun countStrings(relposeList: Iterable<Iterable<RelPos>>, string: String) = findMatches(relposeList) { it == string }.count()
+
+    fun findMatches(relposeList: Iterable<Iterable<RelPos>>, predicate: (content: String) -> Boolean): List<Pair<String, RelPos>> {
+        val matches = ArrayList<Pair<String, RelPos>>()
+        for (r in 0 until height) {
+            for (c in 0 until width) {
+                for (rp in relposeList) {
+                    val st = collectRelative(c, r, rp).joinToString("")
+                    if (predicate(st)) {
+                        matches.add(st to RelPos(c, r))
+                    }
+                }
+            }
+        }
+        return matches
+    }
+
+    fun findCombinedMatches(relposeList: Iterable<Iterable<RelPos>>, predicate: (content: List<String>) -> Boolean): List<RelPos> {
+        val matches = ArrayList<RelPos>()
+        for (r in 0 until height) {
+            for (c in 0 until width) {
+                val str = relposeList.map { collectRelative(c, r, it).joinToString("") }
+                if (predicate(str)) {
+                    matches.add(RelPos(c, r))
+                }
+            }
+        }
+        return matches
+    }
+
     fun matchRelative(c: Int, r: Int, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
         relposes.filter { predicate(get(c + it.dc, r + it.dr)) }
 
diff --git a/src/aoc2024/Day04.kt b/src/aoc2024/Day04.kt
index 6203e40..becf937 100644
--- a/src/aoc2024/Day04.kt
+++ b/src/aoc2024/Day04.kt
@@ -70,31 +70,16 @@ MXMXAXMASX
             listOf(RelPos(0, 0), RelPos(0, 1), RelPos(0, 2), RelPos(0, 3)),
             listOf(RelPos(0, 0), RelPos(0, -1), RelPos(0, -2), RelPos(0, -3)),
         )
-        var sum = 0
-        for (x in 0 until grid.width) {
-            for (y in 0 until grid.height) {
-                for (rp in relposes) {
-                    val st = grid.collectRelative(x, y, rp).joinToString("")
-                    if (st == "XMAS") sum++
-                }
-            }
-        }
-        return sum
+        return grid.countStrings(relposes, "XMAS")
     }
 
     fun part2(input: List<String>): Int {
         val grid = CharGrid(input)
-        val rp1 = listOf(RelPos(-1, -1), RelPos(0, 0), RelPos(1, 1))
-        val rp2 = listOf(RelPos(-1, 1), RelPos(0, 0), RelPos(1, -1))
-        var sum = 0
-        for (x in 0 until grid.width) {
-            for (y in 0 until grid.height) {
-                val st1 = grid.collectRelative(x, y, rp1).joinToString("")
-                val st2 = grid.collectRelative(x, y, rp2).joinToString("")
-                if ((st1 == "MAS" || st1 == "SAM") && (st2 == "MAS" || st2 == "SAM")) sum++
-            }
-        }
-        return sum
+        val relposes = listOf(
+            listOf(RelPos(-1, -1), RelPos(0, 0), RelPos(1, 1)),
+            listOf(RelPos(-1, 1), RelPos(0, 0), RelPos(1, -1)),
+        )
+        return grid.findCombinedMatches(relposes) { it.all { it == "MAS" || it == "SAM" } }.count()
     }
 
     // test if implementation meets criteria from the description, like: