christhekeele

christhekeele

Continuation of Advent of Code 2022​:christmas_tree:, Day 1:

Day 2!

Leaderboard:

Showing Posts 1 to 10

christhekeele

christhekeele OP

My solution lives here, with a test suite.


Part 1:
defmodule AoC.TwentyTwentyTwo.Day.Two.Part.One do
  def solve(input) do
    input
    |> Enum.map(&score_round/1)
    |> Enum.sum()
  end

  defp score_round({"A", "X"}), do: 1 + 3
  defp score_round({"A", "Y"}), do: 2 + 6
  defp score_round({"A", "Z"}), do: 3 + 0

  defp score_round({"B", "X"}), do: 1 + 0
  defp score_round({"B", "Y"}), do: 2 + 3
  defp score_round({"B", "Z"}), do: 3 + 6

  defp score_round({"C", "X"}), do: 1 + 6
  defp score_round({"C", "Y"}), do: 2 + 0
  defp score_round({"C", "Z"}), do: 3 + 3
end

Part 2:
defmodule AoC.TwentyTwentyTwo.Day.Two.Part.Two do
  def solve(input) do
    input
    |> Enum.map(&score_round/1)
    |> Enum.sum()
  end

  defp score_round({"A", "X"}), do: 0 + 3
  defp score_round({"A", "Y"}), do: 3 + 1
  defp score_round({"A", "Z"}), do: 6 + 2

  defp score_round({"B", "X"}), do: 0 + 1
  defp score_round({"B", "Y"}), do: 3 + 2
  defp score_round({"B", "Z"}), do: 6 + 3

  defp score_round({"C", "X"}), do: 0 + 2
  defp score_round({"C", "Y"}), do: 3 + 3
  defp score_round({"C", "Z"}), do: 6 + 1
end

A little hard-coded-y; I could have separated the scoring between win or lose, and the two different ways to interpret the second letter in each instruction.

stevensonmt

stevensonmt

Nothing too clever in this solution, I’m afraid. About as naive as it gets.

  def part1(input) do
    File.stream!(input)
    |> Enum.reduce(0, fn line, score -> score + score_line(String.trim(line)) end)
  end

  defp score_line("A X"), do: 4
  defp score_line("A Y"), do: 8
  defp score_line("A Z"), do: 3
  defp score_line("B X"), do: 1
  defp score_line("B Y"), do: 5
  defp score_line("B Z"), do: 9
  defp score_line("C X"), do: 7
  defp score_line("C Y"), do: 2
  defp score_line("C Z"), do: 6

  def part2(input) do
    File.stream!(input)
    |> Enum.reduce(0, fn line, score -> score + score_line_pt2(String.trim(line)) end)
  end

  defp score_line_pt2("A X"), do: score_line("A Z")
  defp score_line_pt2("A Y"), do: score_line("A X")
  defp score_line_pt2("A Z"), do: score_line("A Y")
  defp score_line_pt2("B X"), do: score_line("B X")
  defp score_line_pt2("B Y"), do: score_line("B Y")
  defp score_line_pt2("B Z"), do: score_line("B Z")
  defp score_line_pt2("C X"), do: score_line("C Y")
  defp score_line_pt2("C Y"), do: score_line("C Z")
  defp score_line_pt2("C Z"), do: score_line("C X")
weeksseth

weeksseth

Similar to @stevensonmt.

defmodule Day02 do
  use AOC

  def part1 do
    input(2)
    ~> String.split("\n")
    ~> Enum.map(fn round ->
      case round ~> String.split(" ") do
        ["A", "X"] -> 4
        ["B", "X"] -> 1
        ["C", "X"] -> 7
        ["A", "Y"] -> 8
        ["B", "Y"] -> 5
        ["C", "Y"] -> 2
        ["A", "Z"] -> 3
        ["B", "Z"] -> 9
        ["C", "Z"] -> 6
      end
    end)
    ~> Enum.sum()
  end

  def part2 do
    input(2)
    ~> String.split("\n")
    ~> Enum.map(fn round ->
      case round ~> String.split(" ") do
        ["A", "X"] -> 3
        ["B", "X"] -> 1
        ["C", "X"] -> 2
        ["A", "Y"] -> 4
        ["B", "Y"] -> 5
        ["C", "Y"] -> 6
        ["A", "Z"] -> 8
        ["B", "Z"] -> 9
        ["C", "Z"] -> 7
      end
    end)
    ~> Enum.sum()
  end

end
weeksseth

weeksseth

Not sure why I did that extra split just to pattern match on the array of both of them. Matching on the string makes way more sense.

christhekeele

christhekeele OP

I do like my pattern of parsing input separately from solving each part; keeps the actual interpretation of inputs up to the part of the problem in question (useful here, as we were asked to re-interpret our input).

mudasobwa

mudasobwa

Creator of Cure

I am trying to fit tweet size so far :slight_smile:

score = fn 
  "A X" -> {4, 3}
  "A Y" -> {8, 4}
  "A Z" -> {3, 8}
  "B X" -> {1, 1}
  "B Y" -> {5, 5}
  "B Z" -> {9, 9}
  "C X" -> {7, 2}
  "C Y" -> {2, 6}
  "C Z" -> {6, 7}
end

input
|> String.split("\n")
|> Enum.map(score)
|> Enum.reduce({0, 0}, fn 
  {r1, r2}, {acc1, acc2} -> {acc1 + r1, acc2 + r2}
end)
code-shoily

code-shoily

I was annoyed a little while making this, don’t know why, maybe for all those reading.

Here it is: advent_of_code/lib/2022/day_02.ex at main · code-shoily/advent_of_code · GitHub

Interesting to see so many of our solutions look similar.

kwando

kwando

I ended up writing a bit more code :slight_smile: I realized pretty quickly I could just precompute the score for every combination like most of you did, but what’s the fun in that? :laughing:

I’m using Livebook this year, so thats why the code ends up in fn -> end instead of wrapped in a module :slight_smile:

input =
  File.stream!("/Users/kwando/projects/AoC2022/02/input.txt")
  |> Stream.map(fn line ->
    line
    |> String.trim()
    |> String.split(" ", parts: 2)
    |> List.to_tuple()
  end)

mapping = %{
  "A" => :rock,
  "B" => :paper,
  "C" => :scissors
}

shape_score = fn
  :rock -> 1
  :paper -> 2
  :scissors -> 3
end

game_score = fn
  any, any -> 3
  :rock, :paper -> 6
  :paper, :scissors -> 6
  :scissors, :rock -> 6
  _, _ -> 0
end

tally_games = fn games, your_pick ->
  for {elf, you} <- games, reduce: 0 do
    score ->
      elf = mapping[elf]
      you = your_pick.(elf, you)
      score + game_score.(elf, you) + shape_score.(you)
  end
end

your_pick = fn
  _, "X" -> :rock
  _, "Y" -> :paper
  _, "Z" -> :scissors
end

# part 1
tally_games.(input, your_pick)

# X = lose
# Y = draw
# Z = win
pick_shape = fn
  # losing
  :rock, "X" -> :scissors
  :paper, "X" -> :rock
  :scissors, "X" -> :paper
  # draw
  any, "Y" -> any
  # winning
  :rock, "Z" -> :paper
  :paper, "Z" -> :scissors
  :scissors, "Z" -> :rock
end

# part 2
tally_games.(input, pick_shape)
marcelfahle

marcelfahle

And here’s mine, nothing too fancy and I even though I find multiple functions usually pretty readable, the second part of the puzzle made my head spin a little and is not readable at all :grin:

  @input "./lib/day2_input.txt"

  @x 1
  @y 2
  @z 3

  @win 6
  @loss 0
  @draw 3

  def puzzle1() do
      process(&score/1)
  end

  def puzzle2() do
      process(&cheat/1)
  end

  defp process(fun) do
    @input
    |> File.read!()
    |> String.split(~r/\R/, trim: true)
    |> Enum.map(fn row ->
      row
      |> String.split()
      |> (&(fun.(&1))).()
      end)
    |> Enum.sum()
  end

  defp score(["A", "X"]), do: @x + @draw
  defp score(["A", "Y"]), do: @y + @win
  defp score(["A", "Z"]), do: @z + @loss

  defp score(["B", "X"]), do: @x + @loss
  defp score(["B", "Y"]), do: @y + @draw
  defp score(["B", "Z"]), do: @z + @win

  defp score(["C", "X"]), do: @x + @win
  defp score(["C", "Y"]), do: @y + @loss
  defp score(["C", "Z"]), do: @z + @draw

  defp cheat(["A", "X"]), do: score(["A", "Z"])
  defp cheat(["A", "Y"]), do: score(["A", "X"])
  defp cheat(["A", "Z"]), do: score(["A", "Y"])

  defp cheat(["B", arg]), do: score(["B", arg])

  defp cheat(["C", "X"]), do: score(["C", "Y"])
  defp cheat(["C", "Y"]), do: score(["C", "Z"])
  defp cheat(["C", "Z"]), do: score(["C", "X"])
LostKobrakai

LostKobrakai

I did write a bit more code, but I used metaprogramming to generate all the score cases instead of hardcoding them. Would’ve been more useful it this hadn’t been just a 3x3 grid of possible inputs per line.

Solution
defmodule Day2 do
  def find_score(text) do
    text
    |> String.split("\n")
    |> Enum.reject(&(&1 == ""))
    |> Enum.map(&score/1)
    |> Enum.sum()
  end

  def find_score_alternate(text) do
    text
    |> String.split("\n")
    |> Enum.reject(&(&1 == ""))
    |> Enum.map(&score_alternate/1)
    |> Enum.sum()
  end

  @score_per_type %{rock: 1, paper: 2, scissors: 3}
  @score_per_result %{loss: 0, draw: 3, win: 6}

  scores_per_round =
    for opponent <- Map.keys(@score_per_type),
        myself <- Map.keys(@score_per_type),
        into: %{} do
      result =
        case {opponent, myself} do
          {x, x} -> :draw
          {:scissors, :rock} -> :win
          {:paper, :scissors} -> :win
          {:rock, :paper} -> :win
          _ -> :loss
        end

      opponent_key =
        case opponent do
          :rock -> "A"
          :paper -> "B"
          :scissors -> "C"
        end

      myself_key =
        case myself do
          :rock -> "X"
          :paper -> "Y"
          :scissors -> "Z"
        end

      {"#{opponent_key} #{myself_key}",
       Map.fetch!(@score_per_result, result) + Map.fetch!(@score_per_type, myself)}
    end

  for {round, score} <- scores_per_round do
    defp score(unquote(round)), do: unquote(score)
  end

  scores_per_round_alternate =
    for opponent <- Map.keys(@score_per_type),
        result <- Map.keys(@score_per_result),
        into: %{} do
      myself =
        case {opponent, result} do
          {x, :draw} -> x
          {:scissors, :win} -> :rock
          {:paper, :win} -> :scissors
          {:rock, :win} -> :paper
          {:scissors, :loss} -> :paper
          {:paper, :loss} -> :rock
          {:rock, :loss} -> :scissors
        end

      opponent_key =
        case opponent do
          :rock -> "A"
          :paper -> "B"
          :scissors -> "C"
        end

      result_key =
        case result do
          :loss -> "X"
          :draw -> "Y"
          :win -> "Z"
        end

      {"#{opponent_key} #{result_key}",
       Map.fetch!(@score_per_result, result) + Map.fetch!(@score_per_type, myself)}
    end

  for {round, score} <- scores_per_round_alternate do
    defp score_alternate(unquote(round)), do: unquote(score)
  end

  @doc false
  def debug, do: unquote(Macro.escape(scores_per_round))

  @doc false
  def debug_alternate, do: unquote(Macro.escape(scores_per_round_alternate))
end

Where Next? Top

Trending in Challenges Top

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews