var initialFloors = []; var initialLift = 0; var minFloor = 0; var _ = require("underscore"); var previous = []; var p = require("pararr"); var scenarios = [ { floors: initialFloors, lift: initialLift } ]; var input = require("fs").readFileSync("input_2.txt").toString().replace(/\r/g, ""); input.split("\n").filter((a)=>(a)).forEach((line)=>{ var floorNums = ["first", "second", "third", "fourth"]; var lineParts = line.match(/The ([^ ]+) floor contains (.*)./); var floorNum = floorNums.indexOf(lineParts[1]); initialFloors[floorNum] = []; var items = lineParts[2].replace("and ", ", ").split(", ").filter((a)=>(a)); items.forEach((item)=>{ if(item.indexOf("generator") != -1){ var itemParts = item.match(/a ([^ ]+) generator/); initialFloors[floorNum].push(["generator", itemParts[1]]) } else if(item.indexOf("microchip") != -1){ var itemParts = item.match(/a ([^ ]+)-compatible microchip/); initialFloors[floorNum].push(["microchip", itemParts[1]]) } }); }); function checkFloors(floors){ for(var floor of floors){ if(floor.filter((a)=>(a[0] == "generator")).length > 0){ for(var element of floor.filter((a)=>(a[0] == "microchip")).map((a)=>(a[1]))){ if(floor.filter((a)=>(a[0] == "generator")).map((a)=>(a[1])).indexOf(element) == -1){ return false; } } } } return true; } function getMinFloors(floors){ return floors.map((a)=>(Boolean(a.length))).indexOf(true); } function possibleScenarios(scenario){ var combinatorics = require("js-combinatorics"); var newScenarios = []; var ids = scenario.floors[scenario.lift].map((a, i)=>(i)); var arrangements = []; if(ids.length >= 1){ arrangements = arrangements.concat(combinatorics.combination(ids, 1).toArray()); } if(ids.length >= 2){ arrangements = arrangements.concat(combinatorics.combination(ids, 2).toArray()); } arrangements.forEach((arrangement)=>{ if(scenario.lift < 3){ var floors = JSON.parse(JSON.stringify(scenario.floors)); floors[scenario.lift + 1].push(floors[scenario.lift][arrangement[0]]); delete floors[scenario.lift][arrangement[0]]; if(arrangement.length == 2){ floors[scenario.lift + 1].push(floors[scenario.lift][arrangement[1]]); delete floors[scenario.lift][arrangement[1]]; } floors[scenario.lift] = floors[scenario.lift].filter((a)=>(a)); newScenarios.push({lift: scenario.lift + 1, floors: floors}); } if((scenario.lift > 0)){ var floors = JSON.parse(JSON.stringify(scenario.floors)); floors[scenario.lift - 1].push(floors[scenario.lift][arrangement[0]]); delete floors[scenario.lift][arrangement[0]]; if(arrangement.length == 2){ floors[scenario.lift - 1].push(floors[scenario.lift][arrangement[1]]); delete floors[scenario.lift][arrangement[1]]; } floors[scenario.lift] = floors[scenario.lift].filter((a)=>(a)); newScenarios.push({lift: scenario.lift - 1, floors: floors}); } }); return newScenarios; } function nextSetOfScenarios(scenarios, callback){ scenarioCheckFloors = (scenario)=>{ for(var floor of scenario.floors){ if(floor.filter((a)=>(a[0] == "generator")).length > 0){ for(var element of floor.filter((a)=>(a[0] == "microchip")).map((a)=>(a[1]))){ if(floor.filter((a)=>(a[0] == "generator")).map((a)=>(a[1])).indexOf(element) == -1){ return false; } } } } return true; }; scenarioSort = (scenario)=>{ scenario.floors = scenario.floors.map((a)=>(a.sort())); return scenario; } scenarioToJson = (scenario)=>{ return scenario }; scenarioFromJson = (scenario)=>(scenario); scenarioDuplicate = (scenario, i, scenarios)=>{ //console.log(scenario[2].findIndex((item)=>(console.log("item", item))), i); var scenarioStr = JSON.stringify(scenario); return (scenarios.findIndex((item)=>(JSON.stringify(item) == scenarioStr)) == i); }; scenarioPrevious = (scenario)=>{ //console.log(previous.indexOf(JSON.stringify(scenario))); return (previous.indexOf(JSON.stringify(scenario)) == -1); }; scenarioAddToPrevious = (scenario)=>{ previous.push(JSON.stringify(scenario)); } console.log("start", scenarios.length); p.map(scenarios, possibleScenarios, (err, scenarios)=>{ var allscenarios = []; for(var scenarioSet of scenarios){ for(var scenario of scenarioSet){ allscenarios.push(scenario); } } scenarios = allscenarios; console.log("possibilities", scenarios.length); p.filter(scenarios, scenarioCheckFloors, (err, scenarios)=>{ console.log("valid", scenarios.length); p.map(scenarios, scenarioSort, (err, scenarios)=>{ console.log("sorted", scenarios.length); console.log("to JSON", scenarios.length); scenarios = scenarios.map((scenario)=>(JSON.stringify(scenario))); console.log("dedupe", scenarios.length); scenarios = _.uniq(scenarios, (scenario)=>(JSON.stringify(scenario))); console.log("removing previous", scenarios.length); scenarios = _.difference(scenarios, previous); console.log("adding to previous", scenarios.length); scenarios.forEach((scenario)=>(previous.push(scenario))); console.log("from JSON", scenarios.length); scenarios = scenarios.map((scenario)=>(JSON.parse(scenario))); callback(scenarios); /* p.map(scenarios, scenarioToJson, (err, scenarios)=>{ console.log("inJSON", scenarios.length); //console.log(scenarios[0]); scenarios = scenarios.map((scenario)=>([false, scenario])); p.map(scenarios, scenarioDuplicate, (err, scenarios)=>{ scenarios = scenarios.filter((scenario)=>(scenario[0])); scenarios = scenarios.map((scenario)=>(scenario[1])); console.log("deduped", scenarios.length); p.map(scenarios, scenarioFromJson, (err, scenarios)=>{ console.log("fromJSON", scenarios.length); callback(scenarios); }); }); }); */ }); }); }); /* Standard code to copy p.map(scenarios, scenarioSort, (err, scenarios)=>{ callback(scenarios); }); */ //p.map(possibleScenarios).reduce(merge).spawn(forceMerge).then(callback); /* for(var scenario of scenarios){ scenarios = newScenarios.concat(possibleScenarios(scenario)); } console.log("removing invalid"); newScenarios = newScenarios.filter((scenario)=>(checkFloors(scenario.floors))); console.log("newLength", newScenarios.length); console.log("calc min"); localMinFloor = newScenarios.map((scenario)=>(getMinFloors(scenario.floors))).reduce((a, b)=>(Math.max(a, b))) console.log("sorting"); newScenarios.forEach((scenario)=>{scenario.floors.forEach((a)=>(a.sort()));}) console.log("to JSON"); newScenarios = newScenarios.map((scenario)=>(JSON.stringify(scenario))); console.log("dedupe"); newScenarios = _.uniq(newScenarios, (scenario)=>(JSON.stringify(scenario))); console.log("removing previous"); newScenarios = _.difference(newScenarios, previous); console.log("adding to previous"); newScenarios.forEach((scenario)=>(previous.push(scenario))); console.log("from JSON"); newScenarios = newScenarios.map((scenario)=>(JSON.parse(scenario))); console.log("MIN", localMinFloor); if(localMinFloor == 3){ console.log("SOLVED"); } scenarios = newScenarios; */ } /* var i = 0; while(minFloor < 3){ i++; nextSetOfScenarios(); console.log("it", i); console.log(scenarios.length); } console.log(i); */ var i = 0; var callback = (scenarios)=>{ i++; console.log(i, scenarios.length); if(scenarios.map((scenario)=>(scenario.floors)).filter((floors)=>(floors[0].length == 0)).filter((floors)=>(floors[1].length == 0)).filter((floors)=>(floors[2].length == 0)).length == 0){ nextSetOfScenarios(scenarios, callback); } else{ console.log("SOLVED", i); p.destroy(); } } nextSetOfScenarios(scenarios, callback);