diff --git a/lib/day1/day1.ex b/lib/day1/day1.ex index 3005aa8..d23d870 100644 --- a/lib/day1/day1.ex +++ b/lib/day1/day1.ex @@ -1,7 +1,7 @@ defmodule Day1 do def calculate_frequency(shifts) do shifts - |> Enum.reduce(0, &+/2) + |> Enum.reduce(0, &+/2) end def first_repetition(shifts, index \\ 0, sum \\ 0, seen \\ [0]) do @@ -11,6 +11,7 @@ defmodule Day1 do cond do Enum.member?(seen, sum) -> sum + true -> first_repetition(shifts, next_index, sum, [sum | seen]) end @@ -18,44 +19,46 @@ defmodule Day1 do def first_repetition_stream(shifts) do shifts - |> Stream.cycle() - |> Enum.reduce_while({0, [0]}, fn shift, {sum, seen} -> - sum = sum + shift - cond do - Enum.member?(seen, sum) -> {:halt, sum} - true -> {:cont, {sum, [sum | seen]}} - end - end) + |> Stream.cycle() + |> Enum.reduce_while({0, [0]}, fn shift, {sum, seen} -> + sum = sum + shift + + cond do + Enum.member?(seen, sum) -> {:halt, sum} + true -> {:cont, {sum, [sum | seen]}} + end + end) end def first_repetition_mapset(shifts) do shifts - |> Stream.cycle() - |> Enum.reduce_while({0, MapSet.new([0])}, fn shift, {sum, seen} -> - sum = sum + shift - cond do - sum in seen -> {:halt, sum} - true -> {:cont, {sum, MapSet.put(seen, sum)}} - end - end) + |> Stream.cycle() + |> Enum.reduce_while({0, MapSet.new([0])}, fn shift, {sum, seen} -> + sum = sum + shift + + cond do + sum in seen -> {:halt, sum} + true -> {:cont, {sum, MapSet.put(seen, sum)}} + end + end) end def parse_input() do File.read!("lib/day1/input.txt") - |> String.split("\n") - |> Enum.map(fn s -> - {num, _} = Integer.parse(s) - num - end) + |> String.split("\n") + |> Enum.map(fn s -> + {num, _} = Integer.parse(s) + num + end) end def part1() do parse_input() - |> calculate_frequency() + |> calculate_frequency() end def part2() do parse_input() - |> first_repetition_mapset() + |> first_repetition_mapset() end -end \ No newline at end of file +end diff --git a/lib/day2/day2.ex b/lib/day2/day2.ex index e38fd4b..a460690 100644 --- a/lib/day2/day2.ex +++ b/lib/day2/day2.ex @@ -1,10 +1,10 @@ defmodule Day2 do def count_characters(id) do id - |> String.graphemes() - |> Enum.reduce(%{}, fn c, acc -> - Map.update(acc, c, 1, &(&1 + 1)) - end) + |> String.graphemes() + |> Enum.reduce(%{}, fn c, acc -> + Map.update(acc, c, 1, &(&1 + 1)) + end) end def checksum(list) do @@ -17,23 +17,25 @@ defmodule Day2 do defp any_char_count(n) do fn map -> map - |> Enum.to_list() - |> Enum.any?(fn {_c, count} -> count == n end) + |> Enum.to_list() + |> Enum.any?(fn {_c, count} -> count == n end) end end def diff(a, b) do a = String.graphemes(a) b = String.graphemes(b) + Enum.zip(a, b) - |> Enum.reduce({0, ""}, fn {a, b}, {diff_count, common} -> - cond do - a == b -> - {diff_count, common <> a} - true -> - {diff_count + 1, common} - end - end) + |> Enum.reduce({0, ""}, fn {a, b}, {diff_count, common} -> + cond do + a == b -> + {diff_count, common <> a} + + true -> + {diff_count + 1, common} + end + end) end def match(id, list) do @@ -47,12 +49,12 @@ defmodule Day2 do def correct_boxes(list) do list - |> Enum.reduce_while(nil, fn id, _acc -> - case match(id, list) do - nil -> {:cont, nil} - common -> {:halt, common} - end - end) + |> Enum.reduce_while(nil, fn id, _acc -> + case match(id, list) do + nil -> {:cont, nil} + common -> {:halt, common} + end + end) end def except(list, except) do @@ -61,16 +63,16 @@ defmodule Day2 do defp parse_input() do File.read!("lib/day2/input.txt") - |> String.split("\n") + |> String.split("\n") end def part1() do parse_input() - |> checksum() + |> checksum() end def part2() do parse_input() - |> correct_boxes() + |> correct_boxes() end -end \ No newline at end of file +end diff --git a/lib/day3/day3.ex b/lib/day3/day3.ex index afec048..cb7be89 100644 --- a/lib/day3/day3.ex +++ b/lib/day3/day3.ex @@ -1,11 +1,12 @@ defmodule Day3 do - defmodule Rect do defstruct [:id, :left, :top, :width, :height] def points(nil), do: [] + def points(rect) do xs = rect.left..(rect.left + rect.width - 1) + Enum.flat_map(xs, fn x -> ys = rect.top..(rect.top + rect.height - 1) Enum.map(ys, fn y -> {x, y} end) @@ -14,26 +15,34 @@ defmodule Day3 do def overlap(a, b) do overlap_left = max(a.left, b.left) - overlap_width = max(0, min(a.left + a.width, b.left + b.width) - overlap_left) + overlap_width = max(0, min(a.left + a.width, b.left + b.width) - overlap_left) overlap_top = max(a.top, b.top) overlap_height = max(0, min(a.top + a.height, b.top + b.height) - overlap_top) + case overlap_width * overlap_height do 0 -> nil + _ -> - %Rect{left: overlap_left, top: overlap_top, width: overlap_width, height: overlap_height} + %Rect{ + left: overlap_left, + top: overlap_top, + width: overlap_width, + height: overlap_height + } end end end def parse_rect(str) do parts = Regex.run(~r/#(\d+) @ (\d+),(\d+): (\d+)x(\d+)/, str) + %Rect{ - id: parts |> Enum.at(1) |> String.to_integer, - left: parts |> Enum.at(2) |> String.to_integer, - top: parts |> Enum.at(3) |> String.to_integer, - width: parts |> Enum.at(4) |> String.to_integer, - height: parts |> Enum.at(5) |> String.to_integer, + id: parts |> Enum.at(1) |> String.to_integer(), + left: parts |> Enum.at(2) |> String.to_integer(), + top: parts |> Enum.at(3) |> String.to_integer(), + width: parts |> Enum.at(4) |> String.to_integer(), + height: parts |> Enum.at(5) |> String.to_integer() } end @@ -43,44 +52,43 @@ defmodule Day3 do def overlap_area(rects) do rects - |> Enum.flat_map(fn rect -> - rects - |> except(rect) - |> Enum.map(fn other -> - Rect.overlap(rect, other) - end) - |> Enum.flat_map(&Rect.points/1) + |> Enum.flat_map(fn rect -> + rects + |> except(rect) + |> Enum.map(fn other -> + Rect.overlap(rect, other) end) - |> Enum.uniq - |> Enum.count + |> Enum.flat_map(&Rect.points/1) + end) + |> Enum.uniq() + |> Enum.count() end def exclude_overlapping(rects) do rects - |> Enum.reject(fn rect -> - rects - |> except(rect) - |> Enum.any?(fn other -> - Rect.overlap(rect, other) != nil - end) + |> Enum.reject(fn rect -> + rects + |> except(rect) + |> Enum.any?(fn other -> + Rect.overlap(rect, other) != nil end) + end) end def parse_input() do File.read!("lib/day3/input.txt") - |> String.split("\n", trim: true) + |> String.split("\n", trim: true) end def part1() do parse_input() - |> Enum.map(&parse_rect/1) - |> overlap_area() + |> Enum.map(&parse_rect/1) + |> overlap_area() end def part2() do parse_input() - |> Enum.map(&parse_rect/1) - |> exclude_overlapping() + |> Enum.map(&parse_rect/1) + |> exclude_overlapping() end - -end \ No newline at end of file +end diff --git a/test/day2_test.exs b/test/day2_test.exs index 7698ed7..f5db59d 100644 --- a/test/day2_test.exs +++ b/test/day2_test.exs @@ -3,7 +3,15 @@ defmodule Day2Test do doctest Day2 test "count characters" do - assert Day2.count_characters("abcdef") == %{"a" => 1, "b" => 1, "c" => 1, "d" => 1, "e" => 1, "f" => 1} + assert Day2.count_characters("abcdef") == %{ + "a" => 1, + "b" => 1, + "c" => 1, + "d" => 1, + "e" => 1, + "f" => 1 + } + assert Day2.count_characters("bababc") == %{"a" => 2, "b" => 3, "c" => 1} assert Day2.count_characters("abbcde") == %{"a" => 1, "b" => 2, "c" => 1, "d" => 1, "e" => 1} end @@ -26,4 +34,4 @@ defmodule Day2Test do list = ["abcde", "fghij", "klmno", "pqrst", "fguij", "axcye", "wvxyz"] assert Day2.correct_boxes(list) == "fgij" end -end \ No newline at end of file +end diff --git a/test/day3_test.exs b/test/day3_test.exs index a060f0d..c16539d 100644 --- a/test/day3_test.exs +++ b/test/day3_test.exs @@ -25,6 +25,7 @@ defmodule Day3Test do %Rect{id: 2, left: 3, top: 1, width: 4, height: 4}, %Rect{id: 3, left: 5, top: 5, width: 2, height: 2} ] + assert Day3.overlap_area(rects) == 4 end @@ -34,9 +35,9 @@ defmodule Day3Test do %Rect{id: 2, left: 3, top: 1, width: 4, height: 4}, %Rect{id: 3, left: 5, top: 5, width: 2, height: 2} ] + res = Day3.exclude_overlapping(rects) assert Enum.count(res) == 1 assert Enum.at(res, 0).id == 3 end - -end \ No newline at end of file +end