|
1 | | -import { parseReports } from "../../reports.ts"; |
2 | 1 | import calculateManhattanDistance from "@lib/calculateManhattanDistance.ts"; |
3 | | - |
4 | | -class Interval { |
5 | | - static of(value: number) { |
6 | | - return new Interval(value, value); |
7 | | - } |
8 | | - |
9 | | - readonly #lower: number; |
10 | | - readonly #upper: number; |
11 | | - |
12 | | - constructor(lower: number, upper: number) { |
13 | | - if (lower > upper) throw new RangeError("upper cannot be less than lower"); |
14 | | - this.#lower = lower; |
15 | | - this.#upper = upper; |
16 | | - } |
17 | | - |
18 | | - get lower() { |
19 | | - return this.#lower; |
20 | | - } |
21 | | - |
22 | | - get upper() { |
23 | | - return this.#upper; |
24 | | - } |
25 | | - |
26 | | - get length() { |
27 | | - return this.#upper - this.#lower + 1; |
28 | | - } |
29 | | - |
30 | | - gapTo(other: Interval) { |
31 | | - if (this.#upper < other.#lower) return other.#lower - this.#upper - 1; |
32 | | - if (other.#upper < this.#lower) return other.#upper - this.#lower + 1; |
33 | | - return 0; |
34 | | - } |
35 | | -} |
36 | | - |
37 | | -class IntervalSet { |
38 | | - #intervals: Interval[] = []; |
39 | | - |
40 | | - constructor(entries?: Iterable<Interval>) { |
41 | | - if (entries) { for (const interval of entries) this.add(interval); } |
42 | | - } |
43 | | - |
44 | | - get size() { |
45 | | - return this.#intervals.reduce((sum, interval) => sum + interval.length, 0); |
46 | | - } |
47 | | - |
48 | | - [Symbol.iterator]() { |
49 | | - return this.#intervals[Symbol.iterator](); |
50 | | - } |
51 | | - |
52 | | - #compareIntervalsTo(other: Interval) { |
53 | | - const { [-1]: lower = [], [0]: contiguous = [], [1]: upper = [] } = Object |
54 | | - .groupBy(this.#intervals, (interval) => Math.sign(other.gapTo(interval))); |
55 | | - return { lower, contiguous, upper }; |
56 | | - } |
57 | | - |
58 | | - add(interval: Interval) { |
59 | | - const { lower, contiguous, upper } = this.#compareIntervalsTo(interval); |
60 | | - if (contiguous.length === 0) { |
61 | | - this.#intervals = [...lower, interval, ...upper]; |
62 | | - return; |
63 | | - } |
64 | | - const mergedInterval = new Interval( |
65 | | - Math.min(interval.lower, contiguous[0].lower), |
66 | | - Math.max(interval.upper, contiguous[contiguous.length - 1].upper), |
67 | | - ); |
68 | | - this.#intervals = [...lower, mergedInterval, ...upper]; |
69 | | - } |
70 | | - |
71 | | - delete(interval: Interval) { |
72 | | - const { lower, contiguous, upper } = this.#compareIntervalsTo(interval); |
73 | | - if (contiguous.length === 0) return; |
74 | | - const newIntervals: Interval[] = []; |
75 | | - const first = contiguous[0]; |
76 | | - if (first.lower < interval.lower) { |
77 | | - newIntervals.push(new Interval(first.lower, interval.lower - 1)); |
78 | | - } |
79 | | - const last = contiguous[contiguous.length - 1]; |
80 | | - if (last.upper > interval.upper) { |
81 | | - newIntervals.push(new Interval(interval.upper + 1, last.upper)); |
82 | | - } |
83 | | - this.#intervals = [...lower, ...newIntervals, ...upper]; |
84 | | - } |
85 | | - |
86 | | - difference(other: IntervalSet) { |
87 | | - const result = new IntervalSet(); |
88 | | - result.#intervals = [...this.#intervals]; |
89 | | - for (const interval of other) result.delete(interval); |
90 | | - return result; |
91 | | - } |
92 | | - |
93 | | - union(other: IntervalSet) { |
94 | | - const result = new IntervalSet(); |
95 | | - result.#intervals = [...this.#intervals]; |
96 | | - for (const interval of other) result.add(interval); |
97 | | - return result; |
98 | | - } |
99 | | -} |
| 2 | +import Interval from "@lib/Interval.ts"; |
| 3 | +import IntervalSet from "@lib/IntervalSet.ts"; |
| 4 | +import { parseReports } from "../../reports.ts"; |
100 | 5 |
|
101 | 6 | export default function solve(input: string, { y = 2000000 } = {}) { |
102 | 7 | let intervalSet = new IntervalSet(); |
|
0 commit comments