bjorng
Erlang Core Team
Advent of Code 2024 - Day 2
Here is my solution for day 2 of Advent of Code:
https://github.com/bjorng/advent-of-code/blob/main/2024/day02/lib/day02.ex
Most Liked
sevenseacat
Author of Ash Framework
dimitarvp
Life sadly kept getting in the way but ultimately:
defmodule Day02 do
@moduledoc ~S"""
A solution to https://adventofcode.com/2024/day/2.
"""
@type level :: pos_integer()
@type distance :: integer()
@type report :: [level()]
@spec all_variants_with_one_element_removed(report()) :: [report()]
def all_variants_with_one_element_removed(list) do
for i <- 0..(length(list) - 1), do: list |> List.delete_at(i)
end
@spec sign(integer()) :: :zero | :minus | :plus
def sign(0), do: :zero
def sign(i) when i > 0, do: :plus
def sign(i) when i < 0, do: :minus
@spec distances(report()) :: [distance()]
def distances([first | rest]) do
rest
|> Enum.reduce({first, []}, fn current_level, {previous_level, distances} ->
{current_level, [current_level - previous_level | distances]}
end)
|> then(fn {_last_level, distances} -> Enum.reverse(distances) end)
end
@spec same_signs?([distance()]) :: boolean()
def same_signs?(list) do
list
|> Enum.map(&sign/1)
|> Enum.uniq()
|> length()
|> Kernel.==(1)
end
@spec safe?(report()) :: boolean()
def safe?(report) do
distances = distances(report)
monotonical? = same_signs?(distances)
safely_advancing? =
distances |> Enum.map(&abs/1) |> Enum.all?(fn distance -> distance <= 3 end)
monotonical? and safely_advancing?
end
@spec safe_with_a_dampener?(report()) :: boolean()
def safe_with_a_dampener?(report) do
safe?(report) or
report |> all_variants_with_one_element_removed() |> Enum.any?(&safe?/1)
end
@doc ~S"""
iex> Day02.part_1("7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9\n")
nil
"""
@spec part_1(String.t()) :: non_neg_integer()
def part_1(input \\ Aoc.input(2)) do
input
|> Aoc.parse_lines_of_integers()
|> Enum.count(&safe?/1)
end
@spec part_2(String.t()) :: non_neg_integer()
def part_2(input \\ Aoc.input(2)) do
input
|> Aoc.parse_lines_of_integers()
|> Enum.count(&safe_with_a_dampener?/1)
end
end
Did my best to make it readable and intuitive, even benchmarked three competing implementation I had ideas about, and only posted the one that won.
3
lud
No optimization here, just building all possible list before trying them one by one ![]()
defmodule AdventOfCode.Solutions.Y24.Day02 do
alias AoC.Input
def parse(input, _part) do
Enum.map(Input.stream!(input, trim: true), &parse_line/1)
end
defp parse_line(line) do
Enum.map(String.split(line, " "), &String.to_integer/1)
end
def part_one(problem) do
problem
|> Enum.filter(&safe?/1)
|> length()
end
defp safe?([a, b | _] = list) when a < b, do: safe?(:asc, list)
defp safe?([a, b | _] = list) when a > b, do: safe?(:desc, list)
defp safe?([a, a | _]), do: false
defp safe?(:asc, [a, b | rest]) when abs(a - b) in 1..3 and a < b, do: safe?(:asc, [b | rest])
defp safe?(:desc, [a, b | rest]) when abs(a - b) in 1..3 and a > b, do: safe?(:desc, [b | rest])
defp safe?(_, [_last]), do: true
defp safe?(_, _), do: false
def part_two(problem) do
problem
|> Enum.filter(&safeish?/1)
|> length()
end
defp safeish?(list) do
candidates = [list | Enum.map(0..(length(list) - 1), &List.delete_at(list, &1))]
Enum.any?(candidates, &safe?/1)
end
end
Edit:
candidates = Stream.concat([list], Stream.map(0..(length(list) - 1), &List.delete_at(list, &1)))
This would save memory but given the input size it’s actually slower.
2
Popular in Challenges
So… that’s it? Everyone is stuck on part 2? :slight_smile: I looked at Reddit hints and thought I probably wouldn’t have come up with the...
New
This topic is about Day 10 of the Advent of Code 2021.
We have a private leaderboard (shared with users of Erlang Forums ):
https://adv...
New
Here is my solution:
https://github.com/bjorng/advent-of-code-2021/blob/77bdef7a51b428b58ffb4ab76f540901e636f841/day12/lib/day12.ex
New
All in all, from what I understand, it is better not to use GenServer.cast when we want some concurrent operations to happen for sure, be...
New
A frustrating one for me. I spent a long time trying to understand why some combinations resulted in fewer presses and struggled to keep ...
New
This is my second year doing AoC in Elixir and my first year doing it with Livebook.
When I was doing just plain Elixir I usually set up...
New
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
Anyone else think the prompt for this challenge is contradictory?
The rules for comparing packets include
If both values are lists, c...
New
Anyone have a solution to Part 2 today? Part 1 was straight forward, but I can’t figure out a programatic way to do part 2. I understand ...
New
Thought I’d kick today’s thread off!
Parsing
Enum rocks, so most of my code was actually in parsing input.
▶ Preprocessing input
Part 1...
New
Other popular topics
Hello!
tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability.
After spen...
New
What is the idiomatic way of matching for not nil in Elixir?
E.g.,
First way:
defp halt_if_not_signed_in(conn, signed_in_account) when...
New
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
In templates/appointment/index.html.eex:
<%= for appointment <- @appointments do %>
<tr>
<td><%= appoi...
New
lets say i have a sample like
a = 20; b = 10;
if (a > b) do
{:ok, "a"}
end
if (a < b) do
{:ok, b}
end
if (a == b) do
{:ok, "equa...
New
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this:
...
New
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum.
...
New
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine)
This is a plugin that adds support for Elixir to JetBrains IntelliJ...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
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
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








