day 5 part 1
This commit is contained in:
parent
2916c3c816
commit
e3d6c5350b
2 changed files with 150 additions and 0 deletions
72
lib/2023_day5.ex
Normal file
72
lib/2023_day5.ex
Normal file
|
@ -0,0 +1,72 @@
|
|||
defmodule Mix.Tasks.Day5 do
|
||||
use Mix.Task
|
||||
|
||||
def run(_) do
|
||||
IO.stream() |> parse() |> part1() |> IO.puts()
|
||||
end
|
||||
|
||||
def split_int_list(s, sep) do
|
||||
s |> String.split(sep) |> Enum.map(fn n -> Integer.parse(n) |> elem(0) end)
|
||||
end
|
||||
|
||||
def parse_line("seeds: " <> seeds) do
|
||||
{:seeds, seeds |> split_int_list(" ")}
|
||||
end
|
||||
|
||||
def parse_line(line) when line != "" do
|
||||
make_range = fn line ->
|
||||
[dest_start, source_start, len] = line |> split_int_list(" ")
|
||||
{:range, {RangeUtil.from_start(dest_start, len), RangeUtil.from_start(source_start, len)}}
|
||||
end
|
||||
cap = Regex.run(~r/(\w+)-to-(\w+) map:/, line)
|
||||
case cap do
|
||||
[_, source, dest] -> {:map_key, { source |> String.to_atom(), dest |> String.to_atom() } }
|
||||
nil -> make_range.(line)
|
||||
end
|
||||
end
|
||||
|
||||
def parse(input) do
|
||||
for line <- input,
|
||||
line = line |> String.trim(),
|
||||
line != "",
|
||||
reduce: %{} do
|
||||
acc ->
|
||||
{type, data} = parse_line(line)
|
||||
case type do
|
||||
:seeds -> acc |> Map.put(type, data)
|
||||
:map_key -> { source, dest } = data
|
||||
acc
|
||||
|> Map.update(:maps, %{source => {dest, []}}, fn maps -> maps |> Map.put(source, {dest, []}) end)
|
||||
|> Map.put(:last_map_key, source)
|
||||
:range -> %{last_map_key: last_map_key} = acc
|
||||
acc |> Map.update!(
|
||||
:maps,
|
||||
fn maps -> maps
|
||||
|> Map.update!(last_map_key, fn {dest, ranges} ->
|
||||
{dest, [data | ranges]}
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
def get_location(:location, n, _) do
|
||||
n
|
||||
end
|
||||
def get_location(source, n, maps) do
|
||||
{dest, ranges} = maps |> Map.get(source)
|
||||
transpose = case ranges |> Enum.find(fn {_, source} ->
|
||||
n in source
|
||||
end) do
|
||||
{dest_range, source_range} ->RangeUtil.transpose(n, source_range, dest_range)
|
||||
nil -> n
|
||||
end
|
||||
IO.puts({dest, transpose} |> inspect())
|
||||
get_location(dest, transpose, maps)
|
||||
end
|
||||
|
||||
def part1(state) do
|
||||
for seed <- state.seeds do
|
||||
get_location(:seed, seed, state.maps)
|
||||
end |> Enum.min()
|
||||
end
|
||||
end
|
78
test/2023_day5_test.exs
Normal file
78
test/2023_day5_test.exs
Normal file
|
@ -0,0 +1,78 @@
|
|||
defmodule Day5Tests do
|
||||
use ExUnit.Case
|
||||
|
||||
test "parse seeds correctly" do
|
||||
assert Mix.Tasks.Day5.parse_line("seeds: 79 14 55 13") == {:seeds, [79, 14, 55, 13]}
|
||||
end
|
||||
|
||||
test "parse map line def" do
|
||||
assert Mix.Tasks.Day5.parse_line("seed-to-soil map:") == {:map_key, { :seed, :soil }}
|
||||
end
|
||||
|
||||
test "parse map line fails" do
|
||||
assert Mix.Tasks.Day5.parse_line("50 98 2") == {:range, {50..51, 98..99}}
|
||||
end
|
||||
|
||||
test "range util does not lie" do
|
||||
assert (RangeUtil.from_start(120, 300) |> Enum.count()) === 300
|
||||
end
|
||||
|
||||
test "range util transpose does not lie" do
|
||||
assert RangeUtil.transpose(98, 98..99, 50..51) === 50
|
||||
end
|
||||
|
||||
test "parse works" do
|
||||
ex = ~s"seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48"
|
||||
assert Mix.Tasks.Day5.parse(ex |> String.split("\n")) == %{
|
||||
:seeds => [79, 14, 55, 13],
|
||||
:maps => %{:seed => {:soil, [{52..99, 50..97}, {50..51, 98..99}]}},
|
||||
:last_map_key => :seed
|
||||
}
|
||||
end
|
||||
|
||||
test "parse doesn't crash with whole input" do
|
||||
ex = ~s"seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
|
||||
temperature-to-humidity map:
|
||||
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
||||
"
|
||||
assert ex |> String.split("\n") |> Mix.Tasks.Day5.parse() |> Mix.Tasks.Day5.part1() == 35
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue