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

Advent of Code 2024/2

2024/2.livemd

Advent of Code 2024/2

Mix.install([
  {:kino, "~> 0.14.2"}
])

Section

input = Kino.Input.textarea("input")
defmodule AoC2024_2 do
  def parse(input) do
    Kino.Input.read(input)
    |> String.split("\n", trim: true)
    |> Enum.map(fn part -> String.split(part, " ", trim: true) |> Enum.map(fn item -> String.to_integer(item) end) end)
  end

  def filter(row) do
    !Enum.any?(row, fn el -> abs(el) > 3 || el == 0 || !(Enum.all?(row, fn el -> el > 0 end) || Enum.all?(row, fn el -> el < 0 end)) end) 
  end

  def count(rows) do
    Enum.map(rows, fn row -> count_row(row) end)
  end

  def count_row(row) do
    Enum.chunk_every(row, 2, 1, :discard) |> Enum.map(fn [first, second] -> first - second end)
  end

  def part_1(input) do
    input
    |> parse
    |> count
    |> Enum.filter(fn row -> filter(row) end)
    |> Enum.count
  end

  def recount(_, true), do: true
  def recount(row, false) do
    row
    |> Enum.with_index
    |> Enum.map(fn {_, position} -> count_row(elem(List.pop_at(row, position),1)) end) 
    |> Enum.any?(fn recomb -> filter(recomb) end)
  end

  def part_2(input) do
    input
    |> parse
    |> Enum.map(fn row -> { row, Enum.chunk_every(row, 2, 1, :discard) |> Enum.map(fn [first, second] -> first - second end) } end)
    |> Enum.map(fn {row, transformed} -> { row, transformed, filter(transformed) } end)
    |> Enum.map(fn {row, transformed, safe} -> { row, transformed, safe, recount(row, safe) } end)
    |> Enum.count(fn {_, _, _, recount} -> recount end)
  end
end
AoC2024_2.part_1(input)
AoC2024_2.part_2(input)