christhekeele

christhekeele

Advent of Code 2022 - Day 2

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

Day 2!

Leaderboard:

Most Liked

kwando

kwando

One of my colleagues came up with something completely different which I thought was interesting:

(This is translated from python to elixir)

 File.stream!("/Users/kwando/projects/AoC2022/02/input.txt")
 |> Stream.map(fn line -> String.trim(line) |> String.to_charlist() end)
 |> Enum.reduce(0, fn [elf, _, you], score ->
  shape_score = you - ?X + 1

  case {elf - ?A, you - ?X} do
    {any, any} ->
      score + 3 + shape_score
    {elf, you} when rem(you + 2, 3) == elf ->
      score + 6 + shape_score
    {_, _} ->
      score + shape_score
  end
end)
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
adamu

adamu

I went for “be very explicit” on this one :smile:

  defp play({:rock, :rock}), do: @rock + @draw
  defp play({:paper, :rock}), do: @rock + @lose
  defp play({:scissors, :rock}), do: @rock + @win
  defp play({:rock, :paper}), do: @paper + @win
  defp play({:paper, :paper}), do: @paper + @draw
  defp play({:scissors, :paper}), do: @paper + @lose
  defp play({:rock, :scissors}), do: @scissors + @lose
  defp play({:paper, :scissors}), do: @scissors + @win
  defp play({:scissors, :scissors}), do: @scissors + @draw
christhekeele

christhekeele

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)

Where Next?

Popular in Challenges Top

Aetherus
This topic is about Day 3 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
bjorng
This topic is about Day 16 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adve...
New
sasajuric
Note by the Moderators: This topic is to talk about Day 5 of the Advent of Code. For general discussion about the Advent of Code 2018 an...
New
Aetherus
The second part of today’s puzzle is very misleading. FYI, each of the ghosts has only one possible position that ends with a "Z" on its...
New
stevensonmt
Anyone else think the prompt for this challenge is contradictory? The rules for comparing packets include If both values are lists, c...
New
bjorng
This topic is about Day 2 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adven...
New
cblavier
Hey there :wave: No magic or algorithmic finesse today, I just finished the challenge and I my code is quite slow (1sec for part1, 3se...
New
New
bjorng
Note: This topic is to talk about Day 6 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New
seeplusplus
Hello all, hopefully I post this before someone else does and I don’t dupe. IMO Day 4 was much easier than Day 3 (yay, I can sleep befor...
New

Other popular topics Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement