@@ -7,32 +7,20 @@ open Std (HashMap)
7
7
8
8
-- Part 1
9
9
10
- private def groupByChar (decoratedChars : List (Point × Char)) : List (Char × List Point) :=
11
- decoratedChars.groupBy (λ (_, c1) (_, c2) => c1 == c2) |>.map (λ l => (l.head!.2 , l.map (·.1 )))
10
+ private def removeDots (decoratedChars : List PointAndChar) : List PointAndChar := decoratedChars.filter (·.char != '.' )
12
11
13
- #guard groupByChar [(⟨0 , 0 ⟩, 'a' ), (⟨1 , 0 ⟩, 'a' ), (⟨0 , 1 ⟩, 'b' ), (⟨1 , 1 ⟩, 'b' )] == [
14
- ('a' , [⟨0 , 0 ⟩, ⟨1 , 0 ⟩]),
15
- ('b' , [⟨0 , 1 ⟩, ⟨1 , 1 ⟩])
16
- ]
17
-
18
- private instance hashableChar : Hashable Char where hash c := c.toNat |> hash
19
-
20
- private def removeDots (decoratedChars : List (Point × Char)) : List (Point × Char) :=
21
- decoratedChars.filter (λ (_, c) => c != '.' )
12
+ private def getAntennaeGroups (input : PuzzleInput) : List (List Point) :=
13
+ input.decoratedChars |> removeDots |>.groupByAndTransformValues (·.char) (·.point) |>.values
22
14
23
15
private def findAntinodes (antennaGroup : List Point) : List Point := do
24
16
let antenna1 <- antennaGroup
25
17
let antenna2 <- antennaGroup
26
18
if antenna1 != antenna2 then
27
19
return antenna2.add (antenna1.vectorTo antenna2)
28
- else
29
- []
30
-
31
- private def getAntennaeGroups (input : PuzzleInput) : List (List Point) :=
32
- input.decoratedChars |> removeDots |>.toArray.groupByKey (·.2 ) |>.map (λ _ v => v.map (·.1 ) |>.toList) |>.values
20
+ []
33
21
34
22
private def solvePart1 (input : PuzzleInput) : Int :=
35
- getAntennaeGroups input |>.bind findAntinodes |>.filter (input.bounds.contains) |>.toSet.size
23
+ getAntennaeGroups input |>.flatMap findAntinodes |>.filter (input.bounds.contains) |>.toSet.size
36
24
37
25
def parseAndSolvePart1 (s : String): Int := parseInput s |> solvePart1
38
26
@@ -44,15 +32,15 @@ private def combinationPairs [BEq α] (xs : List α) : List (α × α) := do
44
32
let [x1, x2] <- xs.combinations 2 | []
45
33
return (x1, x2)
46
34
47
- private def isInLineWith (pair : ( Point × Point)) (point : Point) : Bool :=
35
+ private def Point.isColinearWith (point : Point) (pair : ( Point × Point) ) : Bool :=
48
36
let (p1, p2) := pair
49
37
let v1 := p1.vectorTo p2
50
38
let v2 := p1.vectorTo point
51
39
v1.x * v2.y == v1.y * v2.x
52
40
53
41
private def solvePart2 (input : PuzzleInput) : Int :=
54
- let antennaePairs := getAntennaeGroups input |>.bind combinationPairs
55
- let isAntinode (point : Point) : Bool := antennaePairs.any (λ pair => isInLineWith pair point)
42
+ let antennaePairs := getAntennaeGroups input |>.flatMap combinationPairs
43
+ let isAntinode (point : Point) : Bool := antennaePairs.any point.isColinearWith -- exploiting special property of the input
56
44
input.bounds.allPoints.countP isAntinode
57
45
58
46
def parseAndSolvePart2 (s : String): Int := parseInput s |> solvePart2
0 commit comments