Public
Edited
Dec 5, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
lines = input.split("\n\n")
Insert cell
Insert cell
seeds = lines[0].split(":")[1].match(/\d+/g).map(Number)
Insert cell
Insert cell
_maps = lines.slice(1).map((line) =>
_.sortBy(
line
.split("\n")
.slice(1)
.map((x) => x.match(/\d+/g).map(Number)),
(d) => d[1]
)
)
Insert cell
Insert cell
maps = _maps.map((entries) => (n) => {
for (const [dest, src, length] of entries)
if (src <= n && n < src + length) return dest + n - src;
return n;
})
Insert cell
Insert cell
Insert cell
locations = seeds.map((seed) => maps.reduce((acc, curr) => curr(acc), seed))
Insert cell
Insert cell
part1 = _.min(locations)
Insert cell
Insert cell
Insert cell
Insert cell
function findIntersection(a1, a2, b1, b2) {
let start = Math.max(a1, b1);
let end = Math.min(a2, b2);
if (start <= end) {
return [start, end];
}
return null;
}
Insert cell
Insert cell
intervalMaps = _maps.map((entries) => (intervals) => {
let newIntervals = [];
for (const [intervalStart, intervalEnd] of intervals) {
let pointer = intervalStart;
for (const [dest, srcStart, length] of entries) {
const srcEnd = srcStart + length - 1;
const intersection = findIntersection(
intervalStart,
intervalEnd,
srcStart,
srcEnd
);

if (intersection) {
const [intersectStart, intersectEnd] = intersection;
// This is the intersection
newIntervals.push([
dest + (intersectStart - srcStart),
dest + (intersectEnd - srcStart)
]);
if (intersectStart > pointer) {
// The left side is not mapped
newIntervals.push([pointer, intersectStart]);
}
// Update the left pointer
pointer = intersectEnd + 1;
}
}
if (pointer < intervalEnd) {
// The right side is not mapped
newIntervals.push([pointer, intervalEnd]);
}
}
return newIntervals;
})
Insert cell
Insert cell
seedIntervals = _.chunk(seeds, 2).map(([start, length]) => [
start,
start + length - 1
])
Insert cell
Insert cell
locationIntervals = intervalMaps.reduce((acc, curr) => curr(acc), seedIntervals)
Insert cell
Insert cell
part2 = _.min(locationIntervals.map(([start, length]) => start))
Insert cell
Insert cell
Insert cell
Insert cell
import { worker, workertext } from "@fil/worker"
Insert cell
balancedIntervals = seedIntervals.flatMap(([start, length]) => {
const result = [];
const maxLength = 1000000000;
while (length > maxLength) {
result.push([start, maxLength]);
start += maxLength;
length -= maxLength;
}
if (length > 0) {
result.push([start, length]);
}
return result;
})
Insert cell
findMin(balancedIntervals)
Insert cell
function findMin(intervals) {
return new Promise((resolve, reject) => {
let completed = 0;
let minValues = [];

for (let i = 0; i < intervals.length; i++) {
const b = new Blob([workertext(fn)], { type: "text/javascript" });
const url = URL.createObjectURL(b);
const worker = new Worker(url);
worker.addEventListener("message", (e) => {
console.log("finished", completed, e);
minValues.push(e.data);
completed++;
worker.terminate();
URL.revokeObjectURL(url);

if (completed === intervals.length) {
resolve(minValues);
}
});

worker.onerror = (e) => {
worker.terminate();
URL.revokeObjectURL(url);
reject(e);
};
worker.postMessage({
seedStart: intervals[i][0],
seedEnd: intervals[i][1],
_maps: _maps
});
}
});
}
Insert cell
function fn(args) {
const { seedStart, seedEnd, _maps } = args;
const maps = _maps.map((entries) => (n) => {
for (const [dest, src, length] of entries)
if (src <= n && n < src + length) return dest + n - src;
return n;
});
let min = Number.POSITIVE_INFINITY;

for (let seed = seedStart; seed <= seedEnd; seed++) {
let val = seed;
for (const map of maps) {
val = map(val);
}
min = Math.min(val, min);
}
return min;
}
Insert cell
Insert cell
input = textarea || select.value
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more