hugomd / adventofcode2022

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Advent of Code 2022

Mix.install([
  {:req, "~> 0.3.2"}
])

Set up

aoc_session = System.fetch_env!("LB_AOC_SESSION")

get_input = fn url ->
  Req.get!(url, headers: [cookie: "session=#{aoc_session}"]).body
  |> String.split("\n")
end

Day 1: Part 1

day_one_input_url = "https://adventofcode.com/2022/day/1/input"

day_one_input = get_input.(day_one_input_url)

day_one_input
|> Enum.chunk_by(fn pack -> pack == "" end)
|> Enum.filter(fn pack -> pack != [""] end)
|> Enum.map(fn pack -> Enum.map(pack, &String.to_integer/1) end)
|> Enum.map(fn pack -> Enum.sum(pack) end)
|> Enum.max()

Day 1: Part 2

day_one_input
|> Enum.chunk_by(fn pack -> pack == "" end)
|> Enum.filter(fn pack -> pack != [""] end)
|> Enum.map(fn pack -> Enum.map(pack, &String.to_integer/1) end)
|> Enum.map(fn pack -> Enum.sum(pack) end)
|> Enum.sort(:desc)
|> Enum.take(3)
|> Enum.sum()

Day 2: Part 1

day_two_input_url = "https://adventofcode.com/2022/day/2/input"

day_two_input = get_input.(day_two_input_url)

defmodule Day2Scorer1 do
  def to_play({_, _} = t),
    do:
      t
      |> Tuple.to_list()
      |> Enum.map(&to_play/1)
      |> List.to_tuple()

  def to_play(play) do
    case play do
      :A -> :Rock
      :B -> :Paper
      :C -> :Scissors
      :X -> :Rock
      :Y -> :Paper
      :Z -> :Scissors
    end
  end

  def outcome(game) do
    case game do
      {:Rock, :Scissors} -> :loss
      {:Scissors, :Paper} -> :loss
      {:Paper, :Rock} -> :loss
      {:Scissors, :Rock} -> :win
      {:Rock, :Paper} -> :win
      {:Paper, :Scissors} -> :win
      {left, right} when left == right -> :tie
    end
  end

  def outcome_points(outcome) do
    case outcome do
      :loss -> 0
      :tie -> 3
      :win -> 6
    end
  end

  def play_points(play) do
    case play do
      :Rock -> 1
      :Paper -> 2
      :Scissors -> 3
    end
  end

  def determine_points(game) do
    play = to_play(game)
    {_, your_play} = play
    outcome = outcome(play)

    outcome_points(outcome) + play_points(your_play)
  end
end

day_two_input
|> Enum.map(fn strat -> String.trim(strat) end)
|> Enum.map(fn strat -> String.split(strat, " ") end)
|> Enum.map(fn strat -> Enum.map(strat, &String.to_atom/1) end)
|> Enum.map(&List.to_tuple/1)
|> Enum.filter(fn
  {:""} -> false
  _ -> true
end)
|> Enum.map(&Day2Scorer1.determine_points/1)
|> Enum.sum()

Day 2: Part 2

defmodule Day2Scorer2 do
  def to_play(play) do
    case play do
      :A -> :Rock
      :B -> :Paper
      :C -> :Scissors
    end
  end

  def wanted_outcome(yours) do
    case yours do
      :X -> :loss
      :Y -> :tie
      :Z -> :win
    end
  end

  def select_move(outcome, theirs) do
    case outcome do
      :loss -> get_loss(theirs)
      :tie -> get_tie(theirs)
      :win -> get_win(theirs)
    end
  end

  def get_win(theirs) do
    case theirs do
      :Rock -> :Paper
      :Scissors -> :Rock
      :Paper -> :Scissors
    end
  end

  def get_tie(theirs), do: theirs

  def get_loss(theirs) do
    case theirs do
      :Rock -> :Scissors
      :Scissors -> :Paper
      :Paper -> :Rock
    end
  end

  def outcome_points(outcome) do
    case outcome do
      :loss -> 0
      :tie -> 3
      :win -> 6
    end
  end

  def play_points(play) do
    case play do
      :Rock -> 1
      :Paper -> 2
      :Scissors -> 3
    end
  end

  def determine_points(game) do
    {their_move, your_move} = game
    their_play = to_play(their_move)

    wanted_outcome = wanted_outcome(your_move)
    your_play = select_move(wanted_outcome, their_play)

    outcome_points = outcome_points(wanted_outcome)
    play_points = play_points(your_play)
    outcome_points + play_points
  end
end

day_two_input
|> Enum.map(fn strat -> String.trim(strat) end)
|> Enum.map(fn strat -> String.split(strat, " ") end)
|> Enum.map(fn strat -> Enum.map(strat, &String.to_atom/1) end)
|> Enum.map(&List.to_tuple/1)
|> Enum.filter(fn
  {:""} -> false
  _ -> true
end)
|> Enum.map(&Day2Scorer2.determine_points/1)
|> Enum.sum()

Day 3: Part 1

day_three_input_url = "https://adventofcode.com/2022/day/3/input"

day_three_input = get_input.(day_three_input_url)

defmodule RuckSack do
  @priority ~c("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

  def priority(value) do
    @priority |> Enum.find_index(fn a -> a == value end)
  end

  def split(rucksack) do
    halflength = (String.length(rucksack) / 2) |> round
    {String.slice(rucksack, 0, halflength), String.slice(rucksack, halflength, halflength)}
  end

  def compare({_, _} = pair) do
    [a, b] =
      pair
      |> Tuple.to_list()
      |> Enum.map(&String.graphemes/1)
      |> Enum.map(&MapSet.new/1)

    MapSet.intersection(a, b)
  end
end

day_three_input
|> Enum.map(&RuckSack.split/1)
|> Enum.map(&RuckSack.compare/1)
|> Enum.map(&MapSet.to_list/1)
|> List.flatten()
|> List.to_charlist()
|> Enum.map(&RuckSack.priority/1)
|> Enum.sum()

Day 3: Part 2

defmodule RuckSack do
  @priority ~c("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

  def priority(value) do
    @priority |> Enum.find_index(fn a -> a == value end)
  end

  def compare([_, _, _] = triple) do
    [a, b, c] =
      triple
      |> Enum.map(&String.graphemes/1)
      |> Enum.map(&MapSet.new/1)

    MapSet.intersection(a, b) |> MapSet.intersection(c)
  end

  def compare(_), do: MapSet.new()
end

day_three_input
|> Enum.chunk_every(3)
|> Enum.map(&RuckSack.compare/1)
|> Enum.map(&MapSet.to_list/1)
|> List.flatten()
|> List.to_charlist()
|> Enum.map(&RuckSack.priority/1)
|> Enum.sum()

Day 4: Part 1

day_four_input_url = "https://adventofcode.com/2022/day/4/input"

day_four_input = get_input.(day_four_input_url)

defmodule Assignments do
  def overlap(input) do
    {a, b} =
      input
      |> Enum.chunk_every(2)
      |> Enum.map(fn [from, to] -> MapSet.new(Range.new(from, to)) end)
      |> List.to_tuple()

    MapSet.subset?(a, b) || MapSet.subset?(b, a)
  end
end

day_four_input
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, "-") end)
|> Enum.filter(fn a -> a != "" end)
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(4)
|> Enum.map(&Assignments.overlap/1)
|> Enum.filter(&Function.identity/1)
|> Enum.count()

Day 4: Part 2

defmodule Assignments do
  def intersect(input) do
    input
    |> Enum.chunk_every(2)
    |> Enum.map(fn [from, to] -> MapSet.new(Range.new(from, to)) end)
    |> then(fn [a, b] -> MapSet.intersection(a, b) end)
    |> Enum.empty?()
    |> Kernel.not()
  end
end

day_four_input
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, "-") end)
|> Enum.filter(fn a -> a != "" end)
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(4)
|> Enum.map(&Assignments.intersect/1)
|> Enum.filter(&Function.identity/1)
|> Enum.count()

About