• 0 Posts
  • 17 Comments
Joined 1 year ago
cake
Cake day: July 1st, 2023

help-circle
  • Elixir

    defmodule AdventOfCode.Solution.Year2024.Day01 do
      use AdventOfCode.Solution.SharedParse
    
      @impl true
      def parse(input) do
        numbers =
          input
          |> String.split("\n", trim: true)
          |> Enum.map(fn l -> String.split(l, ~r/\s+/) |> Enum.map(&String.to_integer/1) end)
    
        {Stream.map(numbers, &Enum.at(&1, 0)), Stream.map(numbers, &Enum.at(&1, 1))}
      end
    
      def part1({left, right}) do
        Enum.zip_reduce(Enum.sort(left), Enum.sort(right), 0, &(&3 + abs(&1 - &2)))
      end
    
      def part2({left, right}) do
        freq = Enum.frequencies(right)
        left |> Stream.map(&(&1 * Map.get(freq, &1, 0))) |> Enum.sum()
      end
    end
    

  • Elixir

    defmodule AdventOfCode.Solution.Year2024.Day02 do
      use AdventOfCode.Solution.SharedParse
    
      @impl true
      def parse(input) do
        for line <- String.split(input, "\n", trim: true),
            do: String.split(line) |> Enum.map(&String.to_integer/1)
      end
    
      def part1(input) do
        Enum.count(input, &is_safe(&1, false))
      end
    
      def part2(input) do
        Enum.count(input, &(is_safe(&1, true) or is_safe(tl(&1), false)))
      end
    
      def is_safe([a, b, c | rest], can_fix) do
        cond do
          (b - a) * (c - b) > 0 and abs(b - a) in 1..3 and abs(c - b) in 1..3 ->
            is_safe([b, c | rest], can_fix)
    
          can_fix ->
            is_safe([a, c | rest], false) or is_safe([a, b | rest], false)
    
          true ->
            false
        end
      end
    
      def is_safe(_, _), do: true
    end
    


  • Elixir

    defmodule AdventOfCode.Solution.Year2024.Day04 do
      use AdventOfCode.Solution.SharedParse
    
      defmodule Map do
        defstruct [:chars, :width, :height]
      end
    
      @impl true
      def parse(input) do
        chars = String.split(input, "\n", trim: true) |> Enum.map(&String.codepoints/1)
        %Map{chars: chars, width: length(Enum.at(chars, 0)), height: length(chars)}
      end
    
      def at(%Map{} = map, x, y) do
        cond do
          x < 0 or x >= map.width or y < 0 or y >= map.height -> ""
          true -> map.chars |> Enum.at(y, []) |> Enum.at(x, "")
        end
      end
    
      def part1(map) do
        dirs = for dx <- -1..1, dy <- -1..1, {dx, dy} != {0, 0}, do: {dx, dy}
        xmas = String.codepoints("XMAS") |> Enum.with_index() |> Enum.drop(1)
    
        for x <- 0..(map.width - 1),
            y <- 0..(map.height - 1),
            "X" == at(map, x, y),
            {dx, dy} <- dirs,
            xmas
            |> Enum.all?(fn {c, n} -> at(map, x + dx * n, y + dy * n) == c end),
            reduce: 0 do
          t -> t + 1
        end
      end
    
      def part2(map) do
        for x <- 0..(map.width - 1),
            y <- 0..(map.height - 1),
            "A" == at(map, x, y),
            (at(map, x - 1, y - 1) <> at(map, x + 1, y + 1)) in ["MS", "SM"],
            (at(map, x - 1, y + 1) <> at(map, x + 1, y - 1)) in ["MS", "SM"],
            reduce: 0 do
          t -> t + 1
        end
      end
    end
    

  • Elixir

    defmodule AdventOfCode.Solution.Year2024.Day05 do
      use AdventOfCode.Solution.SharedParse
    
      @impl true
      def parse(input) do
        [rules, pages_list] =
          String.split(input, "\n\n", limit: 2) |> Enum.map(&String.split(&1, "\n", trim: true))
    
        {for(rule <- rules, do: String.split(rule, "|") |> Enum.map(&String.to_integer/1))
         |> MapSet.new(),
         for(pages <- pages_list, do: String.split(pages, ",") |> Enum.map(&String.to_integer/1))}
      end
    
      def part1({rules, pages_list}), do: solve(rules, pages_list, false)
    
      def part2({rules, pages_list}), do: solve(rules, pages_list, true)
    
      def solve(rules, pages_list, negate) do
        for pages <- pages_list, reduce: 0 do
          total ->
            ordered = Enum.sort(pages, &([&1, &2] in rules))
    
            if negate != (ordered == pages),
              do: total + Enum.at(ordered, div(length(ordered), 2)),
              else: total
        end
      end
    end