Powered by AppSignal & Oban Pro

Day 3

elixir/Day 3.livemd

Day 3

Module

defmodule Day3 do
  def process_trhee([upper, middle, lower]) do
    nonsense = [".", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

    characters =
      middle
      |> String.graphemes()
      |> Enum.with_index()
      |> Enum.filter(fn {val, _} -> !Enum.any?(nonsense, fn ch -> ch == val end) end)
      |> Enum.map(fn {_, idx} -> idx end)

    upper = process_line(characters, upper)
    middle = process_line(characters, middle)
    lower = process_line(characters, lower)

    Enum.zip([upper, middle, lower])
    |> Enum.map(&Tuple.to_list/1)
    |> Enum.map(&Enum.flat_map(&1, fn x -> x end))
  end

  def process_line(characters, line) do
    characters
    |> Enum.map(&String.split_at(line, &1))
    |> Enum.map(fn {l, r} -> {l, String.at(r, 0), String.slice(r, 1..-1)} end)
    |> Enum.map(&Day3.parse_chunks/1)
  end

  def parse_chunks({l, m, r}) do
    right = parse(r)
    medium = parse(m)
    left = String.reverse(parse(String.reverse(l)))

    numbers =
      case medium == "" do
        true -> [left, right]
        false -> [left <> medium <> right]
      end

    Enum.filter(numbers, fn val -> val != "" end)
    |> Enum.map(&String.to_integer/1)
  end

  def parse(string) do
    numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
    first = String.at(string, 0)

    case Enum.any?(numbers, fn ch -> first == ch end) do
      true -> first <> parse(String.slice(string, 1..-1))
      false -> ""
    end
  end
end
{:module, Day3, <<70, 79, 82, 49, 0, 0, 20, ...>>, {:parse, 1}}

Part 1

File.read!("../input/day3.txt")
|> String.split("\n")
|> Enum.chunk_every(3, 1, :discard)
|> Enum.flat_map(&Day3.process_trhee/1)
|> Enum.map(&Enum.sum/1)
|> Enum.sum()
532428

Part 2

File.read!("../input/day3.txt")
|> String.split("\n")
|> Enum.chunk_every(3, 1, :discard)
|> Enum.flat_map(&Day3.process_trhee/1)
|> Enum.filter(fn x -> Enum.count(x) > 1 end)
|> Enum.map(&Enum.product/1)
|> Enum.sum()
84051670