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

Advent of Code 2023 Day 3 Part 1

2023_day3_part1.livemd

Advent of Code 2023 Day 3 Part 1

Mix.install([
  {:kino_aoc, "~> 0.1.5"}
])

Get Inputs

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "3", System.fetch_env!("LB_SESSION"))

My answer

defmodule Resolver do
  def parse(input) do
    parsed_input =
      input
      |> String.split("\n")
      |> Enum.with_index()
      |> Enum.map(fn {line, row_index} ->
        number = Regex.scan(~r/[0-9]+/, line)
        number_index = Regex.scan(~r/[0-9]+/, line, return: :index)
        symbol = Regex.scan(~r/[^0-9\.]+/, line)
        symbol_index = Regex.scan(~r/[^0-9\.]+/, line, return: :index)

        numbers =
          Enum.zip(number_index, number)
          |> Enum.into(%{}, fn {[{col_index, length}], [number]} ->
            {{row_index, col_index, length}, String.to_integer(number)}
          end)

        symbols =
          Enum.zip(symbol_index, symbol)
          |> Enum.into(%{}, fn {[{col_index, length}], [symbol]} ->
            {{row_index, col_index, length}, symbol}
          end)

        %{
          numbers: numbers,
          symbols: symbols
        }
      end)

    numbers =
      parsed_input
      |> Enum.reduce(%{}, fn line, acc ->
        Map.merge(acc, line.numbers)
      end)

    symbols =
      parsed_input
      |> Enum.reduce(%{}, fn line, acc ->
        Map.merge(acc, line.symbols)
      end)

    {numbers, symbols}
  end

  def resolve(numbers, symbols) do
    numbers
    |> Enum.filter(fn {{num_row_index, num_col_index, num_length}, _number} ->
      Enum.find(symbols, fn {{sym_row_index, sym_col_index, _sym_length}, _symbol} ->
        sym_row_index >= num_row_index - 1 and sym_row_index <= num_row_index + 1 and
          sym_col_index >= num_col_index - 1 and sym_col_index <= num_col_index + num_length
      end)
    end)
    |> Enum.map(fn {_index, number} -> number end)
    |> Enum.sum()
  end
end
{numbers, symbols} =
  """
  467..114..
  ...*......
  ..35..633.
  ......#...
  617*......
  .....+.58.
  ..592.....
  ......755.
  ...$.*....
  .664.598..
  """
  |> String.slice(0..-2)
  |> Resolver.parse()
Resolver.resolve(numbers, symbols)
{numbers, symbols} = Resolver.parse(puzzle_input)
Resolver.resolve(numbers, symbols)