@@ -31,6 +31,8 @@ object Day9 {
3131 _ => true
3232 }
3333
34+ trait Part2Solution extends Part
35+
3436 // Copied & modified from 2018 day 11
3537 class ArrayPartialSumGrid (f : Pos => Int , box : Box ) extends SumGrid {
3638 val Box (min, max) = box
@@ -56,7 +58,11 @@ object Day9 {
5658 }
5759 }
5860
59- object Part2 extends Part {
61+ /**
62+ * Solution, which compresses the grid to 2-unit distances between occurring coordinates
63+ * and checks validity by counting outside cells (in the compressed grid) using a [[SumGrid ]].
64+ */
65+ object CompressGridPart2Solution extends Part2Solution {
6066 def makeCompressPos (redTiles : Seq [Pos ]): Pos => Pos = {
6167 val xs = redTiles.map(_.x).distinct.sorted
6268 val ys = redTiles.map(_.y).distinct.sorted
@@ -105,9 +111,31 @@ object Day9 {
105111 }
106112 }
107113
114+ /**
115+ * Solution, which checks validity geometrically using axis-aligned line-box intersection.
116+ */
117+ object IntersectionPart2Solution extends Part2Solution {
118+ override def makeIsValid (redTiles : Seq [Pos ]): Box => Boolean = {
119+ val lines =
120+ (redTiles lazyZip redTiles.rotateLeft(1 ))
121+ .toSeq
122+ .map((p1, p2) => Box .bounding(Seq (p1, p2))) // convert line to box of width/height 1
123+
124+ def isValid (box : Box ): Boolean = {
125+ // construct box interior, otherwise box intersects with its own edges
126+ val innerMin = box.min + Pos (1 , 1 )
127+ val innerMax = box.max - Pos (1 , 1 )
128+ // innerMin <= innerMax &&
129+ ! (innerMin <= innerMax) || // box has no/empty interior // TODO: this is wrong for line-line intersections
130+ ! lines.exists(_.intersect(Box (innerMin, innerMax)).nonEmpty) // interior doesn't intersect any line
131+ }
132+
133+ isValid
134+ }
135+ }
136+
108137 // TODO: line of sight in all directions solution (single iteration over corners, not all pairs!)
109138 // TODO: glguy's solution
110- // TODO: polygon-based solution?
111139
112140 def parseRedTile (s : String ): Pos = s match {
113141 case s " $x, $y" => Pos (x.toInt, y.toInt)
@@ -119,6 +147,6 @@ object Day9 {
119147
120148 def main (args : Array [String ]): Unit = {
121149 println(Part1 .largestArea(parseRedTiles(input)))
122- println(Part2 .largestArea(parseRedTiles(input)))
150+ println(CompressGridPart2Solution .largestArea(parseRedTiles(input)))
123151 }
124152}
0 commit comments