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)






















