119 lines
3.2 KiB
JavaScript
119 lines
3.2 KiB
JavaScript
const fs = require('fs/promises');
|
|
|
|
const sum = (arr) => arr.reduce((total, num) => total+num);
|
|
const arrayOfLength = n => Array.from(Array(n).keys()).map(() => {});
|
|
//minus
|
|
const keypress = async () => {
|
|
process.stdin.setRawMode(true)
|
|
return new Promise(resolve => process.stdin.once('data', data => {
|
|
const byteArray = [...data]
|
|
if (byteArray.length > 0 && byteArray[0] === 3) {
|
|
console.log('^C')
|
|
process.exit(1)
|
|
}
|
|
process.stdin.setRawMode(false)
|
|
resolve()
|
|
}))
|
|
}
|
|
|
|
const coords = ([x, y, z]) => `${x},${y},${z}`;
|
|
const createPlan = ([id, orO, crO, obrO, obrC, grO, grObs]) => {
|
|
return {
|
|
id,
|
|
botCosts: {
|
|
ore: {ore: orO},
|
|
clay: {ore: crO},
|
|
obs: {
|
|
ore: obrO,
|
|
clay: obrC
|
|
},
|
|
geo: {
|
|
ore: grO,
|
|
obs: grObs
|
|
}
|
|
},
|
|
maxBotNeed: {
|
|
ore: Math.max(orO, crO, obrO, grO),
|
|
clay: obrC,
|
|
obs: grObs,
|
|
geo: Infinity
|
|
}
|
|
}
|
|
};
|
|
|
|
let exhaustedPossibilities = 0;
|
|
|
|
|
|
const main = async () => {
|
|
const input = (await fs.readFile("./input.txt", 'utf8')).slice(0, -1).split("\n").slice(0,3);
|
|
const plans = input.map(p => createPlan(p.match(/\d+/g).map(x => parseInt(x))));
|
|
|
|
const results = plans.map(plan => {
|
|
let runningBest = 0;
|
|
const runPlan = (
|
|
plan,
|
|
buildNext,
|
|
bots = {ore: 1, clay: 0, obs: 0, geo: 0},
|
|
resources = {ore: 0, clay: 0, obs: 0, geo: 0},
|
|
time=32
|
|
) => {
|
|
if(runningBest < resources.geo) {
|
|
runningBest = resources.geo;
|
|
}
|
|
if(time < 1) {
|
|
exhaustedPossibilities++;
|
|
if(exhaustedPossibilities % 1000000 === 0) {
|
|
console.log("Tried ", exhaustedPossibilities, " possible outcomes");
|
|
}
|
|
return resources.geo;
|
|
}
|
|
if(time * (time - 1) / 2 + resources.geo + bots.geo * time < runningBest) {
|
|
return resources.geo;
|
|
}
|
|
|
|
const {maxBotNeed, botCosts} = plan;
|
|
const nextResources = Object.entries(resources).reduce((next, [type, count]) => {
|
|
next[type] = count + bots[type];
|
|
return next;
|
|
}, {});
|
|
let nextBots = bots;
|
|
const canBuild = buildNext && Object.entries(botCosts[buildNext]).every(([type, needed]) => resources[type] >= needed);
|
|
if(canBuild) {
|
|
nextBots = {...bots, [buildNext]: bots[buildNext] + 1};
|
|
for(const type in botCosts[buildNext]) {
|
|
nextResources[type] -= botCosts[buildNext][type];
|
|
}
|
|
buildNext = undefined;
|
|
}
|
|
if(buildNext) {
|
|
return runPlan(plan, buildNext, nextBots, nextResources, time -1);
|
|
}
|
|
|
|
const outcomes = Object.entries(botCosts).filter(([k]) => k !== "id").map(([type, costs]) => {
|
|
for(const key in costs) {
|
|
if(!nextBots[key]) {
|
|
return 0;
|
|
}
|
|
}
|
|
if(nextBots[type] >= maxBotNeed[type]) {
|
|
return 0;
|
|
}
|
|
|
|
return runPlan(plan, type, nextBots, nextResources, time - 1);
|
|
});
|
|
|
|
return Math.max(...outcomes);
|
|
};
|
|
console.log("Plan: ", plan.id);
|
|
const res = Math.max(runPlan(plan, "ore"), runPlan(plan, "clay"));
|
|
console.log("Best: ", runningBest);
|
|
return res;
|
|
});
|
|
|
|
console.log("Results: ", results);
|
|
|
|
console.log("Answer: ", results.reduce((prod, n) => prod * n));
|
|
}
|
|
|
|
|
|
main();
|