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