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

--- Day 2: Red-Nosed Reports ---

2024/day_2.livemd

— Day 2: Red-Nosed Reports —

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

Section

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "2", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
defmodule RedNosedReports do
  def parse(input) do
    input
    |> String.split("\n")
    |> Enum.map(fn report ->
      for level <- String.split(report) do
        String.to_integer(level)
      end
    end)
  end

  def ordered?(report) do
    asc? = report == Enum.sort(report)
    desc? = report == Enum.sort(report, :desc)

    asc? || desc?
  end

  def gradual?([first | rest]) do
    result =
      Enum.reduce_while(rest, first, fn
        next_level, prev_level ->
          if abs(prev_level - next_level) in 1..3 do
            {:cont, next_level}
          else
            {:halt, :unsafe}
          end
      end)

    result != :unsafe
  end

  def safe?(report), do: ordered?(report) &amp;&amp; gradual?(report)

  def dampener(report) do
    if safe?(report) do
      true
    else
      Enum.reduce_while(report, false, fn level, _acc ->
        if safe?(report -- [level]) || safe?(Enum.reverse(report) -- [level]) do
          {:halt, true}
        else
          {:cont, false}
        end
      end)
    end
  end
end
import RedNosedReports

puzzle_input
|> parse()
|> Enum.map(&amp;safe?/1)
|> Enum.count(&amp; &amp;1)
import RedNosedReports

puzzle_input
|> parse()
|> Enum.map(&amp;dampener/1)
|> Enum.count(&amp; &amp;1)