Last active
December 7, 2019 20:35
-
-
Save SphinxKnight/2de8d1d18b370f939ae8d0dd614af63c to your computer and use it in GitHub Desktop.
Advent of code 2019
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
}); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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