christhekeele
Advent of Code 2023 - Day 2
Thought I’d kick today’s thread off!
Parsing
Enum rocks, so most of my code was actually in parsing input.
Preprocessing input
Data model is:
%{
id :: integer() => [
pull :: %{
red: integer(),
green: integer(),
blue: integer()
}
]
}
I modeled each pull as a struct rather than a bare map, just so I didn’t have to write any extra code to hydrate my maps with default 0 values where input was empty for a color.
Source available here.
defmodule AoC.Day.Two.Input do
defmodule Pull do
defstruct red: 0, green: 0, blue: 0
end
def parse(input_file \\ System.fetch_env!("INPUT_FILE")) do
input_file
|> File.read!()
|> String.split("\n")
|> Enum.reject(&(&1 == ""))
|> Enum.map(&parse_game/1)
|> Map.new()
end
def parse_game("Game " <> game) do
{id, rest} = Integer.parse(game)
<<": ">> <> pulls = rest
pulls =
pulls
|> String.trim()
|> String.split(";")
|> Enum.map(&String.trim/1)
|> Enum.map(&parse_pull/1)
{id, pulls}
end
def parse_pull(pull) do
result =
pull
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.map(&parse_pull_color/1)
struct!(Pull, result)
end
def parse_pull_color(result) do
case Integer.parse(result) do
{num, " red"} -> {:red, num}
{num, " green"} -> {:green, num}
{num, " blue"} -> {:blue, num}
end
end
end
Part 1
Solution
input |> Enum.filter(Enum.all?) |> Enum.map |> Enum.sum. Source available here.
defmodule AoC.Day.Two.Part.One do
@red_limit 12
@green_limit 13
@blue_limit 14
def solve(input) do
input
|> Enum.filter(fn {_id, pulls} ->
Enum.all?(pulls, fn
%{red: red, green: green, blue: blue}
when red <= @red_limit and green <= @green_limit and blue <= @blue_limit ->
true
_ ->
false
end)
end)
|> Enum.map(fn {id, _} -> id end)
|> Enum.sum()
end
end
Part 2
Solution
Simpler still. Could have avoided iterating over pulls 3 times, but not too fussed about it. Source available here.
defmodule AoC.Day.Two.Part.Two do
def solve(input) do
input
|> Enum.map(fn {id, pulls} ->
min_red = pulls |> Enum.map(&Map.fetch!(&1, :red)) |> Enum.max()
min_green = pulls |> Enum.map(&Map.fetch!(&1, :green)) |> Enum.max()
min_blue = pulls |> Enum.map(&Map.fetch!(&1, :blue)) |> Enum.max()
{id, min_red * min_green * min_blue}
end)
|> Enum.map(fn {_id, power} -> power end)
|> Enum.sum()
end
end
Trending in Challenges
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance










First 10 of 30 Posts
adamu
After seeing part 2, we know that both parts only need the aggregate of all the rounds, so for each game I used a single map representing the maximum number of cubes seen.
https://git.adamu.jp/adam/AdventOfCode/src/branch/main/2023/day2.exs
christhekeele
That
Map.merge/3is a very elegant way to get all maxes in one iteration, I wouldn’t’ve thought of it!Aetherus
I was thinking maybe this puzzle could be solved using nimble_parsec, but when I tried, I just got lost because I couldn’t understand the documentation and the examples
Maybe I should just go for yecc.
christhekeele
I struggle with the docs for both every time I have to pick them up
. Would love to see that incarnation if you get around to it!
Aetherus
I have to attend my sister’s wedding ceremony now. Maybe later.
seeplusplus
I was able to knock this one out much quicker than yesterday’s
Edit: really impressed with the brevity from some of the solutions I’ve seen for the last two days. Great stuff all.
midouest
Did a little more work than I needed to in part 1, but it made the modifications for part 2 pretty easy! This was a nice day 2 problem
Part 1
Part 2
mexicat
Quite straightforward with
Regex.scanandEnum.group_by:https://github.com/mexicat/aoc-2023/blob/main/lib/aoc/day_02.ex
kip
I also elected in part 1 to build a map that kept the maxima for each color for each game. Which meant that part 2 was really trivial. This kind of “one off” multi-level parsing is a bit tricky to produce easily readable code and @christhekeele definitely did better than I did.
Pre-processing
Part 1
With the maxima already stored it was straight forward to calculate the games. I tend to reach for
Enum/reduce/3in these cases more than most (it seems).Part 2
This is trivial since the data is already in the right format. Again I find `Enum.reduce` super handy because it already accumulates.herisson
Very elegant, I miss a lot of training with pattern matching.
I did not know one could pattern match on the string directly. That must me a good advantage comparing to other programming langages