| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- // Run this by pasting it into the browser window of the URL "https://adventofcode.com/2025/day/9/input"
- // It is very slow, takeing multiple seconds
- {
- const response = await fetch(window.location.href)
- const input = await response.text()
- // const input = "7,1\n11,1\n11,7\n9,7\n9,5\n2,5\n2,3\n7,3"
- const points = []
- for (const line of input.split("\n")) {
- const [x, y] = line.split(",")
- if (x) {
- const point = [parseInt(x), parseInt(y)]
- points.push(point)
- }
- }
-
- let parity = 0
- {
- let p1 = points[points.length-2]
- let p2 = points[points.length-1]
- for (let i = 0; i < points.length; i++) {
- const p3 = points[i]
- if (p1[0] === p2[0] && p2[1] == p3[1]) {
- parity = parity - Math.sign((p2[1] - p1[1]) * (p3[0] - p2[0]))
- } else if (p1[1] === p2[1] && p2[0] == p3[0]) {
- parity = parity + Math.sign((p2[0] - p1[0]) * (p3[1] - p2[1]))
- }
- p1 = p2
- p2 = p3
- }
- }
- let rightIsInside = parity > 0;
- console.log(rightIsInside ? "Right is inside" : "Left is inside")
-
- let squares = []
- for (const [i, p1] of points.entries()) {
- for (let j = 0; j < i; j++) {
- const p2 = points[j]
- const size = (Math.abs(p1[0] - p2[0]) + 1) * (Math.abs(p1[1] - p2[1]) + 1)
- squares.push([size, p1, p2])
- }
- }
-
- squares.sort(([s1], [s2]) => s2 - s1)
- console.log("Answer part 1:", squares[0][0])
- function cornersToRange(c1, c2) {
- return square = [
- [Math.min(c1[0], c2[0]), Math.min(c1[1], c2[1])],
- [Math.max(c1[0], c2[0]), Math.max(c1[1], c2[1])]
- ]
- }
-
- function lineToVerticalRange(p1, p2) {
- if (p1[1] == p2[1]) {
- const lineParity = Math.sign(p2[0] - p1[0]) * parity
- return [
- [Math.min(p1[0], p2[0]), lineParity > 0 ? p1[1] : - Infinity],
- [Math.max(p1[0], p2[0]), lineParity > 0 ? Infinity : p1[1]]
- ]
- }
- return null
- }
- function intersect([lb1, ub1], [lb2, ub2]) {
- const intersection = [
- [Math.max(lb1[0], lb2[0]), Math.min(ub1[0], ub2[0])],
- [Math.max(lb1[1], lb2[1]), Math.min(ub1[1], ub2[1])]
- ]
- if (intersection[0][0] > intersection[1][0] || intersection[0][1] > intersection[1][1]) {
- return null
- }
- }
- function combineVerticalRange([lb1, ub1], [lb2, ub2]) {
- if (ub1[1] <= lb2[1] || ub2[1] <= lb1[1] || (ub1[1] > ub2[1] && lb1[1] < lb2[1]) || (ub2[1] > ub1[1] && lb2[1] < lb1[1])) {
- return [[[lb1, ub1]], [[lb2, ub2]], []]
- }
- const x1 = Math.max(lb1[0], lb2[0])
- const x2 = Math.min(ub1[0], ub2[0])
- if (x2 <= x1) {
- return [[[lb1, ub1]], [[lb2, ub2]], []]
- }
- const split1 = []
- const split2 = []
- const union = []
- if (lb1[0] < lb2[0]) {
- split1.push([
- [lb1[0], lb1[1]],
- [lb2[0], ub1[1]]
- ])
- } else if (lb2[0] < lb1[0]) {
- split2.push([
- [lb2[0], lb2[1]],
- [lb1[0], ub2[1]]
- ])
- }
- if (ub2[0] > ub1[0]) {
- split2.push([
- [ub1[0], lb2[1]],
- [ub2[0], ub2[1]]
- ])
- } else if (ub1[0] > ub2[0]) {
- split1.push([
- [ub2[0], lb1[1]],
- [ub1[0], ub1[1]]
- ])
- }
- if (lb1[1] < lb2[1]) {
- if (lb1[1] > -Infinity) {
- split1.push([
- [x1, lb1[1]],
- [x2, lb2[1]]
- ])
- }
- } else if (lb2[1] < lb1[1]) {
- if (lb2[1] > -Infinity) {
- split2.push([
- [x1, lb2[1]],
- [x2, lb1[1]]
- ])
- }
- }
- const y1 = Math.max(lb1[1], lb2[1])
- if (ub2[1] > ub1[1]) {
- if (ub2[1] < Infinity) {
- split2.push([
- [x1, ub1[1]],
- [x2, ub2[1]]
- ])
- }
- } else if (ub1[1] > ub2[1]) {
- if (ub1[1] < Infinity) {
- split1.push([
- [x1, ub2[1]],
- [x2, ub1[1]]
- ])
- }
- }
- const y2 = Math.min(ub1[1], ub2[1])
- union.push([
- [x1, y1],
- [x2, y2]
- ])
- return [split1, split2, union]
- }
-
- function splitByYBound([lb, ub], [lyb, uyb]) {
- if (lyb > ub[1] || uyb < lb[1]) {
- return [[[lb, ub]], null]
- }
- const outside = []
- if (lb[1] < lyb) {
- outside.push([
- [lb[0], lb[1]],
- [ub[0], lyb - 1]
- ])
- }
- if (ub[1] > uyb) {
- outside.push([
- [lb[0], uyb + 1],
- [ub[0], ub[1]]
- ])
- }
- const inside = [
- [lb[0], Math.max(lb[1], lyb)],
- [ub[0], Math.min(ub[1], uyb)]
- ]
- return [outside, inside]
- }
-
- function splitByXBound([lb, ub], [lxb, uxb]) {
- if (lxb > ub[0] || uxb < lb[0]) {
- return [[[lb, ub]], null]
- }
- const outside = []
- if (lb[0] < lxb) {
- outside.push([
- [lb[0], lb[1]],
- [lxb - 1, ub[1]]
- ])
- }
- if (ub[0] > uxb) {
- outside.push([
- [uxb + 1, lb[1]],
- [ub[0], ub[1]]
- ])
- }
- const inside = [
- [Math.max(lb[0], lxb), lb[1]],
- [Math.min(ub[0], uxb), ub[1]]
- ]
- return [outside, inside]
-
- }
-
- function subtractRange([lb1, ub1], [lb2, ub2]) {
- const [outsideY, insideY] = splitByYBound([lb1, ub1], [lb2[1], ub2[1]])
- if (insideY) {
- const [outsideX, _] = splitByXBound(insideY, [lb2[0], ub2[0]])
- outsideY.push(...outsideX)
- }
- return outsideY
- }
-
- function combineLists(ranges1, ranges2) {
- for (let i = 0; i < ranges1.length; i++) {
- for (let j = 0; j < ranges2.length; j++) {
- const range1 = ranges1[i]
- const range2 = ranges2[j]
- if (!range1) {
- break
- }
- if (range2) {
- const [split1, split2, union] = combineVerticalRange(range1, range2)
- split1.push(...union)
- ranges1[i] = split1.pop()
- ranges2[j] = split2.pop()
- ranges1.push(...split1)
- ranges2.push(...split2)
- }
- }
- }
- ranges1.push(...ranges2)
- return ranges1.filter((x) => !!x)
- }
-
- function subtractLists(ranges1, ranges2) {
- for (let j = 0; j < ranges2.length; j++) {
- const range2 = ranges2[j]
- for (let i = 0; i < ranges1.length; i++) {
- const range1 = ranges1[i]
- if (!range1) {
- break
- }
- if (range2) {
- const res = subtractRange(range1, range2)
- ranges1[i] = res.pop()
- ranges1.push(...res)
- }
- }
- }
- return ranges1.filter((x) => !!x)
- }
- let ranges = []
- let p1 = points[points.length-1]
- for (let i = 0; i < points.length; i++) {
- const p2 = points[i]
- const range = lineToVerticalRange(p1, p2)
- if (range) {
- ranges = combineLists(ranges, [range])
- }
- p1 = p2
- }
- for (const [s, c1, c2] of squares) {
- const empty = subtractLists([cornersToRange(c1, c2)], ranges)
- if (empty.length == 0) {
- console.log("Answer part 2:", s)
- break
- }
- }
- }
|