This commit is contained in:
Shadowfacts 2018-12-06 20:14:24 -05:00
parent 7d5f3501c0
commit ee489439e1
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
6 changed files with 90 additions and 64 deletions

View File

@ -1,5 +1,4 @@
defmodule Day4 do
defmodule Timestamp do
defstruct [:year, :month, :day, :hour, :minute]
@ -9,7 +8,7 @@ defmodule Day4 do
month: m |> String.to_integer(),
day: d |> String.to_integer(),
hour: h |> String.to_integer(),
minute: min |> String.to_integer
minute: min |> String.to_integer()
}
end
@ -17,10 +16,11 @@ defmodule Day4 do
first.minute..second.minute
end
end
def parse_event(line) do
res = Regex.run(~r/\[(\d+)-(\d+)-(\d+) (\d+):(\d+)\] (.+)/, line)
[_line, y, m, d, h, min, event | _tail] = res
{
Timestamp.create(y, m, d, h, min),
event
@ -53,10 +53,12 @@ defmodule Day4 do
_id -> {:cont, Enum.reverse(acc), [event]}
end
end
after_fun = fn
[] -> {:cont, []}
acc -> {:cont, Enum.reverse(acc), acc}
end
events
|> Enum.chunk_while([], chunk_fun, after_fun)
|> Enum.reject(fn
@ -65,11 +67,14 @@ defmodule Day4 do
end)
|> Enum.reduce(%{}, fn [begin_shift | events], acc ->
guard_id = parse_guard(begin_shift)
ranges = events
|> Enum.chunk_every(2)
|> Enum.map(fn [{sleep, _}, {wake, _} | []] ->
Timestamp.range(sleep, wake)
end)
ranges =
events
|> Enum.chunk_every(2)
|> Enum.map(fn [{sleep, _}, {wake, _} | []] ->
Timestamp.range(sleep, wake)
end)
Map.update(acc, guard_id, ranges, &(&1 ++ ranges))
end)
|> Enum.reject(fn
@ -81,38 +86,48 @@ defmodule Day4 do
def get_max_sleep_time(guards) do
guards
|> Enum.map(fn {id, times} ->
total = times
|> Enum.map(fn a..b -> b - a end)
|> Enum.sum()
{minute, _count} = times
|> Enum.flat_map(&Enum.to_list/1)
|> Enum.reduce(%{}, fn minute, acc ->
Map.update(acc, minute, 1, &(&1 + 1))
end)
|> Enum.max_by(fn {_minute, count} -> count end)
total =
times
|> Enum.map(fn a..b -> b - a end)
|> Enum.sum()
{minute, _count} =
times
|> Enum.flat_map(&Enum.to_list/1)
|> Enum.reduce(%{}, fn minute, acc ->
Map.update(acc, minute, 1, &(&1 + 1))
end)
|> Enum.max_by(fn {_minute, count} -> count end)
{id, total, minute}
end)
|> Enum.max_by(fn {_id, total, _minute} -> total end)
end
def range_containing(ranges) do
first = Enum.reduce(ranges, Enum.at(ranges, 0).first, fn first.._, acc ->
min(first, acc)
end)
last = Enum.reduce(ranges, Enum.at(ranges, 0).last, fn _..last, acc ->
max(last, acc)
end)
first =
Enum.reduce(ranges, Enum.at(ranges, 0).first, fn first.._, acc ->
min(first, acc)
end)
last =
Enum.reduce(ranges, Enum.at(ranges, 0).last, fn _..last, acc ->
max(last, acc)
end)
first..last
end
def get_most_frequent_sleep_time(guards) do
guards
|> Enum.map(fn {id, times} ->
{minute, count} = range_containing(times)
|> Enum.map(fn minute ->
{minute, Enum.count(times, fn range -> minute in range end)}
end)
|> Enum.max_by(fn {_minute, count} -> count end)
{minute, count} =
range_containing(times)
|> Enum.map(fn minute ->
{minute, Enum.count(times, fn range -> minute in range end)}
end)
|> Enum.max_by(fn {_minute, count} -> count end)
{id, minute, count}
end)
|> Enum.max_by(fn {_id, _minute, count} -> count end)
@ -124,21 +139,24 @@ defmodule Day4 do
end
def part1() do
{id, _total, minute} = parse_input()
|> parse_events()
|> sort_events()
|> get_sleep_times()
|> get_max_sleep_time()
{id, _total, minute} =
parse_input()
|> parse_events()
|> sort_events()
|> get_sleep_times()
|> get_max_sleep_time()
String.to_integer(id) * minute
end
def part2() do
{id, minute, _count} = parse_input()
|> parse_events()
|> sort_events()
|> get_sleep_times()
|> get_most_frequent_sleep_time()
{id, minute, _count} =
parse_input()
|> parse_events()
|> sort_events()
|> get_sleep_times()
|> get_most_frequent_sleep_time()
String.to_integer(id) * minute
end
end
end

View File

@ -1,5 +1,4 @@
defmodule Day5 do
@doc """
Compares two codepoints for opposite case.
@ -18,6 +17,7 @@ defmodule Day5 do
else
[c | s]
end
c, [] ->
[c]
end)
@ -76,6 +76,7 @@ defmodule Day5 do
s = <<c::utf8>>
str = String.replace(input, s, "")
str = String.replace(str, String.upcase(s), "")
input
|> String.replace(s, "")
|> String.replace(String.upcase(s), "")
@ -87,7 +88,7 @@ defmodule Day5 do
end
def parse_input() do
File.read!("lib/day5/input.txt")
File.read!("lib/day5/input.txt")
end
def part1() do
@ -101,5 +102,4 @@ defmodule Day5 do
parse_input()
|> min_length()
end
end
end

View File

@ -1,5 +1,4 @@
defmodule Day6 do
@doc """
Parses a node from a string.
@ -11,6 +10,7 @@ defmodule Day6 do
"""
def parse_node(s) do
[x, y] = String.split(s, ", ")
{
x |> String.to_integer(),
y |> String.to_integer()
@ -39,7 +39,7 @@ defmodule Day6 do
nil
"""
def nearest_node(point, all) do
nearest =
nearest =
all
|> Enum.map(fn other -> {other, distance(point, other)} end)
@ -58,9 +58,11 @@ defmodule Day6 do
0..grid_size
|> Enum.reduce(acc, fn x, {areas, infinite_area_nodes} ->
pt = {x, y}
case nearest_node(pt, nodes) do
nil ->
{areas, infinite_area_nodes}
nearest ->
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
|> Enum.reduce(acc, fn x, acc ->
pt = {x, y}
cond do
total_distances(pt, nodes) < max_dist ->
[pt | acc]
true ->
acc
end
@ -128,5 +132,4 @@ defmodule Day6 do
|> region_near_most()
|> Enum.count()
end
end
end

View File

@ -4,11 +4,15 @@ defmodule Day4Test do
alias Day4.Timestamp
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
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"
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: 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: 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"}
]
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: 05}, "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: 30}, "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: 00},
"Guard #10 begins shift"},
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 05}, "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: 30}, "falls asleep"},
{%Timestamp{year: 1518, month: 11, day: 01, hour: 00, minute: 55}, "wakes up"}
]
end
test "get sleep times" do
@ -52,9 +58,9 @@ defmodule Day4Test do
]
assert Day4.get_sleep_times(events) == [
{"10", [5..25, 30..55, 24..29]},
{"99", [40..50, 36..46, 45..55]}
]
{"10", [5..25, 30..55, 24..29]},
{"99", [40..50, 36..46, 45..55]}
]
end
test "get max sleep time" do
@ -79,5 +85,4 @@ defmodule Day4Test do
assert Day4.get_most_frequent_sleep_time(guards) == {"99", 45, 3}
end
end
end

View File

@ -1,4 +1,4 @@
defmodule Day5Test do
use ExUnit.Case
doctest Day5
end
end

View File

@ -1,4 +1,4 @@
defmodule Day6Test do
use ExUnit.Case
doctest Day6
end
end