# Advent of Code 2023 - Day 5

Hi folks! Ukrainian Erlanger is here ! It’s a brand new day, and that means a fresh puzzle challenge awaits us on Advent of Code for for Day 5 . So, get those coding fingers ready and embark on this exciting journey of problem-solving! Happy coding to all!

2 Likes

Here is my Day 5 solution:

``````defmodule Aoc.Five do
def parse(string) do
["seeds:" <> seeds | rest] = String.split(string, "\n\n", trim: true)

{parse_line(seeds),
rest
|> Enum.map(fn block ->
String.split(block, "\n", trim: true)
|> tl()
|> Enum.map(fn line ->
line
|> parse_line()
|> then(fn [map, from, len] -> {from, from + len - 1, map} end)
end)
|> Enum.sort()
end)}
end

def parse_line(line) do
line
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
end

def part_one({seeds, map}) do
seeds
|> Enum.map(&follow_map(&1, map))
|> Enum.min()
end

def follow_map(seed, []), do: seed

def follow_map(seed, [ranges | rest]) do
ranges
|> Enum.find_value(seed, fn {from, to, map} ->
if seed in from..to do
seed - from + map
else
false
end
end)
|> follow_map(rest)
end

def part_two({seeds, map}) do
seeds
|> Enum.chunk_every(2)
|> Enum.map(fn [a, b] -> {a, a + b - 1} end)
|> follow_map_ranges(map)
|> Enum.min()
|> elem(0)
end

def follow_map_ranges(seed_ranges, []), do: seed_ranges

def follow_map_ranges(seed_ranges, [ranges | map]) do
for seed_range <- seed_ranges,
new_ranges <- follow_map_ranges(walk_range(seed_range, ranges), map) do
new_ranges
end
end

def walk_range(range, []), do: [range]

def walk_range({_, b} = range, [{from, _, _} | _])
when b < from do
[range]
end

def walk_range({a, _} = range, [{_, to, _} | rest])
when a > to do
walk_range(range, rest)
end

def walk_range({a, b}, [{from, _, _} | _] = ranges)
when a < from and b >= from do
[{a, from - 1} | walk_range({from, b}, ranges)]
end

def walk_range({a, b}, [{from, to, new_from} | _])
when a >= from and b <= to do
[{new_from + a - from, b - from + new_from}]
end

def walk_range({a, b}, [{from, to, new_from} | rest])
when a >= from and a <= to and b > to do
[{new_from + a - from, new_from + to - from} | walk_range({to + 1, b}, rest)]
end
end