This commit is contained in:
Paul-Henri Froidmont 2025-12-10 19:50:04 +01:00
parent d80a8ce32f
commit 327aaf4fd7
Signed by: phfroidmont
GPG key ID: BE948AFD7E7873BE
2 changed files with 570 additions and 37 deletions

View file

@ -20,45 +20,90 @@ def part1(input: String): Long =
((a.x - b.x + 1) * (a.y - b.y + 1)).abs
}.max
enum Edge:
case H(fixedY: Int, range: Range)
case V(fixedX: Int, range: Range)
def contains(x: Int, y: Int): Boolean =
this match
case H(fixedY, range) => fixedY == y && range.contains(x)
case V(fixedX, range) => fixedX == x && range.contains(y)
object Edge:
def apply(a: Point, b: Point): Edge =
if a.y == b.y then Edge.H(a.y, min(a.x, b.x) to max(a.x, b.x))
else if a.x == b.x then Edge.V(a.x, min(a.y, b.y) to max(a.y, b.y))
else ???
case class Polygon(edges: List[Edge]):
val minX = edges.map {
case Edge.H(_, range) => range.min
case Edge.V(fixedX, _) => fixedX
}.min - 1
def contains(p: Point) =
if edges.exists(_.contains(p.x, p.y)) then true
else
// println(p)
val (count, _) = (minX to p.x).foldLeft((0, false)) { case ((count, switched), x) =>
// println(x)
// print("edge contains ")
// println(edges.exists(_.contains(x, p.y)))
// print("switched ")
// println(switched)
if edges.exists(_.contains(x, p.y)) && !switched then (count + 1, true)
else (count, false)
}
// println("count")
// println(count)
count % 2 == 1
case class Point(x: Int, y: Int)
def part2(input: String): Long =
val points = input.split('\n').map { case s"$x,$y" => (x = x.toLong, y = y.toLong) }
val polygon = points
val points = input.split('\n').map { case s"$x,$y" => Point(x.toInt, y.toInt) }
val polygon = Polygon(
(points :+ points.head).sliding(2).map { case Array(a, b) => Edge(a, b) }.toList
)
def corners(ax: Long, ay: Long, bx: Long, by: Long) =
List((ax, ay), (ax, by), (ay, bx), (bx, by))
def corners(a: Point, b: Point) =
List(
Point(min(a.x, b.x), min(a.y, b.y)),
Point(min(a.x, b.x), max(a.y, b.y)),
Point(max(a.x, b.x), min(a.y, b.y)),
Point(max(a.x, b.x), max(a.y, b.y))
).distinct
def isInside(x: Long, y: Long) =
val counter = polygon.sliding(2).foldLeft(0) { case (counter, Array(a, b)) =>
if y > min(a.y, b.y) && y <= max(a.y, b.y) && x <= max(a.x, b.x) then
val xinters = (y - a.y) * (b.x - a.x) / (b.y - a.y) + a.x
counter + (if a.x == b.x || x <= xinters then 1 else 0)
else counter
}
counter % 2 == 1
// println(polygon.contains(Point(9, 3)))
println(isInside(7, 1))
// println(polygon.edges.mkString("\n"))
println(isInside(7, 2))
println(isInside(0, 0))
// println(polygon.edges.exists(_.contains(9, 3)))
// println(polygon.edges.exists(_.contains(9, 5)))
// println(polygon.contains(Point(11, 1)))
// println(polygon.contains(Point(11, 7)))
// println(polygon.contains(Point(11, 8)))
// println(polygon.contains(Point(11, 9)))
// corners(Point(9, 5), Point(2, 3)).foreach(p =>
// println(p)
// println(polygon.contains(p))
// )
println(
points
.combinations(2)
.map { case Array(a, b) =>
corners(a, b)
}.distinct.size
)
points
.combinations(2)
.collect {
case Array(a, b) if a != b && corners(a.x, a.y, b.x, b.y).forall((x, y) => isInside(x, y)) =>
println(corners(a.x, a.y, b.x, b.y))
case Array(a, b) if a != b && corners(a, b).forall(polygon.contains) =>
println(corners(a, b))
(a, b)
}
.map((a, b) => ((a.x - b.x + 1) * (a.y - b.y + 1)).abs)
.max
// if (p.y > MIN(p1.y,p2.y)) {
// if (p.y <= MAX(p1.y,p2.y)) {
// if (p.x <= MAX(p1.x,p2.x)) {
// if (p1.y != p2.y) {
// xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
// if (p1.x == p2.x || p.x <= xinters)
// counter++;
// }
// }
// }
// }
end part2