diff --git a/day4.exs b/day4.exs index 412b98f..2d37274 100644 --- a/day4.exs +++ b/day4.exs @@ -1,96 +1,134 @@ defmodule DayFour do - def decode_all(input) do - partial = input + 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) + |> Enum.sort_by(fn {_, _, year, month, day, hour, minute} -> + year * 100_000_000 + month * 100_000 + 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) + [[_ | 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)} + {: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)} + {: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)} + {: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) + 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, + Enum.sort_by(list, fn {_, _, year, month, day, hour, minute} -> + year * 100_000_000 + month * 100_000 + 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 + + 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 + |> Enum.reverse() + [longest_sleeper | _] = time_by_guard {id, times} = longest_sleeper - minutes = times + + minutes = + times |> Enum.sort_by(fn {_, time} -> time end) - |> Enum.reverse - [{longest_minute, _} | _ ] = minutes + |> 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))) + 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) + 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, + Enum.sort_by(list, fn {_, _, year, month, day, hour, minute} -> + year * 100_000_000 + month * 100_000 + 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 + + {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 end -{:ok, content} = File.read "input4.txt" +{:ok, content} = File.read("input4.txt") -IO.puts "Part 1: #{DayFour.part_one(content)}" -IO.puts "Part 2: #{DayFour.part_two(content)}" +IO.puts("Part 1: #{DayFour.part_one(content)}") +IO.puts("Part 2: #{DayFour.part_two(content)}") diff --git a/day5.exs b/day5.exs index 890ffba..f9c0ee0 100644 --- a/day5.exs +++ b/day5.exs @@ -2,15 +2,16 @@ defmodule DayFive do def part_one(input) do shortened = fully_react_new(input) # IO.puts shortened - (String.length shortened) - 1 + String.length(shortened) - 1 end def fully_react(input) do - replacer = ~r/Aa|Bb|Cc|Dd|Ee|Ff|Gg|Hh|Ii|Jj|Kk|Ll|Mm|Nn|Oo|Pp|Qq|Rr|Ss|Tt|Uu|Ww|Vv|Xx|Yy|Zz|aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|wW|vV|xX|yY|zZ/ + replacer = + ~r/Aa|Bb|Cc|Dd|Ee|Ff|Gg|Hh|Ii|Jj|Kk|Ll|Mm|Nn|Oo|Pp|Qq|Rr|Ss|Tt|Uu|Ww|Vv|Xx|Yy|Zz|aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|wW|vV|xX|yY|zZ/ + replace_forever(input, replacer, "") end - def replace_forever(string, pattern, replacement) do if Regex.match?(pattern, string) do replace_forever(Regex.replace(pattern, string, replacement), pattern, replacement) @@ -19,34 +20,40 @@ defmodule DayFive do end end - def react([<< char1 >> , << char2 >> | tail]) when char1 == char2 - 32 or char2 == char1 - 32, do: react(tail) + def react([<>, <> | tail]) when char1 == char2 - 32 or char2 == char1 - 32, + do: react(tail) + def react([char | tail]), do: [char | react(tail)] def react(""), do: [] def react([]), do: [] def fully_react_new(input) do # IO.puts "mark" - Enum.join( fully_react_new(String.codepoints(input), []) ) + Enum.join(fully_react_new(String.codepoints(input), [])) end def fully_react_new(input, acc) when input == acc, do: acc + def fully_react_new(input, _acc) do # IO.puts("#{length _acc} #{length input}") fully_react_new(react(input), input) end def part_two(input) do - chars = Enum.map(?a..?z, &(<< &1 >>)) - [{_char, poly} | _ ] = Enum.map(chars, fn char -> {char, String.replace(input, char, "")} end) - |> Enum.map(fn {char, poly} -> {char, String.replace(poly, String.upcase(char), "") } end) - |> Enum.map(fn {char, poly} -> {char, fully_react_new(poly)} end) - |> Enum.sort_by(fn {_char, poly} -> String.length(poly) end) + chars = Enum.map(?a..?z, &<<&1>>) + + [{_char, poly} | _] = + Enum.map(chars, fn char -> {char, String.replace(input, char, "")} end) + |> Enum.map(fn {char, poly} -> {char, String.replace(poly, String.upcase(char), "")} end) + |> Enum.map(fn {char, poly} -> {char, fully_react_new(poly)} end) + |> Enum.sort_by(fn {_char, poly} -> String.length(poly) end) + # IO.puts poly String.length(poly) - 1 end end -{:ok, content} = File.read "input5.txt" +{:ok, content} = File.read("input5.txt") -IO.puts "Part 1: #{DayFive.part_one(content)}" -IO.puts "Part 2: #{DayFive.part_two(content)}" +IO.puts("Part 1: #{DayFive.part_one(content)}") +IO.puts("Part 2: #{DayFive.part_two(content)}") diff --git a/day5_doublelinked.exs b/day5_doublelinked.exs index 3c99ef2..4f6c72d 100644 --- a/day5_doublelinked.exs +++ b/day5_doublelinked.exs @@ -2,25 +2,29 @@ defmodule DayFive do def part_one(input) do shortened = fully_react_new(input) # IO.puts shortened - (String.length shortened) - 1 + String.length(shortened) - 1 end - def fully_react(input) do - replacer = ~r/Aa|Bb|Cc|Dd|Ee|Ff|Gg|Hh|Ii|Jj|Kk|Ll|Mm|Nn|Oo|Pp|Qq|Rr|Ss|Tt|Uu|Ww|Vv|Xx|Yy|Zz|aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|wW|vV|xX|yY|zZ/ - replace_forever(input, replacer, "") + def part_two(input) do + chars = Enum.map(?a..?z, &<<&1>>) + + [{_char, poly} | _] = + Enum.map(chars, fn char -> {char, String.replace(input, char, "")} end) + |> Enum.map(fn {char, poly} -> {char, String.replace(poly, String.upcase(char), "")} end) + |> Enum.map(fn {char, poly} -> {char, fully_react_new(poly)} end) + |> Enum.sort_by(fn {_char, poly} -> String.length(poly) end) + + # IO.puts poly + String.length(poly) - 1 end + def react([<>, <> | tail], rev) when char1 == char2 - 32 or char2 == char1 - 32, + do: react(tail, rev) - def replace_forever(string, pattern, replacement) do - if Regex.match?(pattern, string) do - replace_forever(Regex.replace(pattern, string, replacement), pattern, replacement) - else - string - end - end + def react([<> | tail], [<> | rev]) + when char1 == char2 - 32 or char2 == char1 - 32, + do: react(tail, rev) - def react([<< char1 >> , << char2 >> | tail], rev) when char1 == char2 - 32 or char2 == char1 - 32, do: react(tail, rev) - def react([<< char1 >> | tail], [<< char2 >> | rev]) when char1 == char2 - 32 or char2 == char1 - 32, do: react(tail, rev) def react([char | tail], rev), do: react(tail, [char | rev]) def react("", rev), do: rev def react([], rev), do: rev @@ -29,25 +33,9 @@ defmodule DayFive do # IO.puts "mark" String.reverse(Enum.join(react(String.codepoints(input), []))) end - - #def fully_react_new(input, acc) when input == acc, do: acc - #def fully_react_new(input, _acc) do - # IO.puts("#{length _acc} #{length input}") - # fully_react_new(react(input), input) - #end - - def part_two(input) do - chars = Enum.map(?a..?z, &(<< &1 >>)) - [{_char, poly} | _ ] = Enum.map(chars, fn char -> {char, String.replace(input, char, "")} end) - |> Enum.map(fn {char, poly} -> {char, String.replace(poly, String.upcase(char), "") } end) - |> Enum.map(fn {char, poly} -> {char, fully_react_new(poly)} end) - |> Enum.sort_by(fn {_char, poly} -> String.length(poly) end) - # IO.puts poly - String.length(poly) - 1 - end end -{:ok, content} = File.read "input5.txt" +{:ok, content} = File.read("input5.txt") -IO.puts "Part 1: #{DayFive.part_one(content)}" -IO.puts "Part 2: #{DayFive.part_two(content)}" +IO.puts("Part 1: #{DayFive.part_one(content)}") +IO.puts("Part 2: #{DayFive.part_two(content)}")