Format
This commit is contained in:
parent
7d5f3501c0
commit
ee489439e1
|
@ -1,5 +1,4 @@
|
||||||
defmodule Day4 do
|
defmodule Day4 do
|
||||||
|
|
||||||
defmodule Timestamp do
|
defmodule Timestamp do
|
||||||
defstruct [:year, :month, :day, :hour, :minute]
|
defstruct [:year, :month, :day, :hour, :minute]
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ defmodule Day4 do
|
||||||
month: m |> String.to_integer(),
|
month: m |> String.to_integer(),
|
||||||
day: d |> String.to_integer(),
|
day: d |> String.to_integer(),
|
||||||
hour: h |> String.to_integer(),
|
hour: h |> String.to_integer(),
|
||||||
minute: min |> String.to_integer
|
minute: min |> String.to_integer()
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,10 +16,11 @@ defmodule Day4 do
|
||||||
first.minute..second.minute
|
first.minute..second.minute
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_event(line) do
|
def parse_event(line) do
|
||||||
res = Regex.run(~r/\[(\d+)-(\d+)-(\d+) (\d+):(\d+)\] (.+)/, line)
|
res = Regex.run(~r/\[(\d+)-(\d+)-(\d+) (\d+):(\d+)\] (.+)/, line)
|
||||||
[_line, y, m, d, h, min, event | _tail] = res
|
[_line, y, m, d, h, min, event | _tail] = res
|
||||||
|
|
||||||
{
|
{
|
||||||
Timestamp.create(y, m, d, h, min),
|
Timestamp.create(y, m, d, h, min),
|
||||||
event
|
event
|
||||||
|
@ -53,10 +53,12 @@ defmodule Day4 do
|
||||||
_id -> {:cont, Enum.reverse(acc), [event]}
|
_id -> {:cont, Enum.reverse(acc), [event]}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
after_fun = fn
|
after_fun = fn
|
||||||
[] -> {:cont, []}
|
[] -> {:cont, []}
|
||||||
acc -> {:cont, Enum.reverse(acc), acc}
|
acc -> {:cont, Enum.reverse(acc), acc}
|
||||||
end
|
end
|
||||||
|
|
||||||
events
|
events
|
||||||
|> Enum.chunk_while([], chunk_fun, after_fun)
|
|> Enum.chunk_while([], chunk_fun, after_fun)
|
||||||
|> Enum.reject(fn
|
|> Enum.reject(fn
|
||||||
|
@ -65,11 +67,14 @@ defmodule Day4 do
|
||||||
end)
|
end)
|
||||||
|> Enum.reduce(%{}, fn [begin_shift | events], acc ->
|
|> Enum.reduce(%{}, fn [begin_shift | events], acc ->
|
||||||
guard_id = parse_guard(begin_shift)
|
guard_id = parse_guard(begin_shift)
|
||||||
ranges = events
|
|
||||||
|> Enum.chunk_every(2)
|
ranges =
|
||||||
|> Enum.map(fn [{sleep, _}, {wake, _} | []] ->
|
events
|
||||||
Timestamp.range(sleep, wake)
|
|> Enum.chunk_every(2)
|
||||||
end)
|
|> Enum.map(fn [{sleep, _}, {wake, _} | []] ->
|
||||||
|
Timestamp.range(sleep, wake)
|
||||||
|
end)
|
||||||
|
|
||||||
Map.update(acc, guard_id, ranges, &(&1 ++ ranges))
|
Map.update(acc, guard_id, ranges, &(&1 ++ ranges))
|
||||||
end)
|
end)
|
||||||
|> Enum.reject(fn
|
|> Enum.reject(fn
|
||||||
|
@ -81,38 +86,48 @@ defmodule Day4 do
|
||||||
def get_max_sleep_time(guards) do
|
def get_max_sleep_time(guards) do
|
||||||
guards
|
guards
|
||||||
|> Enum.map(fn {id, times} ->
|
|> Enum.map(fn {id, times} ->
|
||||||
total = times
|
total =
|
||||||
|> Enum.map(fn a..b -> b - a end)
|
times
|
||||||
|> Enum.sum()
|
|> Enum.map(fn a..b -> b - a end)
|
||||||
{minute, _count} = times
|
|> Enum.sum()
|
||||||
|> Enum.flat_map(&Enum.to_list/1)
|
|
||||||
|> Enum.reduce(%{}, fn minute, acc ->
|
{minute, _count} =
|
||||||
Map.update(acc, minute, 1, &(&1 + 1))
|
times
|
||||||
end)
|
|> Enum.flat_map(&Enum.to_list/1)
|
||||||
|> Enum.max_by(fn {_minute, count} -> count end)
|
|> Enum.reduce(%{}, fn minute, acc ->
|
||||||
|
Map.update(acc, minute, 1, &(&1 + 1))
|
||||||
|
end)
|
||||||
|
|> Enum.max_by(fn {_minute, count} -> count end)
|
||||||
|
|
||||||
{id, total, minute}
|
{id, total, minute}
|
||||||
end)
|
end)
|
||||||
|> Enum.max_by(fn {_id, total, _minute} -> total end)
|
|> Enum.max_by(fn {_id, total, _minute} -> total end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def range_containing(ranges) do
|
def range_containing(ranges) do
|
||||||
first = Enum.reduce(ranges, Enum.at(ranges, 0).first, fn first.._, acc ->
|
first =
|
||||||
min(first, acc)
|
Enum.reduce(ranges, Enum.at(ranges, 0).first, fn first.._, acc ->
|
||||||
end)
|
min(first, acc)
|
||||||
last = Enum.reduce(ranges, Enum.at(ranges, 0).last, fn _..last, acc ->
|
end)
|
||||||
max(last, acc)
|
|
||||||
end)
|
last =
|
||||||
|
Enum.reduce(ranges, Enum.at(ranges, 0).last, fn _..last, acc ->
|
||||||
|
max(last, acc)
|
||||||
|
end)
|
||||||
|
|
||||||
first..last
|
first..last
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_most_frequent_sleep_time(guards) do
|
def get_most_frequent_sleep_time(guards) do
|
||||||
guards
|
guards
|
||||||
|> Enum.map(fn {id, times} ->
|
|> Enum.map(fn {id, times} ->
|
||||||
{minute, count} = range_containing(times)
|
{minute, count} =
|
||||||
|> Enum.map(fn minute ->
|
range_containing(times)
|
||||||
{minute, Enum.count(times, fn range -> minute in range end)}
|
|> Enum.map(fn minute ->
|
||||||
end)
|
{minute, Enum.count(times, fn range -> minute in range end)}
|
||||||
|> Enum.max_by(fn {_minute, count} -> count end)
|
end)
|
||||||
|
|> Enum.max_by(fn {_minute, count} -> count end)
|
||||||
|
|
||||||
{id, minute, count}
|
{id, minute, count}
|
||||||
end)
|
end)
|
||||||
|> Enum.max_by(fn {_id, _minute, count} -> count end)
|
|> Enum.max_by(fn {_id, _minute, count} -> count end)
|
||||||
|
@ -124,21 +139,24 @@ defmodule Day4 do
|
||||||
end
|
end
|
||||||
|
|
||||||
def part1() do
|
def part1() do
|
||||||
{id, _total, minute} = parse_input()
|
{id, _total, minute} =
|
||||||
|> parse_events()
|
parse_input()
|
||||||
|> sort_events()
|
|> parse_events()
|
||||||
|> get_sleep_times()
|
|> sort_events()
|
||||||
|> get_max_sleep_time()
|
|> get_sleep_times()
|
||||||
|
|> get_max_sleep_time()
|
||||||
|
|
||||||
String.to_integer(id) * minute
|
String.to_integer(id) * minute
|
||||||
end
|
end
|
||||||
|
|
||||||
def part2() do
|
def part2() do
|
||||||
{id, minute, _count} = parse_input()
|
{id, minute, _count} =
|
||||||
|> parse_events()
|
parse_input()
|
||||||
|> sort_events()
|
|> parse_events()
|
||||||
|> get_sleep_times()
|
|> sort_events()
|
||||||
|> get_most_frequent_sleep_time()
|
|> get_sleep_times()
|
||||||
|
|> get_most_frequent_sleep_time()
|
||||||
|
|
||||||
String.to_integer(id) * minute
|
String.to_integer(id) * minute
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
defmodule Day5 do
|
defmodule Day5 do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Compares two codepoints for opposite case.
|
Compares two codepoints for opposite case.
|
||||||
|
|
||||||
|
@ -18,6 +17,7 @@ defmodule Day5 do
|
||||||
else
|
else
|
||||||
[c | s]
|
[c | s]
|
||||||
end
|
end
|
||||||
|
|
||||||
c, [] ->
|
c, [] ->
|
||||||
[c]
|
[c]
|
||||||
end)
|
end)
|
||||||
|
@ -76,6 +76,7 @@ defmodule Day5 do
|
||||||
s = <<c::utf8>>
|
s = <<c::utf8>>
|
||||||
str = String.replace(input, s, "")
|
str = String.replace(input, s, "")
|
||||||
str = String.replace(str, String.upcase(s), "")
|
str = String.replace(str, String.upcase(s), "")
|
||||||
|
|
||||||
input
|
input
|
||||||
|> String.replace(s, "")
|
|> String.replace(s, "")
|
||||||
|> String.replace(String.upcase(s), "")
|
|> String.replace(String.upcase(s), "")
|
||||||
|
@ -87,7 +88,7 @@ defmodule Day5 do
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_input() do
|
def parse_input() do
|
||||||
File.read!("lib/day5/input.txt")
|
File.read!("lib/day5/input.txt")
|
||||||
end
|
end
|
||||||
|
|
||||||
def part1() do
|
def part1() do
|
||||||
|
@ -101,5 +102,4 @@ defmodule Day5 do
|
||||||
parse_input()
|
parse_input()
|
||||||
|> min_length()
|
|> min_length()
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
defmodule Day6 do
|
defmodule Day6 do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Parses a node from a string.
|
Parses a node from a string.
|
||||||
|
|
||||||
|
@ -11,6 +10,7 @@ defmodule Day6 do
|
||||||
"""
|
"""
|
||||||
def parse_node(s) do
|
def parse_node(s) do
|
||||||
[x, y] = String.split(s, ", ")
|
[x, y] = String.split(s, ", ")
|
||||||
|
|
||||||
{
|
{
|
||||||
x |> String.to_integer(),
|
x |> String.to_integer(),
|
||||||
y |> String.to_integer()
|
y |> String.to_integer()
|
||||||
|
@ -39,7 +39,7 @@ defmodule Day6 do
|
||||||
nil
|
nil
|
||||||
"""
|
"""
|
||||||
def nearest_node(point, all) do
|
def nearest_node(point, all) do
|
||||||
nearest =
|
nearest =
|
||||||
all
|
all
|
||||||
|> Enum.map(fn other -> {other, distance(point, other)} end)
|
|> Enum.map(fn other -> {other, distance(point, other)} end)
|
||||||
|
|
||||||
|
@ -58,9 +58,11 @@ defmodule Day6 do
|
||||||
0..grid_size
|
0..grid_size
|
||||||
|> Enum.reduce(acc, fn x, {areas, infinite_area_nodes} ->
|
|> Enum.reduce(acc, fn x, {areas, infinite_area_nodes} ->
|
||||||
pt = {x, y}
|
pt = {x, y}
|
||||||
|
|
||||||
case nearest_node(pt, nodes) do
|
case nearest_node(pt, nodes) do
|
||||||
nil ->
|
nil ->
|
||||||
{areas, infinite_area_nodes}
|
{areas, infinite_area_nodes}
|
||||||
|
|
||||||
nearest ->
|
nearest ->
|
||||||
if x == 0 or y == 0 or x == grid_size or y == grid_size do
|
if x == 0 or y == 0 or x == grid_size or y == grid_size do
|
||||||
{
|
{
|
||||||
|
@ -102,9 +104,11 @@ defmodule Day6 do
|
||||||
0..grid_size
|
0..grid_size
|
||||||
|> Enum.reduce(acc, fn x, acc ->
|
|> Enum.reduce(acc, fn x, acc ->
|
||||||
pt = {x, y}
|
pt = {x, y}
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
total_distances(pt, nodes) < max_dist ->
|
total_distances(pt, nodes) < max_dist ->
|
||||||
[pt | acc]
|
[pt | acc]
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
|
@ -128,5 +132,4 @@ defmodule Day6 do
|
||||||
|> region_near_most()
|
|> region_near_most()
|
||||||
|> Enum.count()
|
|> Enum.count()
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
|
||||||
|
|
|
@ -4,11 +4,15 @@ defmodule Day4Test do
|
||||||
alias Day4.Timestamp
|
alias Day4.Timestamp
|
||||||
|
|
||||||
test "parse event" do
|
test "parse event" do
|
||||||
assert Day4.parse_event("[1518-11-01 00:00] Guard #10 begins shift") == {%Timestamp{year: 1518, month: 11, day: 01, hour: 0, minute: 0}, "Guard #10 begins shift"}
|
assert Day4.parse_event("[1518-11-01 00:00] Guard #10 begins shift") ==
|
||||||
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 0, minute: 0},
|
||||||
|
"Guard #10 begins shift"}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "parse guard" do
|
test "parse guard" do
|
||||||
event = {%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00}, "Guard #10 begins shift"}
|
event =
|
||||||
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00}, "Guard #10 begins shift"}
|
||||||
|
|
||||||
assert Day4.parse_guard(event) == "10"
|
assert Day4.parse_guard(event) == "10"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,17 +21,19 @@ defmodule Day4Test do
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 05}, "falls asleep"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 05}, "falls asleep"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 55}, "wakes up"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 55}, "wakes up"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 25}, "wakes up"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 25}, "wakes up"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00}, "Guard #10 begins shift"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00},
|
||||||
|
"Guard #10 begins shift"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 30}, "falls asleep"}
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 30}, "falls asleep"}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Day4.sort_events(events) == [
|
assert Day4.sort_events(events) == [
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00}, "Guard #10 begins shift"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 00},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 05}, "falls asleep"},
|
"Guard #10 begins shift"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 25}, "wakes up"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 05}, "falls asleep"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 30}, "falls asleep"},
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 25}, "wakes up"},
|
||||||
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 55}, "wakes up"}
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 30}, "falls asleep"},
|
||||||
]
|
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 55}, "wakes up"}
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get sleep times" do
|
test "get sleep times" do
|
||||||
|
@ -52,9 +58,9 @@ defmodule Day4Test do
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Day4.get_sleep_times(events) == [
|
assert Day4.get_sleep_times(events) == [
|
||||||
{"10", [5..25, 30..55, 24..29]},
|
{"10", [5..25, 30..55, 24..29]},
|
||||||
{"99", [40..50, 36..46, 45..55]}
|
{"99", [40..50, 36..46, 45..55]}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get max sleep time" do
|
test "get max sleep time" do
|
||||||
|
@ -79,5 +85,4 @@ defmodule Day4Test do
|
||||||
|
|
||||||
assert Day4.get_most_frequent_sleep_time(guards) == {"99", 45, 3}
|
assert Day4.get_most_frequent_sleep_time(guards) == {"99", 45, 3}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Day5Test do
|
defmodule Day5Test do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
doctest Day5
|
doctest Day5
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Day6Test do
|
defmodule Day6Test do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
doctest Day6
|
doctest Day6
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue