Public
Edited
Feb 27, 2023
Insert cell
Insert cell
Insert cell
in18b = "2,2,2|1,2,2|3,2,2|2,1,2|2,3,2|2,2,1|2,2,3|2,2,4|2,2,6|1,2,5|3,2,5|2,1,5|2,3,5"
Insert cell
cubes = new Set(in18.split("|"))
Insert cell
lava = [...cubes].map(pos)
Insert cell
adjacents
.reduce((a,b) => a+b.length, 0)
Insert cell
SCOPE = lava.reduce(({xmin, xmax, ymin, ymax, zmin, zmax}, [a,b,c]) => ({ xmin: Math.min(xmin, a), ymin: Math.min(ymin, b), zmin: Math.min(zmin, c), xmax: Math.max(xmax, a), ymax: Math.max(ymax, b), zmax: Math.max(zmax, c) }), { xmin: 16, xmax: 16, ymin: 8, ymax: 8, zmin: 5, zmax: 5 })
Insert cell
adjacents = lava
.map(([a,b,c]) => [[a+1,b,c],[a-1,b,c],[a,b+1,c],[a,b-1,c],[a,b,c+1],[a,b,c-1]])
.map(sides => sides.filter((p) => !cubes.has(str(p))))
Insert cell
function str([x,y,z]) {
return `${x},${y},${z}`;
}
Insert cell
function pos(s) {
return s.split(",").map(i => parseInt(i));
}
Insert cell
Insert cell
exteriors = {
const interior = new Set();
const exterior = new Set();
const points = [].concat(...adjacents)
// const points = [[15,4,15]]
points.forEach(p => investigate(interior, exterior, p, new Set(), 100));
return {interior, exterior, remaining: points.map(str).filter(s => !interior.has(s) && !exterior.has(s)), surface: points.map(str).filter(s => interior.has(s))}
}
Insert cell
[...exteriors.interior].map(pos)
.map(([a,b,c]) => [[a+1,b,c],[a-1,b,c],[a,b+1,c],[a,b-1,c],[a,b,c+1],[a,b,c-1]])
.map(sides => sides.filter((p) => exteriors.exterior.has(str(p))))
.filter(l => l.length > 0)
.map(sides => sides.map(str))
Insert cell
[...exteriors.exterior].map(pos)
.map(([a,b,c]) => [[a+1,b,c],[a-1,b,c],[a,b+1,c],[a,b-1,c],[a,b,c+1],[a,b,c-1]])
.map(sides => sides.filter((p) => exteriors.interior.has(str(p))))
.filter(l => l.length > 0)
.map(sides => sides.map(str))
Insert cell
function investigate(interior, exterior, [a,b,c], avoid, step) {
let abcstr = str([a,b,c]);
if (interior.has(abcstr) || exterior.has(abcstr)) {
return;
}
let adj = [[a+1,b,c],[a-1,b,c],[a,b+1,c],[a,b-1,c],[a,b,c+1],[a,b,c-1]]
.map(str)
.filter(l => !avoid.has(l))
.filter(l => !cubes.has(l))
.map(pos);

if (adj.length === 0) {
interior.add(abcstr);
return;
}
for (let [i,j,k] of adj) {
let s = str([i,j,k]);
if (interior.has(s)) {
interior.add(abcstr);
return;
} else if (exterior.has(s)) {
exterior.add(abcstr);
return;
} else if (i < SCOPE.xmin || i > SCOPE.xmax || j < SCOPE.ymin || j > SCOPE.ymax || k < SCOPE.zmin || k > SCOPE.zmax) {
exterior.add(s);
exterior.add(abcstr);
return;
}
}

let w = "";
if (avoid.size < step) {
for (let [i,j,k] of adj) {
let s = str([i,j,k]);
investigate(interior, exterior, [i,j,k], new Set([...avoid, abcstr]), step);
if (exterior.has(s)) {
w = "ext";
break;
} else if (interior.has(s)) {
w = "int";
}
}
if (w === "ext") {
for (let pp of adj) {
interior.delete(str(pp));
exterior.add(str(pp));
}
exterior.add(abcstr);
return;
} else if (w === "int") {
for (let pp of adj) {
interior.add(str(pp));
}
interior.add(abcstr);
return;
}
}
}
Insert cell
Insert cell
Insert cell
blueprints = in19.split("|").map(bp => bp.split(": Each ore robot costs "))
.map(([a,b]) => [parseInt(a.split("Blueprint ")[1]), ...b.split(" ore. Each clay robot costs ").map(l => l.split(" ore. Each obsidian robot costs "))])
.map(([a,[b], [c,d]]) => [a, parseInt(b), parseInt(c), ...d.split(" clay. Each geode robot costs ")])
.map(([a, b, c, d, e]) => [a,b,c,d.split(" ore and "), e.split(" obsidian.")[0].split(" ore and ")])
.map(([a, b, c, [d, e], [f, g]]) => [a, b, c, parseInt(d), parseInt(e), parseInt(f), parseInt(g)])
Insert cell
function collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, robot_turn) {
if (robot_turn < 0) {
// Simulation
let a0 = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, 0);
let a1 = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, 1);
let a2 = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, 2);
let a3 = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, 3);
// let a4 = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, collection, robots, 4);

// Pick best
let top = [a0, a1, a2, a3].sort(([p,c,r,d], [p1,c1,r1,d1]) => {
if (c1.geo > c.geo) return 1;
if (c1.geo < c.geo) return -1;
if (r1.geo > r.geo) return 1;
if (r1.geo < r.geo) return -1;
if (c1.obs > c.obs) return 1;
if (c1.obs < c.obs) return -1;
if (r1.obs > r.obs) return 1;
if (r1.obs < r.obs) return -1;
if (c1.clay > c.clay) return 1;
if (c1.clay < c.clay) return -1;
if (r1.clay > r.clay) return 1;
if (r1.clay < r.clay) return -1;
if (c1.ore > c.ore) return 1;
if (c1.ore < c.ore) return -1;
else return 0
});
return top[0];
}
let col = { ...collection };
let rob = { ...robots };

// Produce
while (duration > 0 && !canCreate([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], col, robot_turn)) {
duration--;
col.ore += robots.ore;
col.clay += robots.clay;
col.obs += robots.obs;
col.geo += robots.geo;
}
if (duration === 0) {
// return `END ${rob.ore}/${rob.clay}/${rob.obs}/${rob.geo} | ${col.ore}/${col.clay}/${col.obs}/${col.geo} | ${duration}`;
return [[robot_turn], col, rob, 0];
}

// Create robot
duration--;
[rob, col] = consume([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], rob, col, robot_turn);
col.ore += robots.ore;
col.clay += robots.clay;
col.obs += robots.obs;
col.geo += robots.geo;
if (duration === 0) {
// return `END ${rob.ore}/${rob.clay}/${rob.obs}/${rob.geo} | ${col.ore}/${col.clay}/${col.obs}/${col.geo} | ${duration}`;
return [[robot_turn], col, rob, 0];
}
let [sim_path, sim_col, sim_rob, sim_dur] = collect([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], duration, col, rob, -1);
return [[robot_turn, ...sim_path], sim_col, sim_rob, sim_dur];
}
Insert cell
function canCreate([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], col, robot_turn) {
if (robot_turn === 0) {
return col.ore >= ore;
} else if (robot_turn === 1) {
return col.ore >= clay;
} else if (robot_turn === 2) {
return col.ore >= ob_ore && col.clay >= ob_clay;
} else if (robot_turn === 3) {
return col.ore >= geo_ore && col.obs >= geo_obs;
} else {
return false;
}
}
Insert cell
function consume([bp, ore, clay, ob_ore, ob_clay, geo_ore, geo_obs], robots, collection, robot_turn) {
let col = { ...collection };
let rob = { ...robots };
if (robot_turn === 0) {
col.ore -= ore;
rob.ore++;
} else if (robot_turn === 1) {
col.ore -= clay;
rob.clay++;
} else if (robot_turn === 2) {
col.ore -= ob_ore;
col.clay -= ob_clay;
rob.obs++;
} else if (robot_turn === 3) {
col.ore -= geo_ore;
col.obs -= geo_obs;
rob.geo++;
}
return [rob, col]
}
Insert cell
[collect([1, 4, 2, 3, 14, 2, 7], DURATION, COLLECTION, FIRST_ROBOTS, TURN), collect([2, 2, 3, 3, 8, 3, 12], DURATION, COLLECTION, FIRST_ROBOTS, TURN)].map(([path, col, rob, duration]) => `[${path}] rob: ${rob.ore}/${rob.clay}/${rob.obs}/${rob.geo} | col: ${col.ore}/${col.clay}/${col.obs}/${col.geo} | ${duration}`)
Insert cell
best = blueprints.map(bp => [bp[0], ...collect(bp, DURATION, COLLECTION, FIRST_ROBOTS, TURN)])
Insert cell
best.map(([a,b,c]) => a * c.geo).reduce((a,b) => a+b, 0)
Insert cell
best.slice(0, 3).map(([bp, p, c, r]) => collect(blueprints[bp-1], 8, c, r, -1))
Insert cell
[FIRST_NEXT, SECOND_NEXT, THIRD_NEXT].map(([path, col, rob, duration]) => `[${path}] rob: ${rob.ore}/${rob.clay}/${rob.obs}/${rob.geo} | col: ${col.ore}/${col.clay}/${col.obs}/${col.geo} | ${duration}`)
Insert cell
RUN_1 = 20
Insert cell
RUN_2 = 20
Insert cell
RUN_3 = 20
Insert cell
MAX_RUN = 25
Insert cell
FIRST = collect(blueprints[0], RUN_1, COLLECTION, FIRST_ROBOTS, -1)
Insert cell
FIRST_NEXT = collect(blueprints[0], MAX_RUN - RUN_1, FIRST[1], FIRST[2], -1)
Insert cell
SECOND = collect(blueprints[1], RUN_2, COLLECTION, FIRST_ROBOTS, -1)
Insert cell
SECOND_NEXT = collect(blueprints[1], MAX_RUN - RUN_2, SECOND[1], SECOND[2], -1)
Insert cell
THIRD = collect(blueprints[2], RUN_3, COLLECTION, FIRST_ROBOTS, -1)
Insert cell
THIRD_NEXT = collect(blueprints[2], MAX_RUN - RUN_3, THIRD[1], THIRD[2], -1)
Insert cell
DURATION = 2
Insert cell
COLLECTION = ({ ore: 0, clay: 0, obs: 0, geo: 0 })
Insert cell
FIRST_ROBOTS = ({ ore: 1, clay: 0, obs: 0, geo: 0 })
Insert cell
TURN = -1
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