this repo has no description
1<!-- vim:set ft=markdown: -->
2
3<!-- livebook:{"persist_outputs":true} -->
4
5# Day 5
6
7```elixir
8defmodule Day5 do
9 defmodule Point do
10 defstruct [:x, :y]
11
12 def parse(input) do
13 [x, y] = String.split(input, ",")
14
15 %__MODULE__{x: String.to_integer(x), y: String.to_integer(y)}
16 end
17 end
18
19 defmodule Line do
20 defstruct [:start, :finish]
21
22 def new(a, b) do
23 {start, finish} =
24 cond do
25 a.x < b.x -> {a, b}
26 a.y < b.y -> {a, b}
27 true -> {b, a}
28 end
29
30 %__MODULE__{start: start, finish: finish}
31 end
32
33 def horizontal?(a), do: a.start.y == a.finish.y
34 def vertical?(a), do: a.start.x == a.finish.x
35
36 def points(a) do
37 case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do
38 {0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y}
39 {dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y}
40 {dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy)
41 end
42 end
43
44 def orientation(a) do
45 cond do
46 horizontal?(a) -> :horizontal
47 vertical?(a) -> :vertical
48 true -> :diagonal
49 end
50 end
51
52 defp sign(0), do: 0
53 defp sign(x) when x < 0, do: -1
54 defp sign(x) when x > 0, do: 1
55 end
56end
57
58lines =
59 File.stream!("day5.txt")
60 |> Stream.map(&String.trim/1)
61 |> Stream.map(fn input ->
62 [a, b] = String.split(input, " -> ")
63
64 pa = Day5.Point.parse(a)
65 pb = Day5.Point.parse(b)
66
67 Day5.Line.new(pa, pb)
68 end)
69```
70
71```output
72#Stream<[
73 enum: %File.Stream{
74 line_or_bytes: :line,
75 modes: [:raw, :read_ahead, :binary],
76 path: "day5.txt",
77 raw: true
78 },
79 funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>]
80]>
81```
82
83## Task 1
84
85```elixir
86lines
87|> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal))
88|> Stream.flat_map(&Day5.Line.points/1)
89|> Enum.frequencies()
90|> Enum.count(fn {_k, v} -> v > 1 end)
91```
92
93```output
945197
95```
96
97## Task 2
98
99```elixir
100lines
101|> Stream.flat_map(&Day5.Line.points/1)
102|> Enum.frequencies()
103|> Enum.count(fn {_k, v} -> v > 1 end)
104```
105
106```output
10718605
108```