Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

🎄 Year 2024 🔔 Day 04

elixir/notebooks/2024/day04.livemd

🎄 Year 2024 🔔 Day 04

Setup

input =
  File.read!("#{__DIR__}/../../../inputs/2024/day04.txt")
  |> String.split("\n", trim: true)
  |> Enum.map(&String.graphemes/1)

input_map =
  input
  |> Enum.with_index(fn row, y ->
    Enum.with_index(row, fn e, x ->
      {{x, y}, e}
    end)
  end)
  |> Enum.concat()
  |> Map.new()

max_y = Enum.count(input) - 1
max_x = Enum.at(input, 0) |> Enum.count() |> then(&(&1 - 1))

{max_x, max_y}

Part 1

input = input
transposed = List.zip(input) |> Enum.map(&Tuple.to_list/1)

top_left_diagonal =
  for end_x <- 0..max_x do
    for x <- 0..end_x, y = end_x - x, do: {x, y}
  end

bottom_right_diagonal =
  for start_x <- 1..max_x do
    for x <- start_x..max_x, y = max_y + start_x - x, do: {x, y}
  end

top_right_diagonal =
  for start_x <- 0..max_x do
    for x <- start_x..max_x, y = x - start_x, do: {x, y}
  end

bottom_left_diagonal =
  for end_x <- 0..(max_x - 1) do
    for x <- 0..end_x, y = max_y - end_x + x, do: {x, y}
  end

diagonals =
  Enum.concat([
    top_left_diagonal,
    bottom_right_diagonal,
    top_right_diagonal,
    bottom_left_diagonal
  ])
  |> Enum.map(fn line ->
    Enum.map(line, &amp;Map.fetch!(input_map, &amp;1))
  end)

Enum.concat([
  input,
  transposed,
  diagonals
])
|> Enum.filter(&amp;(Enum.count(&amp;1) >= 4))
|> Enum.flat_map(&amp;[&amp;1, Enum.reverse(&amp;1)])
|> Enum.map(&amp;Enum.join/1)
|> Enum.map(fn line ->
  line |> String.split("XMAS") |> Enum.count() |> then(&amp;(&amp;1 - 1))
end)
|> Enum.sum()

Part 2

a_coords = input_map |> Enum.filter(fn {_, e} -> e == "A" end) |> Enum.map(&amp;elem(&amp;1, 0))

a_coords
|> Enum.filter(fn {x, y} ->
  a1 = {x - 1, y - 1} |> then(&amp;Map.get(input_map, &amp;1))
  a2 = {x + 1, y + 1} |> then(&amp;Map.get(input_map, &amp;1))
  b2 = {x + 1, y - 1} |> then(&amp;Map.get(input_map, &amp;1))
  b1 = {x - 1, y + 1} |> then(&amp;Map.get(input_map, &amp;1))
  a_matches = "#{a1}A#{a2}" == "MAS" || "#{a2}A#{a1}" == "MAS"
  b_matches = "#{b1}A#{b2}" == "MAS" || "#{b2}A#{b1}" == "MAS"
  a_matches &amp;&amp; b_matches
end)
|> Enum.count()