bjorng
Erlang Core Team
Most Liked
sevenseacat
Author of Ash Framework
3
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
Aetherus
I was trying hard to find a smart-ass solution for part 2 without using List.delete_at/2, but in the end, I had to admit that I’m not that smart after all.
Part 1
puzzle_input
|> String.split("\n")
|> Enum.map(&String.split/1)
|> Enum.map(&Enum.map(&1, fn s -> String.to_integer(s) end))
|> Enum.count(fn
[a, a | _] ->
false
[a, b | _] = line ->
sign = div(a - b, abs(a - b))
line
|> Enum.chunk_every(2, 1, :discard)
|> Enum.all?(fn [a, b] ->
sign * (a - b) in 1..3
end)
end)
Part 2
puzzle_input
|> String.split("\n")
|> Enum.map(&String.split/1)
|> Enum.map(&Enum.map(&1, fn s -> String.to_integer(s) end))
|> Enum.count(fn line ->
0..length(line)
|> Stream.map(&List.delete_at(line, &1))
|> Enum.any?(fn
[a, a | _] ->
false
[a, b | _] = line ->
sign = div(a - b, abs(a - b))
line
|> Enum.chunk_every(2, 1, :discard)
|> Enum.all?(fn [a, b] ->
sign * (a - b) in 1..3
end)
end)
end)
2
lkuty
#!/usr/bin/env elixir
# 2024. day 2.
defmodule A do
@spec is_ok?([integer()]) :: boolean()
def is_ok?(lst), do: is_ok?(lst, nil, nil)
@spec is_ok?([integer()], nil | integer(), nil | :inc | :dec) :: boolean()
defp is_ok?(lst, prev, dir)
defp is_ok?([], _, _), do: true # empty list
defp is_ok?([_fst], nil, _), do: true # single element list
defp is_ok?([fst | rest], nil, nil), do: is_ok?(rest, fst, nil) # more than one element
# same number!
defp is_ok?([fst | _rest], fst, _dir), do: false
# direction is unknown
defp is_ok?([fst | rest], prev, nil) when fst < prev, do: (if prev-fst<=3, do: is_ok?(rest, fst, :dec), else: false)
defp is_ok?([fst | rest], prev, nil) when fst > prev, do: (if fst-prev<=3, do: is_ok?(rest, fst, :inc), else: false)
# direction is decreasing
defp is_ok?([fst | rest], prev, :dec) when fst < prev, # we keep on decreasing
do: (if prev-fst<=3, do: is_ok?(rest, fst, :dec), else: false)
defp is_ok?([fst | _rest], prev, :dec) when fst > prev, do: false # we start to increase
# direction is increasing
defp is_ok?([fst | rest], prev, :inc) when fst > prev,
do: (if fst-prev<=3, do: is_ok?(rest, fst, :inc), else: false) # we keep on increasing
defp is_ok?([fst | _rest], prev, :inc) when fst < prev, do: false # we start to decrease
# get all the sublists of lst with one element less than lst
# A.sublists([1,2,3,4]) => [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
def sublists(lst), do: sublists([], lst, [])
def sublists(_pre, [], acc), do: acc
def sublists(pre, [a | rest], acc), do: sublists([a | pre], rest, [(Enum.reverse(pre) ++ rest) | acc])
end
File.stream!("day02.txt")
|> Stream.map(fn line -> String.split(line) |> Enum.map(&String.to_integer/1) |> A.is_ok?() end)
|> Enum.count(&Function.identity/1)
|> IO.inspect(label: "part 1")
File.stream!("day02.txt")
|> Stream.map(fn line ->
lst = String.split(line) |> Enum.map(&String.to_integer/1)
Enum.any?([lst | A.sublists(lst)], fn lst -> A.is_ok?(lst) end)
end)
|> Enum.count(&Function.identity/1)
|> IO.inspect(label: "part 2")
2
Popular in Challenges
I have 2 arrays: a1 can be any combination of value or nil like that
a1 = [1,nil,3]
and array 2 the same
a2 = [4,2, nil]
How do I com...
New
Today’s challenge is quite interesting. I ended up using Zipper to solve this problem. Maybe I overengineered quite a bit.
The data stru...
New
Took me a minute to remember my binary math :smile: :grimacing:…
import Bitwise
__DIR__
|> Path.join("puzzle.txt")
|> File.stream...
New
Note by the Moderators: This topic is to talk about the first day of the Advent of Code.
For general discussion about the Advent of Code...
New
At first I was scared but I found is a simple way to compute the sides.
defmodule AdventOfCode.Solutions.Y24.Day12 do
alias AdventOfCo...
New
Note: This topic is to talk about Day 3 of the Advent of Code 2019 .
There is a private leaderboard for elixirforum members. You can jo...
New
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
Hello, guys. I’m back again, but only for the weekends, maybe.
This topic is about Day 13 of the Advent of Code 2020 .
Thanks to @egze,...
New
Took a while, but another use case for “move vectors” today and pattern matching. :slight_smile:
The trick was to first generate a list...
New
I spent 3 hours struggling in part 2, until I noticed a very basic mistake :joy:
Here’s my code:
By the way, the starting position in...
New
Other popular topics
Hello all!
I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
Hi folks,
Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
New
I am trying to run a deploy with docker and I successfully runned with this command:
docker build -t romenigld/blog-prod .
but when I t...
New
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode.
The solution seems to be, in a hyphena...
New
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
As a follow up to my earlier question:
I have the code compiling and running but not getting a successful login from the rest server. ...
New
Hi all,
I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage.
I'm trying to use Postg...
New
I will often find my self writing things similar to:
case some_value do
nil -> something()
"" -> something()
_ -> someth...
New
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum.
...
New







