1
1
Fork 0

Fucking again.

I couldn't solve Day 4 in elixir. once again. I had to trash this and do
it in scala instead
This commit is contained in:
g 2018-12-04 15:01:32 +08:00
parent 65afc4b41b
commit 6090646727
No known key found for this signature in database
GPG Key ID: 60F3D48C2F3C0415
2 changed files with 1152 additions and 0 deletions

96
day4.exs Normal file
View File

@ -0,0 +1,96 @@
defmodule DayFour do
def decode_all(input) do
partial = input
|> String.split("\n")
|> Enum.filter(&(&1 != ""))
|> Enum.map(&DayFour.decode_log/1)
|> Enum.sort_by(fn {_,_, year, month, day, hour, minute} -> year * 100000000 + month * 100000 + day * 10000 + hour * 100 + minute end)
DayFour.map_to_guard(partial, 0)
# |> Enum.map(fn {action, guard, _, _, _, _, minute} -> {action, guard, minute} end)
end
def decode_log(log) do
pattern = ~r/\[(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})\] (wakes|falls|Guard) #?(\d{0,})/
[[ _ | match]] = Regex.scan(pattern, log)
decode_entry(match)
end
def decode_entry([year, month, day, hour, minute, "Guard", number]) do
{:guard, String.to_integer(number), String.to_integer(year), String.to_integer(month), String.to_integer(day), String.to_integer(hour), String.to_integer(minute)}
end
def decode_entry([year, month, day, hour, minute, "wakes", _]) do
{:wake, nil, String.to_integer(year), String.to_integer(month), String.to_integer(day), String.to_integer(hour), String.to_integer(minute)}
end
def decode_entry([year, month, day, hour, minute, "falls", _]) do
{:sleep, nil, String.to_integer(year), String.to_integer(month), String.to_integer(day), String.to_integer(hour), String.to_integer(minute)}
end
def map_to_guard([{:guard, id, year, month, day, hour, minute} | tail], _) do
now = {:guard, id, year, month, day, hour, minute}
[now | map_to_guard(tail, id)]
end
def map_to_guard([now | tail], current) do
{action, _, year, month, day, hour, minute} = now
[{action, current, year, month, day, hour, minute} | map_to_guard(tail, current)]
end
def map_to_guard([], _), do: []
def part_one(input) do
minutes = Enum.zip(0..60, Enum.map(0..60, fn _ -> 0 end)) |> Map.new
sleeping_by_guard = decode_all(input)
|> Enum.group_by(fn {_, id, _, _, _, _, _} -> id end)
|> Enum.map(fn {id, list} -> {id, Enum.sort_by(list, fn {_,_, year, month, day, hour, minute} -> year * 100000000 + month * 100000 + day * 10000 + hour * 100 + minute end)} end)
|> Enum.map(fn {id, list} -> {id, calc_asleep_times(list, 60, minutes)} end)
time_by_guard = sleeping_by_guard
|> Enum.map(fn {id, times} -> {id, Map.to_list(times)} end)
|> Enum.sort_by(fn {_, times} -> List.foldl(times, 0, fn {_, c}, acc -> c + acc end) end)
|> Enum.reverse
[longest_sleeper | _] = time_by_guard
{id, times} = longest_sleeper
minutes = times
|> Enum.sort_by(fn {_, time} -> time end)
|> Enum.reverse
[{longest_minute, _} | _ ] = minutes
"(id: #{id}, minute: #{longest_minute})"
end
def calc_asleep_times([{:guard, _, _, _, _, _, _} | tail], 60, acc) do
calc_asleep_times(tail, 60, acc)
end
def calc_asleep_times([{:guard, _, _, _, _, _, _} | tail], last, acc) do
times = Enum.to_list(last..60)
calc_asleep_times(tail, 60, increment_map(times, acc))
end
def calc_asleep_times([{:sleep, _, _, _, _, _, minute} | tail], _, acc) do
calc_asleep_times(tail, minute, acc)
end
def calc_asleep_times([{:wake, _, _, _, _, _, minute} | tail], last, acc) do
times = Enum.to_list(last..minute)
calc_asleep_times(tail, 60, increment_map(times, acc))
end
def calc_asleep_times([], 60, acc), do: acc
def calc_asleep_times([], last, acc), do: increment_map(Enum.to_list(last..60), acc)
def increment_map([head | tail], acc) do
increment_map(tail, Map.update!(acc, head, &( &1 + 1)))
end
def increment_map([], acc), do: acc
def part_two(input) do
minutes = Enum.zip(0..60, Enum.map(0..60, fn _ -> 0 end)) |> Map.new
sleeping_by_guard = decode_all(input)
|> Enum.group_by(fn {_, id, _, _, _, _, _} -> id end)
|> Enum.map(fn {id, list} -> {id, Enum.sort_by(list, fn {_,_, year, month, day, hour, minute} -> year * 100000000 + month * 100000 + day * 10000 + hour * 100 + minute end)} end)
|> Enum.map(fn {id, list} -> {id, calc_asleep_times(list, 60, minutes)} end)
{id, {minute, time}} = sleeping_by_guard
|> Enum.map(fn {id, sleeps} -> {id, Enum.max_by(sleeps, fn {minute, time} -> time end)} end)
|> Enum.max_by(fn {id, {minute, time}} -> time end)
"id: #{id} minute: #{minute} times: #{time}"
end
end
{:ok, content} = File.read "input4.txt"
IO.puts "Part 1: #{DayFour.part_one(content)}"
IO.puts "Part 2: #{DayFour.part_two(content)}"

1056
input4.txt Normal file

File diff suppressed because it is too large Load Diff