Skip to content

Instantly share code, notes, and snippets.

@SphinxKnight
Last active December 7, 2019 20:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SphinxKnight/2de8d1d18b370f939ae8d0dd614af63c to your computer and use it in GitHub Desktop.
Save SphinxKnight/2de8d1d18b370f939ae8d0dd614af63c to your computer and use it in GitHub Desktop.
Advent of code 2019
const fs = require("fs");
const dataFile = "input1.txt";
const assert = require("assert").strict;
function convertFuel(amount) {
return Math.trunc(amount / 3) - 2;
}
assert.equal(convertFuel(1969), 654);
assert.equal(convertFuel(100756), 33583);
function compensateFuel(initialAmount) {
if(convertFuel(initialAmount) <= 0){
return 0;
} else {
const amountMoreFuelNeeded = convertFuel(initialAmount);
return amountMoreFuelNeeded + compensateFuel(amountMoreFuelNeeded);
}
}
assert.equal(compensateFuel(14), 2);
assert.equal(compensateFuel(100756), 50346);
assert.equal(compensateFuel(1969), 966);
fs.readFile(dataFile, {encoding: "utf8"}, (err,data)=>{
if(err) {
throw err;
} else {
const totalFuel = data.split("\n").map(elem => {
const initialFuel = convertFuel(Number.parseInt(elem, 10));
const compensate = compensateFuel(initialFuel);
return initialFuel + compensate;
}).reduce((a,b) => (a + b));
console.log("Total", totalFuel);
}
});
const fs = require("fs").promises;
const dataFile = "input2_fixed.txt";
const assert = require("assert").strict;
const MAX_VALUE = 99;
async function mainAsync(){
let arrIntCode = (await fs.readFile(dataFile, {encoding: "utf8"})).split(",").map(n => Number.parseInt(n,10));
const initMemory = Array.from(arrIntCode);
console.log("Answer - Part 1:", decodeIntCode(arrIntCode)[0]);
let noun = -1;
let result = 0;
let verb = -1;
do {
let newMemory = [];
noun++;
verb = -1;
do {
verb++;
newMemory = Array.from(initMemory);
newMemory[1] = noun;
newMemory[2] = verb;
result = decodeIntCode(newMemory)[0];
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write("Bruteforcing like no one is watching: ");
process.stdout.write(`noun: ${noun} \tverb: ${verb}`);
} while ( verb < MAX_VALUE && result != 19690720);
} while(noun < MAX_VALUE && result != 19690720);
console.log("\nnoun found:", noun);
console.log("verb found:", verb);
let answer = 100 * noun + verb;
console.log("Answer - part 2: ", answer);
}
function decodeIntCode(arrIntCodes, index = 0) {
if(arrIntCodes[index] === 99) {
return arrIntCodes;
} else {
const operand1 = arrIntCodes[arrIntCodes[index + 1]];
const operand2 = arrIntCodes[arrIntCodes[index + 2]];
if (arrIntCodes[index] === 1) {
arrIntCodes[arrIntCodes[index + 3]] = operand1 + operand2;
return decodeIntCode(arrIntCodes, index + 4);
} else if (arrIntCodes[index] === 2) {
arrIntCodes[arrIntCodes[index + 3]] = operand1 * operand2;
return decodeIntCode(arrIntCodes, index + 4);
} else {
return arrIntCodes;
}
}
}
assert.deepEqual(decodeIntCode([1,0,0,0,99]),[2,0,0,0,99]);
assert.deepEqual(decodeIntCode([2,3,0,3,99]),[2,3,0,6,99]);
assert.deepEqual(decodeIntCode([2,4,4,5,99,0]),[2,4,4,5,99,9801]);
assert.deepEqual(decodeIntCode([1,1,1,4,99,5,6,0,99]),[30,1,1,4,2,5,6,0,99]);
mainAsync();
const fs = require("fs").promises;
const dataFile = "input3.txt";
const assert = require("assert").strict;
function intersectorFinder(arrPath1, arrPath2) {
const arrPointsPath1 = getPoints(arrPath1);
const arrPointsPath2 = getPoints(arrPath2);
const commonPoints = computeIntersections(arrPointsPath1, arrPointsPath2);
return commonPoints.map(computeManhattanDist).reduce((a,b)=> Math.min(a,b));
}
function minStepIntersector(arrPath1, arrPath2) {
const arrPointsPath1 = getPoints(arrPath1);
const arrPointsPath2 = getPoints(arrPath2);
const commonPoints = computeIntersections(arrPointsPath1, arrPointsPath2);
return commonPoints.map(e=> e.stepA + e.stepB).reduce((a,b)=> Math.min(a,b));
}
function getPoints(arrPath) {
let currentPosition = {x: 0, y: 0, step: 0};
let arrPoints = [];
for (let i = 0; i < arrPath.length; i++) {
const currentMove = arrPath[i];
const positionsExplored = moveWire(currentPosition, currentMove, currentPosition.step);
arrPoints.push(positionsExplored);
currentPosition = positionsExplored.slice(-1)[0];
}
return arrPoints.flat().slice(1);
}
function moveWire(pos, move, currStep = 0) {
const direction = move[0];
const distance = Number.parseInt(move.slice(1), 10);
const pointsExplored = [];
for (let i = 1; i <= distance; i++) {
switch (direction) {
case "R":
pointsExplored.push({x: pos.x + i, y: pos.y, step: currStep + i});
break;
case "L":
pointsExplored.push({x: pos.x - i, y: pos.y, step: currStep + i});
break;
case "U":
pointsExplored.push({x: pos.x, y: pos.y + i, step: currStep + i});
break;
case "D":
pointsExplored.push({x: pos.x, y: pos.y - i, step: currStep + i});
break;
default:
pointsExplored.push(pos);
}
}
return pointsExplored;
}
function computeIntersections(arr1, arr2) {
let intersection = [];
for (const elemA of arr1) {
for(const elemB of arr2) {
if(elemA.x === elemB.x && elemA.y === elemB.y){
const intersectionPoint = {x: elemA.x, y: elemA.y, stepA: elemA.step, stepB: elemB.step};
intersection.push(intersectionPoint);
}
}
}
return intersection;
}
function computeManhattanDist(pointXY){
return Math.abs(pointXY.x) + Math.abs(pointXY.y);
}
assert.equal(intersectorFinder(["R8","U5","L5","D3"],["U7","R6","D4","L4"]),6);
assert.equal(intersectorFinder(["R75","D30","R83","U83","L12","D49","R71","U7","L72"],["U62","R66","U55","R34","D71","R55","D58","R83"]), 159);
assert.equal(intersectorFinder(["R98","U47","R26","D63","R33","U87","L62","D20","R33","U53","R51"],["U98","R91","D20","R16","D67","R40","U7","R15","U6","R7"]), 135);
assert.equal(minStepIntersector(["R8","U5","L5","D3"],["U7","R6","D4","L4"]),30);
assert.equal(minStepIntersector(["R75","D30","R83","U83","L12","D49","R71","U7","L72"],["U62","R66","U55","R34","D71","R55","D58","R83"]), 610);
assert.equal(minStepIntersector(["R98","U47","R26","D63","R33","U87","L62","D20","R33","U53","R51"],["U98","R91","D20","R16","D67","R40","U7","R15","U6","R7"]), 410);
async function mainAsync(){
let pathsStr = (await fs.readFile(dataFile, {encoding: "utf8"})).split("\n");
let pathsArr = pathsStr.map(x => x.split(","));
console.log(minStepIntersector(pathsArr[0], pathsArr[1]));
}
mainAsync();
const assert = require("assert").strict;
function checkRule1(number){
return number > 99999 && number < 1000000;
}
function checkRule2(number, min, max){
return number >= min && number <= max;
}
function checkRule3_1(number){
const strNumber = number + "";
return strNumber.split("")
.map((e, i, arr)=>( e===arr[i+1] ))
.some(e=> e === true);
}
function checkRule3_2(number){
const arrStrNumber = (number + "").split("");
let currentDigit = "";
let validStreak = false;
let nbStreak = 0;
for (let i = 0; i < arrStrNumber.length; i++) {
if(arrStrNumber[i] === currentDigit){
nbStreak++;
currentDigit = arrStrNumber[i];
if(nbStreak === 1){
validStreak = true;
} else if (nbStreak === 2){
validStreak = false;
}
} else {
if(nbStreak === 1){
break;
}
nbStreak = 0;
currentDigit = arrStrNumber[i];
}
}
return validStreak;
}
function checkRule4(number){
const strNumber = number + "";
return strNumber.split("").reduce(
(flag, elem, index, arr)=>{
return flag && (
( index === arr.length - 1)
||
(Number.parseInt(elem ,10) <= Number.parseInt(arr[index + 1] ,10))
);
}
, true);
}
assert.equal(checkRule3_2(144555), true);
assert.equal(checkRule1(111111), true);
assert.equal(checkRule2(111111, 100000, 120000), true);
assert.equal(checkRule3_2(138889), false);
assert.equal(checkRule3_2(111111), false);
assert.equal(checkRule3_2(123444), false);
assert.equal(checkRule1(144555), true);
assert.equal(checkRule2(144555, 100000, 150000), true);
assert.equal(checkRule4(144555), true);
assert.equal(checkRule3_2(112233), true);
assert.equal(checkRule3_2(111122), true);
assert.equal(checkRule3_2(123789), false);
assert.equal(checkRule4(112233), true);
assert.equal(checkRule4(223450), false);
const MIN_RANGE = 138241;
const MAX_RANGE = 674034;
let arrRange = (new Array(MAX_RANGE - MIN_RANGE + 1)).fill(0).map((elem, index)=> MIN_RANGE + index);
let arrValid = arrRange
.filter(checkRule1)
.filter(elem => checkRule2(elem, MIN_RANGE, MAX_RANGE))
.filter(checkRule3_2)
.filter(checkRule4);
const nbValid = arrValid.length;
console.log(nbValid);
const fs = require("fs").promises;
const assert = require("assert").strict;
const dataFile = "input5.txt";
async function mainAsync(){
let arrIntCode = (await fs.readFile(dataFile, {encoding: "utf8"})).split(",").map(n => Number.parseInt(n,10));
let memory1 = Array.from(arrIntCode);
decodeIntCode(memory1, 0, 1);
let memory2 = Array.from(arrIntCode);
decodeIntCode(memory2, 0, 5);
}
function decodeParameter(mode, value, arrIntCode){
if(mode === 0){
return arrIntCode[value];
} else if(mode === 1){
return value;
}
}
function decodeIntCode(arrIntCodes, index = 0, input, output) {
let instruction = (arrIntCodes[index] + "").padStart(5,"0");
let opCode = Number.parseInt(instruction.slice(-2),10);
let mode1 = Number.parseInt(instruction.slice(-3,-2),10);
let mode2 = Number.parseInt(instruction.slice(-4,-3),10);
const param1 = decodeParameter(mode1,arrIntCodes[index + 1],arrIntCodes);
const param2 = decodeParameter(mode2,arrIntCodes[index + 2],arrIntCodes);
switch (opCode) {
case 99:
return {output: output, memory:arrIntCodes};
case 1:
arrIntCodes[arrIntCodes[index + 3]] = param1 + param2;
return decodeIntCode(arrIntCodes, index + 4, input, output);
case 2:
arrIntCodes[arrIntCodes[index + 3]] = param1 * param2;
return decodeIntCode(arrIntCodes, index + 4, input, output);
case 3:
arrIntCodes[arrIntCodes[index + 1]] = input;
return decodeIntCode(arrIntCodes, index + 2, input, output);
case 4:
console.log(param1);
return decodeIntCode(arrIntCodes, index + 2, input, param1);
case 5:
if(param1 !== 0){
return decodeIntCode(arrIntCodes, param2, input, output);
} else {
return decodeIntCode(arrIntCodes, index + 3, input, output);
}
case 6:
if(param1 === 0){
return decodeIntCode(arrIntCodes, param2, input, output);
} else {
return decodeIntCode(arrIntCodes, index + 3, input, output);
}
case 7:
if(param1 < param2){
arrIntCodes[arrIntCodes[index + 3]] = 1;
} else {
arrIntCodes[arrIntCodes[index + 3]] = 0;
}
return decodeIntCode(arrIntCodes, index + 3, input, output);
case 8:
if(param1 === param2){
arrIntCodes[arrIntCodes[index + 3]] = 1;
} else {
arrIntCodes[arrIntCodes[index + 3]] = 0;
}
return decodeIntCode(arrIntCodes, index + 3, input, output);
default:
return decodeIntCode(arrIntCodes, index + 1, input, output);
}
}
//assert.deepEqual(decodeIntCode([3,3,1107,-1,8,3,4,3,99],0,7).output, 1);
//assert.deepEqual(decodeIntCode([3,3,1108,-1,8,3,4,3,99],0,8).output, 1);
//assert.deepEqual(decodeIntCode([3,9,8,9,10,9,4,9,99,-1,8],0,8).output, 1);
assert.deepEqual(decodeIntCode([1,0,0,0,99]).memory,[2,0,0,0,99]);
assert.deepEqual(decodeIntCode([2,3,0,3,99]).memory,[2,3,0,6,99]);
assert.deepEqual(decodeIntCode([2,4,4,5,99,0]).memory,[2,4,4,5,99,9801]);
assert.deepEqual(decodeIntCode([1,1,1,4,99,5,6,0,99]).memory,[30,1,1,4,2,5,6,0,99]);
assert.deepEqual(decodeIntCode([1002,4,3,4,33]).memory,[1002,4,3,4,99]);
assert.deepEqual(decodeIntCode([3,9,8,9,10,9,4,9,99,-1,8],0,9).output, 0);
assert.deepEqual(decodeIntCode([3,9,7,9,10,9,4,9,99,-1,8],0, 7).output, 1);
assert.deepEqual(decodeIntCode([3,9,7,9,10,9,4,9,99,-1,8],0, 8).output, 0);
//assert.deepEqual(decodeIntCode([3,3,1108,-1,8,3,4,3,99],0,9).output, 0);
//assert.deepEqual(decodeIntCode([3,3,1107,-1,8,3,4,3,99],0,10).output, 0);
mainAsync();
const fs = require("fs").promises;
const dataFile = "input_6.txt";
async function mainAsync() {
const dataArr = (await fs.readFile(dataFile, {encoding: "utf8"})).split("\n");
let dataOrbits = dataArr.map(e=> e.split(")"));
let treeCollection = buildTrivialTrees(dataOrbits);
let megaTree = treesAssemble(treeCollection);
console.log("Nb Orbits:", megaTree.countOrbits());
let nbJumpsForSanta = getNbJumps("YOU", "SAN", megaTree);
console.log("Nb Orbits to Santa:", nbJumpsForSanta);
}
mainAsync();
function getNbJumps(nodeA, nodeB, tree, root = "COM)"){
let pathUs = getPath(nodeA, tree);
let pathSanta = getPath(nodeB, tree);
let commonFragment = root;
let i = 0;
do {
commonFragment += (pathUs.split(")")[++i] + ")");
} while(pathUs.startsWith(commonFragment) && pathSanta.startsWith(commonFragment));
let ourSpecificPath = pathUs.substring(commonFragment.length);
let santaSpecificPath = pathSanta.substring(commonFragment.length);
return ourSpecificPath.split(")").length + santaSpecificPath.split(")").length;
}
function buildTrivialTrees(arrOrbits){
return arrOrbits.map(elem=> new Tree(elem[0],[new Tree(elem[1],[])]));
}
function treesAssemble(treeCollection){
let megaTree = new Tree("COM",[]);
while(treeCollection.length > 0){
let currTree = treeCollection.shift();
if(megaTree.containsNode(currTree.root)){
megaTree.mergeTrees(currTree);
} else if(currTree.containsNode(megaTree.root)){
currTree.mergeTrees(megaTree);
} else {
treeCollection.push(currTree);
}
}
return megaTree;
}
// Pour chaque nouveau segment
// Est-ce qu'il fait partie d'un Treee existant = est ce que l'orbite d'un des deux points est la racine ou une feuille du Treee ?
// Si oui, on rattache le segment au Treee précédent
// S'il y a un sous Treee, on le rattache à la feuille et on le supprime
// sinon : on crée un nouveau Treee
class Tree {
constructor(root, nodes){
this.root = root;
// nodes is an array
// each node is another tree
this.nodes = nodes;
}
mergeTrees(subTree){
// Identifier le noeud qu'il faut rattacher
const subRoot = subTree.root;
if(subRoot === this.root){
this.nodes = this.nodes.concat(subTree.nodes);
} else {
for (let index = 0; index < this.nodes.length; index++) {
const node = this.nodes[index];
if(node.containsNode(subRoot)){
node.mergeTrees(subTree);
}
}
}
}
countOrbits(parentOrbit = 0){
if(this.nodes.length === 0){
return parentOrbit;
} else {
return parentOrbit + this.nodes.map(node => node.countOrbits(parentOrbit + 1)).reduce((a,b)=>a+b);
}
}
containsNode(nodeValue){
return this.root === nodeValue || this.nodes.some(elem => elem.containsNode(nodeValue));
}
print(levelDepth = 0){
console.log(" ".repeat(levelDepth) + this.root);
this.nodes.forEach(node => node.print(levelDepth + 1));
}
}
function getPath(targetNode, tree){
if(tree.root === targetNode){
return targetNode;
} else {
for(let node of tree.nodes){
if(node.containsNode(targetNode)){
return tree.root + ")" + getPath(targetNode, node);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment