lud
Advent of Code 2025 - Day 1
Hello everyone!
This year is going to be shorter, but the difficulty will grow faster. Today I already feel that this is not standard “Day 1” difficulty.
Or I am really overcomplicating things. Didn’t sleep well ![]()
defmodule AdventOfCode.Solutions.Y25.Day01 do
alias AoC.Input
def parse(input, :part_one) do
input
|> Input.stream!(trim: true)
|> Enum.map(fn
"R" <> n -> {:right, String.to_integer(n)}
"L" <> n -> {:left, String.to_integer(n)}
end)
end
def parse(input, :part_two) do
input
|> Input.stream!(trim: true)
|> Enum.flat_map(fn
"R" <> n -> expand_rotation(:right, String.to_integer(n))
"L" <> n -> expand_rotation(:left, String.to_integer(n))
end)
end
defp expand_rotation(direction, amount) when amount <= 100 do
[{direction, amount}]
end
defp expand_rotation(direction, amount) when amount > 100 do
[{direction, 100} | expand_rotation(direction, amount - 100)]
end
def part_one(problem) do
problem
|> Stream.scan(50, fn
{:left, n}, acc -> Integer.mod(acc - n, 100)
{:right, n}, acc -> Integer.mod(acc + n, 100)
end)
|> Enum.count(&(&1 == 0))
end
def part_two(problem) do
problem
|> Stream.transform(50, fn
{:left, n}, acc ->
new_acc = Integer.mod(acc - n, 100)
{[{:left, acc, new_acc}], new_acc}
{:right, n}, acc ->
new_acc = Integer.mod(acc + n, 100)
{[{:right, acc, new_acc}], new_acc}
end)
|> Enum.count(fn
{_, _, 0} -> true
{_, 0, _} -> false
{:right, a, b} when a > b -> true
{:left, a, b} when a < b -> true
{_, same, same} -> true
_ -> false
end)
end
end
Most Liked
billylanchantin
Boilerplate
def file_to_lines(file), do: file |> File.read!() |> String.trim() |> String.split("\n")
def file_to_lines(file, fun), do: file |> file_to_lines() |> Enum.map(fun)
Part 1
def part1(file), do: file |> file_to_lines(&parse/1) |> count0()
def parse(l), do: l |> String.replace("R", "") |> String.replace("L", "-") |> Integer.parse() |> elem(0)
def count0(i), do: i |> Enum.scan(50, &Integer.mod(&1 + &2, 100)) |> Enum.count(&(&1 == 0))
Enum.scan/3 works really well here.
Part 2
def part2(file), do: file |> file_to_lines(&parse/1) |> Stream.flat_map(&flatten/1) |> count0()
def flatten(x), do: if(x < 0, do: List.duplicate(-1, abs(x)), else: List.duplicate(1, x))
It’s tempting to do math, but reusing prior work is simpler if less performant.
tnlogy
Hi! Nice to see some solutions to compare with since this is my first time using Elixir. I like it so far :).
This is my solution for day1, I tried to simplify part 2 by replacing the instructions with just +1 and -1. Maybe some of my code is a bit strange since I’m new to Elixir.
defmodule Advent2025Test do
use ExUnit.Case
doctest Advent2025
def day1_data() do
"day1.txt"
|> File.stream!()
|> Stream.map(fn line -> String.split_at(line, 1) end)
|> Stream.map(fn {dir, num} -> {dir, String.to_integer(String.trim(num))} end)
end
def day1_count(data) do
data
|> Enum.reduce({50, 0}, fn {dir, num}, {val, res} ->
Integer.mod(
val +
case dir do
"L" -> -num
"R" -> num
end,
100
)
|> then(fn new_val ->
{new_val, if(new_val == 0, do: res + 1, else: res)}
end)
end)
end
def day1_make_ticks(data) do
data
|> Stream.flat_map(fn {dir, num} ->
Stream.map(1..num, fn _ -> {dir, 1} end)
end)
end
test "day1_p1" do
{_, zeroes} = day1_data() |> day1_count()
IO.puts("answer #{zeroes}")
assert zeroes == 1048
end
test "day1_p2" do
# Same as part1, but make a list of just {"L", 1} and {"R", 1}
{_, zeroes} = day1_data() |> day1_make_ticks() |> day1_count()
IO.puts("answer: #{zeroes}")
assert zeroes == 6498
end
end
lkuty
I wanted to play a little bit with nimble_parsec. I will try to use it for every parsing job. Usually I use regexes but 1) time to change, 2) and get a more powerful parsing technique.
#!/usr/bin/env elixir
# Advent of Code 2025. Day 1
Mix.install([
{:nimble_parsec, "~> 1.4.2"},
])
defmodule M do
import NimbleParsec
rotation =
choice([string("L"), string("R")])
|> integer(min: 1)
defparsec :rotation, rotation
end
# Part 1
File.stream!("../day01.txt")
|> Stream.map(fn line -> {:ok, [dir, qty], "\n", %{}, _, _} = M.rotation(line) ; {dir, qty} end)
|> Enum.reduce({50, 0}, fn {dir, qty}, {pos, zeroes} ->
pos = Integer.mod(pos + (if dir == "R", do: 1, else: -1) * qty, 100)
{pos, (if pos == 0, do: zeroes+1, else: zeroes)}
end)
|> tap(fn {_pos, zeroes} -> IO.puts("Day 1. Part 1. Number of zeroes: #{zeroes}") end)
# Part 2
File.stream!("../day01.txt")
|> Stream.map(fn line -> {:ok, [dir, qty], "\n", %{}, _, _} = M.rotation(line) ; {dir, qty} end)
|> Enum.reduce({50, 0}, fn {dir, qty}, {pos, zeroes} ->
dist_to_zero = if dir == "L", do: pos, else: Integer.mod(100-pos, 100)
pos = Integer.mod(pos + (if dir == "R", do: 1, else: -1) * qty, 100)
n = div(max(0, qty-dist_to_zero), 100) + (if pos != 0 && qty-dist_to_zero >= 0, do: 1, else: 0)
{pos, zeroes + n}
end)
|> tap(fn {_pos, zeroes} -> IO.puts("Day 1. Part 2. Number of zeroes: #{zeroes}") end)
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









