Advent of Code 2024 - Day 4 - Ceres Search

Поделиться
HTML-код
  • Опубликовано: 11 янв 2025

Комментарии • 3

  • @aaronperl
    @aaronperl Месяц назад

    (did my comment on Day 3 not get posted? I had written something up, and I thought I had pushed the button, but I don't see it on the video now. Hm)
    I mis-read the question the first time, and I missed that words could go diagonally. So, I wrote a rotate function to turn my grid of letters by 90 degrees so that I could just look for "XMAS" in each direction .... and then when I only found half the expected words, I realized my mistake. 🤦‍♂
    Then my proper solution was a straightforward search, when I find an "X" I look in each direction around it for "M-A-S". In my first attempt I forgot that it was possible to have multiple matches on a single X.
    My solution for Part B was more similar to yours, I look for "A" and then check the diagonals for "M" and "S". I saved the diagonals into string variables so that I could check for "MAS or SAM" in each direction, which I felt simplified the condition checking a little:
    if (r[c] == "A") {
    val ul = this.matrix[rowIndex-1][c-1]
    val ur = this.matrix[rowIndex-1][c+1]
    val ll = this.matrix[rowIndex+1][c-1]
    val lr = this.matrix[rowIndex+1][c+1]
    val ldiag = ul + r[c] + lr
    val rdiag = ll + r[c] + ur
    if ((ldiag == "MAS" || ldiag == "SAM") && (rdiag == "MAS" || rdiag == "SAM")) {
    count++
    }
    I thought this was a fun puzzle. I think they have one like this every year, but they're fun.

  • @WayneBagguley
    @WayneBagguley Месяц назад +1

    Managed to do both parts in one line again but here's the uncompressed part 1 solution first:
    fun calc(input: List): Int = input.find('X').sumOf { input.valid("XMAS", it) }
    private fun List.find(character: Char): List =
    flatMapIndexed { y, s -> s.mapIndexed { x, c -> x to c }
    .filter { it.second == character }.map { it.first to y } }
    private fun List.valid(word: String, point: Pair): Int =
    listOf(0 to -1, 1 to -1, 1 to 0, 1 to 1, 0 to 1, -1 to 1, -1 to 0, -1 to -1)
    .count { valid(word, point, it.first, it.second) }
    private fun List.valid(word: String, point: Pair, xStep:Int, yStep: Int): Boolean =
    word.indices.map { getOrNull(point.second + it * yStep)?.getOrNull(point.first + it * xStep) ?: "" }
    .joinToString("") == word
    Compressed to one line:
    fun calc(input: List): Int = input.flatMapIndexed { y, s -> s.mapIndexed { x, c -> x to c }
    .filter { it.second == 'X' }.map { it.first to y } }.sumOf { p ->
    listOf(0 to -1, 1 to -1, 1 to 0, 1 to 1, 0 to 1, -1 to 1, -1 to 0, -1 to -1)
    .count { o -> "XMAS".indices.map { input.getOrNull(p.second + it * o.second)
    ?.getOrNull(p.first + it * o.first) ?: "" }.joinToString("") == "XMAS" } }

    • @WayneBagguley
      @WayneBagguley Месяц назад

      Part 2:
      fun calc(input:List): Int = input.find('A').count { input.valid("MAS", it) }
      private fun List.find(character: Char): List =
      flatMapIndexed { y, s -> s.mapIndexed { x, c -> x to c }
      .filter { it.second == character }.map { it.first to y } }
      private fun List.valid(word: String, point: Pair): Boolean {
      val w1 = extract(point, listOf(-1 to -1, 0 to 0, 1 to 1))
      val w2 = extract(point, listOf(1 to -1, 0 to 0, -1 to 1))
      return (w1 == word || w1 == word.reversed()) && (w2 == word || w2 == word.reversed())
      }
      private fun List.extract(point: Pair, steps: List): String =
      steps.map { s -> getOrNull(point.second + s.second)?.getOrNull(point.first + s.first) ?: "" }.joinToString("")
      Compressed:
      fun calc(input:List): Int = input.flatMapIndexed { y, s -> s.mapIndexed { x, c -> x to c }
      .filter { it.second == 'A' }.map { it.first to y } }.count { p -> listOf(listOf(-1 to -1, 0 to 0, 1 to 1),
      listOf(1 to -1, 0 to 0, -1 to 1)).map{ it.map { s -> input.getOrNull(p.second + s.second)
      ?.getOrNull(p.first + s.first) ?: "" }.joinToString("") }.all { it in listOf("MAS", "SAM") } }