defmodule Day06 do
def part1(input) do
input
|> Enum.map(fn line ->
line
|> String.split(" ", trim: true)
|> Enum.map(fn token ->
case Integer.parse(token) do
:error -> String.to_atom(token)
{n, ""} -> n
end
end)
end)
|> transpose
|> Enum.map(fn column ->
operator = List.last(column)
Enum.drop(column, -1)
|> Enum.reduce(&(eval(operator, &1, &2)))
end)
|> Enum.sum
end
def part2(input) do
operators = List.last(input)
spaces = count_spaces(String.to_charlist(operators))
operators = operators
|> String.to_charlist
|> Enum.filter(&(&1 !== ?\s))
|> Enum.map(&List.to_atom([&1]))
input
|> Enum.drop(-1)
|> Enum.map(fn line ->
String.to_charlist(line)
|> split_line(spaces)
end)
|> transpose
|> Enum.zip(operators)
|> Enum.map(fn {column, operator} ->
column
|> transpose
|> Enum.map(fn column ->
column
|> Enum.filter(&(&1 !== ?\s))
|> List.to_integer
end)
|> Enum.reduce(&(eval(operator, &1, &2)))
end)
|> Enum.sum
end
defp split_line([], []), do: []
defp split_line(line, [n]) do
{number, []} = Enum.split(line, n + 1)
[number]
end
defp split_line(line, [n | ns]) do
{number, rest} = Enum.split(line, n)
[?\s | rest] = rest
[number | split_line(rest, ns)]
end
defp count_spaces([]), do: []
defp count_spaces([_op|rest]) do
{spaces, rest} = Enum.split_while(rest, &(&1 === ?\s))
[length(spaces) | count_spaces(rest)]
end
defp eval(operator, number1, number2) do
apply(Kernel, operator, [number1, number2])
end
defp transpose(list) do
Enum.zip_with(list, &Function.identity/1)
end
end
Yet another easy puzzle.
Part 1
puzzle_input
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, " ", trim: true))
|> Enum.map(fn row ->
Enum.map(row, fn
"+" -> &+/2
"*" -> &*/2
s -> String.to_integer(s)
end)
end)
|> Enum.zip_with(&Function.identity/1)
|> Enum.map(&Enum.reverse/1)
|> Enum.sum_by(fn [operator | numbers] ->
Enum.reduce(numbers, operator)
end)
Part 2
Split the puzzle input into [[char()]], then rotate left (= transpose then reverse).
puzzle_input
|> String.split("\n", trim: true)
|> Enum.map(&:binary.bin_to_list/1)
|> Enum.zip_with(&Function.identity/1)
|> Enum.reverse()
|> Enum.map(&to_string/1)
|> Enum.map(&String.trim/1)
|> Enum.map(&Integer.parse/1)
|> Enum.flat_map(fn
:error ->
[]
{num, ""} ->
[num]
{num, op} ->
op
|> String.trim()
|> String.to_atom()
|> then(fn op -> &apply(Kernel, op, [&1, &2]) end)
|> then(&[num, &1])
end)
|> Enum.chunk_while([],
fn
num, acc when is_integer(num) -> {:cont, [num | acc]}
op, acc -> {:cont, Enum.reduce(acc, op), []}
end,
fn
[] -> {:cont, []}
end
)
|> Enum.sum()
Iām using my Array module again: Array.col returns a column as a list, Array.subarray returns a subarray with given indexes, and Array.from_list is a constructor that takes a list of lists.
defmodule Y2025.Day06 do
def parse_lines(s), do: s |> String.trim() |> String.split("\n") |> Enum.split(-1)
def split_by_spaces(s), do: String.trim(s) |> String.split(~r/\s+/)
def parse1(s) do
{nums, [ops]} = parse_lines(s)
nums =
nums
|> Enum.map(fn line ->
line |> split_by_spaces() |> Enum.map(&String.to_integer/1)
end)
|> Array.from_list()
ops = ops |> split_by_spaces()
{nums, ops}
end
def part1(s) do
{nums, ops} = parse1(s)
ops
|> Enum.with_index()
|> Enum.map(fn {op, i} -> apply_op(op, Array.col(nums, i)) end)
|> Enum.sum()
end
def apply_op("+", nums), do: Enum.sum(nums)
def apply_op("*", nums), do: Enum.product(nums)
def parse2(s) do
{nums, [ops]} = parse_lines(s)
nums =
nums
|> Enum.map(fn line -> String.graphemes(line) |> Enum.map(&maybe_to_digit/1) end)
|> Array.from_list()
ops = ops |> split_by_spaces()
{nums, ops}
end
def maybe_to_digit(" "), do: " "
def maybe_to_digit(d), do: String.to_integer(d)
def part2(s) do
{nums, ops} = parse2(s)
nums =
nums
|> array_split_by_spaces()
|> Enum.map(fn a -> cellophod_digits(a) end)
Enum.zip(ops, nums)
|> Enum.map(fn {op, num} -> if op == "*", do: Enum.product(num), else: Enum.sum(num) end)
|> Enum.sum()
end
@doc "Split array of digits and spaces into a list of arrays separated by columns of spaces"
def array_split_by_spaces(%Array{} = a) do
do_array_split_by_spaces(a, 0, 0, [])
end
def do_array_split_by_spaces(a, i, j, acc) do
cond do
i >= a.x_max ->
Enum.reverse(acc)
j == a.x_max || all_spaces?(Array.col(a, j)) ->
do_array_split_by_spaces(a, j + 1, j + 1, [Array.subarray(a, x: i..(j - 1)) | acc])
true ->
do_array_split_by_spaces(a, i, j + 1, acc)
end
end
def all_spaces?(list), do: Enum.all?(list, &(&1 == " "))
def cellophod_digits(%Array{} = a) do
0..(a.x_max - 1)
|> Enum.map(fn i -> Array.col(a, i) |> Enum.reject(&(&1 == " ")) end)
|> Enum.map(&Integer.undigits/1)
end
end
#!/usr/bin/env elixir
# Advent of Code 2025. Day 6
defmodule M do
def i("*"), do: "*"
def i("+"), do: "+"
def i(x), do: String.to_integer(x)
def n(a,b,c,d) do
[a,b,c,d]
|> Enum.reject(& &1 == " ")
|> Enum.map(&String.to_integer/1)
|> Integer.undigits()
end
end
# Part 1
# Original solution, before knowing part 2
rows = File.read!("../day06.txt") |> String.trim_trailing() |> String.split("\n")
map = rows |> Enum.reduce(%{}, fn row, map ->
row
|> String.trim_trailing()
|> String.split(~r/\s+/)
|> Enum.with_index()
|> Enum.reduce(map, fn {cell, col_idx}, map ->
Map.update(
map,
col_idx,
[M.i(cell)],
# We could as well do the operations directly here and only store the result in the map at the given col_idx
fn lst -> [(case cell do "*" -> &Enum.product/1 ; "+" -> &Enum.sum/1 ; _ -> M.i(cell) end) | lst] end
# variant 1
# fn lst -> [(case cell do "*" -> {1, fn a,b -> a*b end} ; "+" -> {0, fn a,b -> a+b end} ; _ -> M.i(cell) end) | lst] end
)
end)
end)
map
|> Enum.map(fn {_idx, [fun | numbers]} -> fun.(numbers) end)
# variant 1
# |> Enum.map(fn {_idx, [{id, fun} | numbers]} -> Enum.reduce(numbers, id, fun) end)
|> Enum.sum()
|> IO.inspect(label: "Day 6. Part 1")
# Part 2
File.read!("../day06.txt")
|> String.trim_trailing("\n")
|> String.split("\n")
|> Enum.map(&String.codepoints/1)
|> Enum.zip() # transpose the file
|> Enum.reduce({0, [], nil}, fn
{" ", " ", " ", " ", " "}, {total, numbers, "+"} -> {total+Enum.sum(numbers), [], nil}
{" ", " ", " ", " ", " "}, {total, numbers, "*"} -> {total+Enum.product(numbers), [], nil}
{a,b,c,d," "}, {total, numbers, op} -> {total, [M.n(a,b,c,d) | numbers], op}
{a,b,c,d,op}, {total, numbers, nil} -> {total, [M.n(a,b,c,d) | numbers], op}
end)
|> then(fn
{total,numbers,"+"} -> total+Enum.sum(numbers)
{total,numbers,"*"} -> total+Enum.product(numbers)
end)
|> IO.inspect(label: "Day 6. Part 2")
# Part 1 revisited
File.read!("../day06.txt")
|> String.trim_trailing("\n")
|> String.split("\n")
|> Enum.map(fn row -> row |> String.trim_trailing() |> String.split(~r/\s+/) |> Enum.map(&M.i/1) end)
|> Enum.zip() # transpose the file
|> Enum.reduce(0, fn
{a,b,c,d,"+"}, total -> total+a+b+c+d
{a,b,c,d,"*"}, total -> total+a*b*c*d
end)
|> IO.inspect(label: "Day 6. Part 1")
Setup
{tasks, [ops]} =
puzzle_input
|> String.split("\n", trim: true)
|> Enum.split(-1)
ops =
ops
|> String.split()
|> Enum.map(&String.to_atom/1)
Part 1
tasks
|> Enum.map(&String.split/1)
|> Enum.zip_with(fn numbers -> Enum.map(numbers, &String.to_integer/1) end)
|> Enum.zip(ops)
|> Enum.sum_by(fn
{nums, :+} -> Enum.sum(nums)
{nums, :*} -> Enum.product(nums)
end)
Part 2
tasks
|> Enum.map(&String.to_charlist/1)
|> Enum.zip_with(&(&1 |> List.to_string() |> String.trim()))
|> Enum.chunk_while(
[],
fn
"", acc -> {:cont, acc, []}
num, acc -> {:cont, [String.to_integer(num) | acc]}
end,
&{:cont, &1, []}
)
|> Enum.zip(ops)
|> Enum.sum_by(fn
{nums, :+} -> Enum.sum(nums)
{nums, :*} -> Enum.product(nums)
end)
Arf I wish I had thought to use String.to_integer before chunking!
defmodule AdventOfCode.Solutions.Y25.Day06 do
alias AoC.Input
# No separate parsing today :)
def parse(input, _), do: input
def part_one(input) do
input
|> Input.stream!(trim: true)
|> Stream.map(&String.split(&1, " ", trim: true))
|> Enum.zip_with(& &1)
|> Enum.sum_by(fn list ->
{op, args} = List.pop_at(list, -1)
apply_op(op, Enum.map(args, &String.to_integer/1))
end)
end
def part_two(input) do
rows = Input.read!(input) |> String.split("\n", trim: true)
{ops, rows} = List.pop_at(rows, -1)
rows = Enum.map(rows, &String.graphemes/1)
ops = String.split(ops, " ", trim: true)
rows
|> Stream.unfold(fn
[[] | _] ->
nil
rows ->
{rows, col} = Enum.map_reduce(rows, [], fn [h | t], acc -> {t, [h | acc]} end)
{:lists.reverse(col), rows}
end)
|> Stream.map(fn str_digits ->
case str_digits |> Enum.join("") |> String.trim() do
"" -> nil
str_num -> String.to_integer(str_num)
end
end)
|> Stream.chunk_by(&is_integer/1)
|> Stream.filter(&(&1 != [nil]))
|> Stream.zip(ops)
|> Enum.sum_by(fn {numbers, op} -> apply_op(op, numbers) end)
end
defp apply_op("+", args), do: Enum.sum(args)
defp apply_op("*", args), do: Enum.product(args)
end
Edit:
yes, that makes is much simpler:
def part_two(input) do
rows = Input.read!(input) |> String.split("\n", trim: true)
{ops, rows} = List.pop_at(rows, -1)
rows = Enum.map(rows, &String.graphemes/1)
ops = String.split(ops, " ", trim: true)
rows
|> Enum.zip_with(fn digits -> String.trim(Enum.join(digits)) end)
|> Stream.map(fn
"" -> nil
str_num -> String.to_integer(str_num)
end)
|> Stream.chunk_by(&is_integer/1)
|> Stream.filter(&(&1 != [nil]))
|> Stream.zip(ops)
|> Enum.sum_by(fn {numbers, op} -> apply_op(op, numbers) end)
end
I had a version of my first solution with chunk_while as well but I feel it makes everything harder to read.
I donāt love the code I wrote today - all the work was in parsing the input into the shape I wanted. Lots of string manipulations, list transposing, and messy stuff.
Also, this is the first time this year Iāve been confused at the speed of my solution, did some profiling, and found out that all the time was totally not where I expected it to be!
Name ips average deviation median 99th %
day 06, part 1 363.34 2.75 ms ±1.88% 2.76 ms 2.82 ms
day 06, part 2 258.39 3.87 ms ±5.48% 3.91 ms 4.97 ms
Same comment. Most of the job is done in the parsing, accumulate data in Map, to get a data structure that makes the main algorithm I simple.
But I still wonder how to make it nice.
defmodule AdventOfCode.Solution.Year2025.Day06 do
import Enum, only: [with_index: 1, reduce: 3, sum: 1, take: 2]
def mul(l), do: reduce(l, 1, &(&1 * &2))
def parse_part1(input) do
# Returns a list of groups like {:mul, [12,1453,23]} (operator, operands)
input
|> String.split("\n", trim: true)
|> reduce(
%{},
fn line, acc ->
indexed_groups = line |> String.split(" ", trim: true) |> with_index()
reduce(indexed_groups, acc, fn {chunk, chunk_number}, local_acc ->
{operator, operands} = Map.get(local_acc, chunk_number, {nil, []})
case chunk do
"*" ->
Map.put(local_acc, chunk_number, {:mul, operands})
"+" ->
Map.put(local_acc, chunk_number, {:add, operands})
number ->
Map.put(local_acc, chunk_number, {operator, [String.to_integer(number) | operands]})
end
end)
end
)
|> Map.values()
end
def part1(input) do
parse_part1(input)
|> reduce(0, fn
{op, l}, acc ->
acc + if op == :mul, do: mul(l), else: sum(l)
end)
end
def parse2(input) do
lines = input |> String.split("\n", trim: true)
{
# map of %{column => number}
reduce(take(lines, length(lines) - 1), %{}, fn line, acc ->
line
|> String.codepoints()
|> with_index()
|> reduce(acc, fn {c, col}, local_acc ->
Map.update(local_acc, col, c, &(&1 <> c))
end)
end)
|> reduce(%{}, fn {col, s}, acc ->
s = String.trim(s)
if s == "", do: acc, else: Map.put(acc, col, String.to_integer(s))
end)
|> Map.new(),
# map of %{column => operator}
List.last(lines)
|> to_charlist()
|> with_index()
|> reduce(%{}, fn {c, col}, acc ->
if c == 32, do: acc, else: Map.put(acc, col, c)
end)
}
end
# Find the next element in a list. returns max_length if reaching the end of the list
def next([val], val, max_length), do: max_length
def next([val, n | _], val, _max_length), do: n
def next([_n | r], val, max_length), do: next(r, val, max_length)
# Gather numbers starting from col till an empty column
def gather(numbers, col, acc) do
if Map.has_key?(numbers, col), do: gather(numbers, col + 1, [numbers[col] | acc]), else: acc
end
def part2(input) do
{numbers, operators} = parse2(input)
reduce(operators, 0, fn {col, op}, acc ->
l = gather(numbers, col, [])
acc + if op == ?*, do: mul(l), else: sum(l)
end)
end
end
Anyone else feel there was little āfunā in todays problem? I enjoy problems when there is a challenging data structure or algorithmic obstacle to surmount. This seemed like a lot of persnickety busywork.
defmodule RAoc.Solutions.Y25.Day06 do
alias AoC.Input
# Parts 1 and 2 have their own parsers
def parse(input, _part) do
input
end
def part_one(input) do
Input.stream!(input, trim: true)
|> Stream.map(fn line ->
String.split(line, " ", trim: true)
end)
|> Enum.zip()
|> Enum.map(fn tuple ->
[operator | operands] = Tuple.to_list(tuple) |> Enum.reverse()
{operator, Enum.map(operands, &String.to_integer/1)}
end)
|> Enum.map(&solve/1)
|> Enum.sum()
end
def part_two(input) do
Input.read!(input)
|> String.split("\n", trim: true)
|> Enum.map(&String.graphemes/1)
|> move_last_to_first()
|> then(fn [operators | operands] ->
operators =
operators
|> Enum.reject(&(&1 == " "))
|> Enum.reverse()
operands =
operands
|> Enum.zip()
|> Enum.reverse()
|> Enum.map(fn tuple ->
tuple
|> Tuple.to_list()
|> Enum.join()
|> String.trim()
end)
|> Enum.chunk_by(&(&1 == ""))
|> Enum.reject(&(&1 == [""]))
|> Enum.map(fn list -> Enum.map(list, &String.to_integer/1) end)
Enum.zip(operators, operands)
end)
|> Enum.map(&solve/1)
|> Enum.sum()
end
defp solve({"*", operands}), do: Enum.product(operands)
defp solve({"+", operands}), do: Enum.sum(operands)
defp move_last_to_first([]), do: []
defp move_last_to_first(list) do
[last | rest_reversed] = Enum.reverse(list)
[last | Enum.reverse(rest_reversed)]
end
end
Yeah, as I have a time limit I only made Part 1, Part 2 I only drafted in pseudo code: taking largest number in a row (A), then chunk the 'row stringā with number A to have the numbers including whitespace. From there on itās just āgridāing again.
Part 1
def parse(input, _part) do
Input.read!(input)
|> String.trim()
|> String.split("\n")
end
def part_one(problem) do
problem
|> Enum.flat_map(&String.split(&1) |> Enum.with_index )
|> Enum.reverse()
|> Enum.group_by(fn {x,y} -> y end, fn {x,y} -> x end)
|> Enum.map(fn {_, [op | rest]} ->
Enum.intersperse(rest, op)
|> List.to_string()
|> Code.eval_string()
|> elem(0)
end)
|> Enum.sum()
end
Reading the second problem on the iPhone makes it more challenging to understand how their math works⦠(see the alignment of numbers)
I donāt use elixir much, mainly just learning for some hobby projects I have in mind, but I like doing these puzzles as I learn about functions I donāt use or know much and itās just a different way of thinking stringing things together in pipelines. I kind of enjoyed the parsing challenge in the second part. Zip and chunk_by are ones I rarely use that helped me out today.
defmodule Puzzle do
def parse_first(input) do
input
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, " ", trim: true))
|> Enum.zip()
|> Enum.map(&Tuple.to_list/1)
|> Enum.map(&Enum.reverse/1)
end
def parse_second(input) do
rows = String.split(input, "\n")
operators =
List.last(rows)
|> String.split(" ", trim: true)
rows =
rows
|> List.delete_at(length(rows) - 1)
|> Enum.map(&String.graphemes/1)
|> Enum.zip()
|> Enum.map(&Tuple.to_list/1)
|> Enum.map(&Enum.join/1)
|> Enum.map(&String.trim/1)
|> Enum.chunk_by(&(&1 == ""))
|> Enum.filter(fn chunk -> chunk != [""] end)
Enum.zip(operators, rows)
|> Enum.map(fn {operator, values} -> [operator | values] end)
end
def compute_column([operator | values]) do
case operator do
"*" ->
Enum.reduce(values, 1, fn value_str, acc ->
String.to_integer(value_str) * acc
end)
"+" ->
Enum.reduce(values, 0, fn value_str, acc ->
String.to_integer(value_str) + acc
end)
end
end
end
#Part 1
Puzzle.parse_first(input)
|> Enum.reduce(0, fn col, acc ->
acc + Puzzle.compute_column(col)
end)
#Part 2
Puzzle.parse_second(input)
|> Enum.reduce(0, fn col, acc ->
acc + Puzzle.compute_column(col)
end)
Today was a very easy but nice problem
That one is going straight into my Aoc.Utils, thank you!
2025 Dec 06
Trash Compactor
defmodule Cephalopod do
def parse_line(line, columns) do
col_strs = String.split(line)
columns = if columns == nil do
Enum.map(col_strs, fn _ -> [] end)
else
columns
end
Enum.zip_with(col_strs, columns, fn str, column ->
case Integer.parse(str) do
:error ->
[String.to_atom(str) | column]
{n, ""} ->
[n | column]
end
end)
end
def parse(lines) do
Enum.reduce(lines, nil, &parse_line/2)
end
def sum_work(columns) do
Enum.reduce(columns, 0, fn column, sum ->
case column do
[:+ | ns] ->
sum + Enum.sum(ns)
[:* | ns] ->
sum + Enum.product(ns)
end
end)
end
end
test_input = """
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
""" |> String.split("\n", trim: true)
|> IO.inspect()
test1_work = Cephalopod.parse(test_input)
Cephalopod.sum_work(test1_work)
input_work = File.stream!(__DIR__ <> "/dec-06-input.txt")
|> Cephalopod.parse()
Cephalopod.sum_work(input_work)
Part Two
defmodule Cephalopod2 do
def parse(lines) do
flipped = Enum.map(lines, fn line ->
to_charlist(String.trim_trailing(line, "\n"))
end)
|> Enum.zip_with(&Function.identity/1)
|> Enum.map(&to_string/1)
Enum.flat_map(flipped, fn s ->
case Regex.run(~r"^\s*(\d*)\s*([*+])?$", s) do
[_match, ""] ->
[]
[_match, digits] ->
[String.to_integer(digits)]
[_match, digits, op] ->
[String.to_atom(op), String.to_integer(digits)]
end
end)
end
def sum_work(formulae, op \\ nil, acc \\ nil, sum \\ 0) do
case formulae do
[:+ | rest] ->
sum = if acc != nil do
sum + acc
else
sum
end
sum_work(rest, :+, 0, sum)
[:* | rest] ->
sum = if acc != nil do
sum + acc
else
sum
end
sum_work(rest, :*, 1, sum)
[n | rest] ->
acc = case op do
:* ->
n * acc
:+ ->
n + acc
end
sum_work(rest, op, acc, sum)
[] ->
sum + acc
end
end
end
test2_work = Cephalopod2.parse(test_input)
|> IO.inspect()
Cephalopod2.sum_work(test2_work)
input_work2 = File.stream!(__DIR__ <> "/dec-06-input.txt")
|> Cephalopod2.parse()
|> IO.inspect()
Cephalopod2.sum_work(input_work2)
Didnāt know about that one, would have made my life easier
Enum.zip_with(list, &Function.identity/1)
My original code, didnāt refactor, so not very readable :
defmodule Day6 do
def file, do: Parser.read_file(6)
def test, do: Parser.read_file("test")
def parse(input) do
input
end
def solve(input \\ file()) do
input
|> Enum.reduce(%{}, fn line, acc ->
line
|> String.split()
|> Stream.with_index()
|> Enum.reduce(acc, fn {value, index}, acc ->
Map.update(acc, index, [value], fn list -> [value | list] end)
end)
end)
|> Map.values()
|> Enum.map(&solve_line/1)
|> Enum.sum()
end
def solve_line(list) do
[operation | rest] = list
new_list = Enum.reverse(rest) |> Enum.map(&String.to_integer/1)
calculate(new_list, operation)
end
def calculate(list, "+"), do: Enum.sum(list)
def calculate(list, "*"), do: Enum.product(list)
def solve_two(input \\ file()) do
{operator_line, number_lines} = Enum.map(input, &String.graphemes/1) |> List.pop_at(-1)
operator_line
|> get_operation_length
|> Enum.reduce({[], number_lines}, fn {operator, operation_length},
{new_stuf, lines_to_cut} ->
{problem, rest} =
Enum.reduce(lines_to_cut, {[], []}, fn line, {new, old} ->
{one, two} = line |> Enum.split(operation_length)
{new ++ [one], old ++ [two]}
end)
{[{operator, problem} | new_stuf], rest}
end)
|> elem(0)
|> Enum.map(fn {operator, future_number} ->
future_number |> build_number() |> Enum.reverse() |> calculate(operator)
end)
|> Enum.sum()
end
def build_number(list) do
list
|> Enum.reduce(%{}, fn list, acc ->
list
|> Stream.with_index()
|> Map.new(fn {k, v} -> {v, k} end)
|> Map.merge(acc, fn _key, v1, v2 -> [v1 | List.wrap(v2)] end)
end)
|> Map.values()
|> Enum.map(fn list ->
list
|> Enum.join()
|> String.trim()
|> String.reverse()
end)
|> Enum.reject(&(&1 == ""))
|> Enum.map(&String.to_integer/1)
end
def get_operation_length(operator_line) do
operator_line
|> Enum.reduce([], fn symbol, acc ->
case symbol do
" " ->
[{operator, count} | rest] = acc
[{operator, count + 1} | rest]
operator ->
[{operator, 1} | acc]
end
end)
|> Enum.map(fn {op, count} -> {op, count} end)
|> Enum.reverse()
end
end
Apologies for those who recurse.
I love Elixir but Iām solving the problems in Go this year. I also felt day06 was a fussy problem not challenging. I parsed part 1 quickly and solved it. Then it was parse again with a rotated input. Ok, how do you rotate a grid, then apply use in the puzzle. That was about the only interesting bit.
My Go solution is here if anyone wants to look.
Part 1
transpose = fn list -> Enum.zip_with(list, &Function.identity/1) end
values =
File.read!("ids.txt")
|> String.split("\n")
|> Enum.map(&(Regex.split(~r{\s+}, &1, trim: true)))
transpose.(values)
|> Enum.map(&Enum.reverse/1)
|> Enum.map(fn [head | tail] ->
case head do
"*" -> tail |> Enum.map(&String.to_integer/1) |> Enum.product
"+" -> tail |> Enum.map(&String.to_integer/1) |> Enum.sum
end
end)
|> Enum.sum
|> IO.inspect
Part 2
transpose = fn list -> Enum.zip_with(list, &Function.identity/1) end
items =
File.read!("ids.txt")
|> String.split("\n")
|> Enum.map(&(String.split(&1, "", trim: true)))
transpose.(items)
|> Enum.map(&Enum.reverse/1)
|> Enum.map(fn [head | tail] -> {head, tail |> Enum.reverse |> Enum.join("") |> String.trim} end)
|> Enum.chunk_by(fn {_, value} -> value == "" end)
|> Enum.reject(&(&1 == [{" ", ""}]))
|> Enum.map(fn [{operand, value} | tail] ->
Enum.reduce(tail, String.to_integer(value), fn {_, x}, acc ->
case operand do
"*" -> acc * String.to_integer(x)
"+" -> acc + String.to_integer(x)
end
end)
end)
|> Enum.sum
|> IO.inspect
You can replace
def mul(l), do: reduce(l, 1, &(&1 * &2))
with
def mul(l), do: reduce(l, &*/2)
shorter and easier to read ![]()
Enum.product(list)























