Run this notebook

Use Livebook to open this notebook and explore new ideas.

It is easy to get started, on your machine or the cloud.

Click below to open and run it in your Livebook at .

(or change your Livebook location)

# Day 4: Ceres Search ```elixir Mix.install([ {:kino_aoc, "~> 0.1.7"} ]) ``` ## Part One "Looks like the Chief's not here. Next!" One of The Historians pulls out a device and pushes the only button on it. After a brief flash, you recognize the interior of the [Ceres monitoring station](https://adventofcode.com/2019/day/10)! As the search for the Chief continues, a small Elf who lives on the station tugs on your shirt; she'd like to know if you could help her with her _word search_ (your puzzle input). She only has to find one word: `XMAS`. This word search allows words to be horizontal, vertical, diagonal, written backwards, or even overlapping other words. It's a little unusual, though, as you don't merely need to find one instance of `XMAS` - you need to find _all of them_. Here are a few ways `XMAS` might appear, where irrelevant characters have been replaced with `.`: ``` ..X... .SAMX. .A..A. XMAS.S .X.... ``` The actual word search will be full of letters instead. For example: ``` MMMSXXMASM MSAMXMSMSA AMXSXMAAMM MSAMASMSMX XMASAMXAMM XXAMMXXAMA SMSMSASXSS SAXAMASAAA MAMMMXMMMM MXMXAXMASX ``` In this word search, `XMAS` occurs a total of _`18`_ times; here's the same word search again, but where letters not involved in any `XMAS` have been replaced with `.`: ``` ....XXMAS. .SAMXMS... ...S..A... ..A.A.MS.X XMASAMX.MM X.....XA.A S.S.S.S.SS .A.A.A.A.A ..M.M.M.MM .X.X.XMASX ``` Take a look at the little Elf's word search. _How many times does `XMAS` appear?_ <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiI0Iiwic2Vzc2lvbl9zZWNyZXQiOiJBT0MyMDI0X1NFU1NJT04iLCJ5ZWFyIjoiMjAyNCJ9","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> ```elixir {:ok, puzzle_input} = KinoAOC.download_puzzle("2024", "4", System.fetch_env!("LB_AOC2024_SESSION")) ``` ```elixir defmodule EnumUtil do def transpose(list_of_lists) do Enum.zip_with(list_of_lists, &Function.identity/1) end def rotate(list, n) do {a, b} = Enum.split(list, n) b ++ a end end word_search = String.split(puzzle_input) diag_grids = word_search |> Enum.map(&String.pad_trailing(&1, length(word_search) + String.length(&1))) |> Enum.map(&to_charlist/1) |> Enum.with_index(&EnumUtil.rotate/2) |> EnumUtil.transpose() |> Enum.chunk_every(2) |> EnumUtil.transpose() |> Enum.map(fn diagRows -> Enum.with_index(diagRows, &EnumUtil.rotate(&1, -&2)) |> EnumUtil.rotate(div(length(word_search), 2)) end) word_search_grid = Enum.map(word_search, &String.to_charlist/1) grids = [word_search_grid | diag_grids] grids |> Enum.flat_map(&[&1, EnumUtil.transpose(&1)]) |> Enum.concat() |> Enum.join("\n") |> then(&Regex.scan(~r/X(?=MAS)|S(?=AMX)/, &1)) |> Enum.count() ``` ## Part 2 The Elf looks quizzically at you. Did you misunderstand the assignment? Looking for the instructions, you flip over the word search to find that this isn't actually an _`XMAS`_ puzzle; it's an <span title="This part originally involved searching for something else, but this joke was too dumb to pass up."><code><em>X-MAS</em></code></span> puzzle in which you're supposed to find two `MAS` in the shape of an `X`. One way to achieve that is like this: ``` M.S .A. M.S ``` Irrelevant characters have again been replaced with `.` in the above diagram. Within the `X`, each `MAS` can be written forwards or backwards. Here's the same example from before, but this time all of the `X-MAS`es have been kept instead: ``` .M.S...... ..A..MSMS. .M.S.MAA.. ..A.ASMSM. .M.S.M.... .......... S.S.S.S.S. .A.A.A.A.. M.M.M.M.M. .......... ``` In this example, an `X-MAS` appears _`9`_ times. Flip the word search from the instructions back over to the word search side and try again. _How many times does an `X-MAS` appear?_ ```elixir diag_grids |> Enum.flat_map(fn grid -> for {row, rowIdx} <- Enum.with_index(grid) |> Enum.drop(1), {slice, colIdx} <- Enum.chunk_every(row, 3, 1, :discard) |> Enum.with_index(1), slice in [~c/SAM/, ~c/MAS/], Enum.map([-1, +1], &Enum.at(Enum.at(grid, rowIdx + &1, []), colIdx)) in [~c/SM/, ~c/MS/] do {rowIdx, colIdx} end end) |> Enum.count() ``` <!-- livebook:{"offset":4182,"stamp":{"token":"XCP.3KcHMfvZRwnXfzRym_G77w1d-wvbpjOn8N1EPXrvj3HQSmh9aFmsEcp-4auB9d--5TlNj9CWojQVMIN0Vaq11Anz8bOV2uguCB5la5fBLrIThrRRHvg-Csix","version":2}} -->
See source

Have you already installed Livebook?

If you already installed Livebook, you can configure the default Livebook location where you want to open notebooks.
Livebook up Checking status We can't reach this Livebook (but we saved your preference anyway)
Run notebook

Not yet? Install Livebook in just a minute

Livebook is open source, free, and ready to run anywhere.

Run in the cloud

on select platforms

To run on Linux, Docker, embedded devices, or Elixir’s Mix, check our README.

PLATINUM SPONSORS
SPONSORS
Code navigation with go to definition of modules and functions Read More