bjorng
Advent of Code 2024 - Day 1
Here is my solution for day 1 of Advent of Code:
defmodule Day01 do
def part1(input) do
all = parse(input)
{first, second} = Enum.unzip(all)
Enum.zip([Enum.sort(first), Enum.sort(second)])
|> Enum.map(fn {a, b} ->
abs(a - b)
end)
|> Enum.sum
end
def part2(input) do
all = parse(input)
{first, second} = Enum.unzip(all)
frequencies = Enum.frequencies(second)
first
|> Enum.map(fn n ->
n * Map.get(frequencies, n, 0)
end)
|> Enum.sum
end
defp parse(input) do
input
|> Enum.map(fn line ->
{first, line} = Integer.parse(line)
line = String.trim(line)
{second, ""} = Integer.parse(line)
{first, second}
end)
end
end
Most Liked
al2o3cr
I liked this solution for part 1 because of the unzip / process / zip pattern:
File.stream!("example.txt")
|> Stream.map(&String.trim/1)
|> Stream.map(&String.split/1)
|> Stream.map(fn [a, b] -> {String.to_integer(a), String.to_integer(b)} end)
|> Enum.unzip()
|> then(fn {l, r} -> [Enum.sort(l), Enum.sort(r)] end)
|> Stream.zip()
|> Stream.map(fn {a, b} -> abs(b-a) end)
|> Enum.sum()
|> IO.inspect()
Part 2 wasn’t quite as symmetrical:
{left, right} =
File.stream!("input.txt")
|> Stream.map(&String.trim/1)
|> Stream.map(&String.split/1)
|> Stream.map(fn [a, b] -> {String.to_integer(a), String.to_integer(b)} end)
|> Enum.unzip()
f_right = Enum.frequencies(right)
left
|> Stream.map(fn l -> {l, Map.get(f_right, l, 0)} end)
|> Stream.map(fn {l, n} -> l * n end)
|> Enum.sum()
|> IO.inspect()
Technically it would be faster to fuse successive Stream.maps into a single one with a more-complicated function, but writing in this style keeps each line focused on a specific transformation.
clayscode
Signed up just to say thank you for this comment! Didn’t know about the then function. Subsequently have learned about the tap function as well thanks to this article: Useful Elixir Functions You May Not Know: tap() & then()
I guess it’s not that different from |> fn x -> x end.(), but it at least feels a bit nicer.
dimitarvp
I got so severely humbled by @billylanchantin that I just copied his code with very slight changes like adding types and specs and doctests, and extracting functions for better understanding of what does what, plus have common AOC helpers in a separate module.
In my defense for stealing his code, I did stare at the code for 40 minutes and played with it in iex until I understood exactly how it’s working. And then I was finally like “gods, I would absolutely do it this way if I knew about this Elixir API!”.
But yeah, I had no idea about Enum.zip_with and Enum.zip_reduce. Lesson learned – check Elixir’s CHANGELOGs!
Here’s my final Day 1 version:
https://github.com/dimitarvp/advent-of-code-2024-elixir/blob/main/lib/day01.ex
Popular in Challenges
Other popular topics
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
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








