Last active
December 12, 2020 00:45
-
-
Save gulhe/508a5eabbf45d406b9c1120e5aef7b95 to your computer and use it in GitHub Desktop.
Advent Of Code 2020
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
/*Part 1*/ | |
document.body.innerText.trim().split(/\n/g).map(Number) | |
.filter((e,_,t)=>t.some(te=>te+e===2020)) | |
.reduce((a,b)=>a*b) | |
/*Part 2*/ | |
document.body.innerText.trim().split(/\n/g).map(Number) | |
.filter((e,_,t)=>t.some(te=>t.some(tte=>tte+te+e===2020))) | |
.reduce((a,b)=>a*b) |
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
/*Part 1*/ | |
document.body.innerText.trim().split(/\n/g) | |
.filter(l => { | |
const [rule, str] = l.split(`: `); | |
const [range, letter] = rule.split(` `); | |
const [min, max] = range.split(`-`) | |
const numberOfOccurences = Array.from(str).filter(l=>l===letter).length; | |
return (min <= numberOfOccurences) && (numberOfOccurences <= max); | |
}).length | |
/*Part 2*/ | |
document.body.innerText.trim().split(/\n/g) | |
.filter(l => { | |
const [rule, str] = l.split(`: `); | |
const [range, letter] = rule.split(` `); | |
const [left, right] = range.split(`-`).map(x=>str[x+1]); | |
if (left + right === letter + letter) { | |
return false; | |
} | |
if (left === letter) { | |
return true; | |
} | |
if (right === letter) { | |
return true; | |
} | |
return false; | |
}).length | |
/*Part 2 (with extracted-named lambdas)*/ | |
function letterIsLeftXorRight(letter, left, right) { | |
if (left + right === letter + letter) { | |
return false; | |
} | |
if (left === letter) { | |
return true; | |
} | |
if (right === letter) { | |
return true; | |
} | |
return false; | |
} | |
function lineVerifiesItsOwnRule(line) { | |
const [rule, password] = line.split(`: `); | |
const [range, letter] = rule.split(` `); | |
const [left, right] = range.split(`-`).map(x=>password[x+1]); | |
return letterIsLeftXorRight(letter, left, right); | |
}; | |
document.body.innerText.trim().split(/\n/g) | |
.filter(lineVerifiesItsOwnRule) | |
.length |
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
/*Part 1*/ | |
[{r: 3, d: 1}].map(c => document.body.innerText.trim().split(/\n/g) | |
.filter((_, i) => !(i % c.d)) | |
.map((e, i) => e[(i * c.r) % (e.length)]) | |
.filter(e => e === `#`).length) | |
.reduce((a, b) => a * b) | |
/*Part 2*/ | |
[ | |
{r: 1, d: 1}, | |
{r: 3, d: 1}, | |
{r: 5, d: 1}, | |
{r: 7, d: 1}, | |
{r: 1, d: 2} | |
].map(c => document.body.innerText.trim().split(/\n/g) | |
.filter((_, i) => !(i % c.d)) | |
.map((e, i) => e[(i * c.r) % (e.length)]) | |
.filter(e => e === `#`).length) | |
.reduce((a, b) => a * b) |
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 between = (low, high) => y => low <= y && y <= high; | |
const heightCheckers = { | |
in: between(59, 76), | |
cm: between(150, 193) | |
}; | |
const noper = _ => false; | |
const isPresent = _ => _; | |
const hex6Max = parseInt(`ffffff`, 16); | |
const in6HexRange = between(0, hex6Max); | |
const toHex = str => parseInt(str, 16); | |
let hgt = str => (heightCheckers[str.slice(-2)] || noper)(str.slice(0, -2)); | |
let hcl = ([pound, ...hexPart]) => | |
(pound === "#") && | |
in6HexRange(toHex(hexPart.join(``))); | |
[ | |
/*Part 1*/ | |
{ | |
byr:isPresent, | |
iyr:isPresent, | |
eyr:isPresent, | |
hgt:isPresent, | |
hcl:isPresent, | |
ecl:isPresent, | |
pid:isPresent | |
}, | |
/*Part 2*/ | |
{ | |
byr: between(1920, 2002), | |
iyr: between(2010, 2020), | |
eyr: between(2020, 2030), | |
hgt, | |
hcl, | |
ecl: ecl => ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"].includes(ecl), | |
pid: pid => /^[0-9]{9}$/.test(pid) | |
} | |
].map(constraints => document.body.innerText.trim().split(/\n\n/g) | |
.map(passport => passport.split(/[ \n]/g) | |
.map(kv => kv.split(':')) | |
.map(([k,v])=>{ | |
const res={}; | |
res[k]=v; | |
return res | |
}) | |
.reduce((acc,nxt)=>({...acc,...nxt}),{})) | |
.filter(obj => Object.keys(constraints).every(key => constraints[key](obj[key] || "")) | |
).length | |
).forEach(e=>console.log(e)) |
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
/*Part 1*/ | |
document.body.innerText.trim().split(/\n/) | |
.map(s => s.replaceAll(/F|L/gi, `0`).replaceAll(/B|R/gi, `1`)) | |
.map(s => parseInt(s, 2)) | |
.reduce((a,b)=>Math.max(a,b)) | |
/*Part 2*/ | |
1 + document.body.innerText.trim().split(/\n/) | |
.map(s => s.replaceAll(/F|L/gi, `0`).replaceAll(/B|R/gi, `1`)) | |
.map(s => parseInt(s, 2)) | |
.sort((a, b) => a - b) | |
.find((e, i, t) => (e + 1) !== t[i + 1]) |
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
/*Part 1*/ | |
document.body.innerText.trim().split(/\n\n/g) | |
.map(group=>group.replaceAll(/\n/g,"")) | |
.map(str => new Set(Array.from(str)).size) | |
.reduce((a,b)=>a+b) | |
/*Part 2*/ | |
document.body.innerText.trim().split(/\n\n/g) | |
.map(group=>group.split(/\n/g) | |
.map(str=>Array.from(str)) | |
.reduce((acc,e)=>Array.from(acc).filter(Ξ±=>e.includes(Ξ±))) | |
) | |
.map(commonAnswersArray => commonAnswersArray.length) | |
.reduce((a,b)=>a+b) | |
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 diveTowardsTerminalValues = (source, ...terminalValues) => (contentType) => Object | |
.keys(source[contentType]) | |
.some(k => terminalValues.includes(k) || diveTowardsTerminalValues(source, ...terminalValues)(k)) | |
const reachTheSurfaceFromValues = (source, ...contentTypes) => contentTypes | |
.map(type=> Object.entries(source) | |
.filter(([_,v])=>type in v) | |
.map(([k,..._])=>k) | |
.reduce((set,e)=>new Set([...set, ...reachTheSurfaceFromValues(source,e)]), new Set([type])) | |
).reduce((a,b)=>new Set([...a, ...b]), new Set()) | |
const countComponents = (source, contentType) => Object.entries(source[contentType]) | |
.map(([k, v]) => v * (1 + countComponents(source, k))) | |
.reduce((a, b) => a + b, 0) | |
const contents = Object.fromEntries(document.body.innerText.trim().split(/\n/g) | |
.map(line => { | |
const [name, contentSpec] = line.split(/ bags contain /g); | |
const content = contentSpec.split(/, /g) | |
.map(desc => { | |
if (desc === `no other bags.`) { | |
return; | |
} | |
return desc.matchAll(/^(\d+) (.+ .+) bag.*$/g); | |
}) | |
.filter(a => a) | |
.map(iter => Array.from(iter)) | |
.map(([[, qty, type]]) => [type, qty]); | |
return [name, Object.fromEntries(content)]; | |
})); | |
/*Part 1*/ | |
const part1TopToBottom = _ => Object.keys(contents) | |
.filter(diveTowardsTerminalValues(contents, "shiny gold")) | |
.length | |
/*Part 1-alt*/ | |
const part1BottomToTop = _ => reachTheSurfaceFromValues(contents, "shiny gold").size -1 | |
/*Part 2*/ | |
const part2 = _ => countComponents(contents, "shiny gold") |
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 compiler = { | |
jmp: (i) => runner => runner.HEAD += parseInt(i), | |
nop: () => compiler.jmp(1), | |
acc: (i) => runner => { | |
runner.data += parseInt(i); | |
compiler.nop()(runner) | |
} | |
}; | |
const compileLine = ([opCode, param]) => compiler[opCode](param) | |
const source = document.body.innerText.trim().split(/\n/g) | |
.map(line => line.split(" ")) | |
/*Part 1*/ | |
const part1 = _ => { | |
return ({ | |
source, | |
HEAD: 0, | |
data: 0, | |
beenThere: new Set(), | |
run() { | |
if (this.beenThere.has(this.HEAD)) { | |
return this.data; | |
} | |
this.beenThere.add(this.HEAD); | |
compileLine(this.source[this.HEAD])(this); | |
return this.run(); | |
} | |
}).run() | |
} | |
/*Part 1*/ | |
const part2 = _ => { | |
const runner = source => ({ | |
HEAD: 0, | |
data: 0, | |
beenThere: new Set(), | |
run() { | |
if (this.beenThere.has(this.HEAD)) { | |
return; | |
} | |
if (this.HEAD === source.length) { | |
return this.data; | |
} | |
this.beenThere.add(this.HEAD); | |
compileLine(source[this.HEAD])(this); | |
return this.run(); | |
} | |
}) | |
function toggleIf(opp, b) { | |
if (!b) { | |
return opp; | |
} | |
if (opp === `acc`) { | |
return opp; | |
} | |
if (opp === `jmp`) { | |
return `nop`; | |
} | |
return `jmp`; | |
} | |
return source.map((_, i, t) => | |
t.map(([opp, param], ti) => [toggleIf(opp, ti === i), param]) | |
) | |
.map(runner) | |
.map(runner => runner.run()) | |
.filter(r=>r)[0] | |
} |
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 input = document.body.innerText.trim().split(/\n/g).map/* la morue de ses chiens morts de map(Number) que j'avais zappΓ© lΓ , Γ§a me saoul*/(Number) | |
/*Part 1*/ | |
const part1Result = input.find( | |
(e, i, t) => (i >= 25) && !t.slice(i - 25, i).some( | |
(ste, sti, stt) => stt.some( | |
stte => stte + ste === e | |
) | |
) | |
); | |
/*Part 2*/ | |
const solver = { | |
"π": { | |
twig: input, | |
head: 2, | |
ass: 0, | |
coveredArea: function () { | |
return this.twig.slice(this.ass, this.head); | |
}, | |
crunch() { | |
/* this caterpillar munches all there is under her body at once ... got a problem with that ? */ | |
return this.coveredArea().reduce((a, e) => a + e); | |
}, | |
sanityCheck() { | |
if ((this.head - this.ass) < 2) { | |
throw new Error("Something happens and I'm head over heels\n" + | |
"I never find out till I'm head over heels\n" + | |
"Something happens and I'm head over heels\n" + | |
"Ah, don't take my heart, don't break my heart\n" + | |
"Don't, don't, don't throw it away"); | |
} | |
if (this.head === this.twig.length) { | |
throw new Error("I've got to be strong\n" + | |
"Oh, I'm falling off the edge of the world\n" + | |
"Think you're safe, but you're wrong!\n" + | |
"We are falling off the edge of the world!"); | |
} | |
}, | |
shitAnAnswer() { | |
const mouthful = this.crunch(); | |
if (mouthful === part1Result) { | |
return this.digest(); | |
} | |
if (mouthful > part1Result) { | |
this.ass++; | |
} | |
if (mouthful < part1Result) { | |
this.head++; | |
} | |
this.sanityCheck(); | |
/* the answer you shit maybe the answer shat by yourself in a near future ... | |
I would have loved to use what gets shat in the crunch() function but this is a caterpillar not a centipede ... */ | |
return this.shitAnAnswer(); | |
}, | |
digest() { | |
return this.coveredArea().sort().filter((_, i, t) => (i === 0) || ((i + 1) === t.length)).reduce( | |
(a, e) => a + e | |
) | |
} | |
}, | |
"π": { | |
"ππΎπ³": input, //This represents a field ... | |
"π": 1, | |
"π": 0, | |
bellyContent: input.slice(0,2).reduce((a,e)=>a+e), | |
"π½οΈ"() { | |
this.bellyContent+=this["ππΎπ³"][++this["π"]]; | |
}, | |
"π©"() { | |
this.bellyContent-=this["ππΎπ³"][this["π"]++]; | |
}, | |
sanityCheck() { | |
if ((this["π"] - this["π"]) < 1) { | |
throw new Error("Something happens and I'm head over heels\n" + | |
"I never find out till I'm head over heels\n" + | |
"Something happens and I'm head over heels\n" + | |
"Ah, don't take my heart, don't break my heart\n" + | |
"Don't, don't, don't throw it away"); | |
} | |
if (this["π"] === this["ππΎπ³"].length) { | |
throw new Error("I've got to be strong\n" + | |
"Oh, I'm falling off the edge of the world\n" + | |
"Think you're safe, but you're wrong!\n" + | |
"We are falling off the edge of the world!"); | |
} | |
}, | |
digest() { | |
if (this.bellyContent === part1Result) { | |
return this.spit(); | |
} | |
if (this.bellyContent > part1Result) { | |
this["π©"](); | |
} else { | |
this["π½οΈ"](); | |
} | |
this.sanityCheck(); | |
/* the answer you shit maybe the answer shat by yourself in a near future ... | |
I would have loved to use what gets shat in the crunch() function but this is a caterpillar not a centipede ... */ | |
return this.digest(); | |
}, | |
spit(){ | |
return this["ππΎπ³"].slice(this["π"], this["π"] + 1).sort().filter((_, i, t) => (i === 0) || ((i + 1) === t.length)).reduce((a, e) => a + e) | |
} | |
} | |
}; | |
console.time("π") | |
const part2Result = solver["π"].shitAnAnswer() | |
console.timeEnd("π") | |
console.time("π") | |
const part2BisResult = solver["π"].digest() | |
console.timeEnd("π") | |
console.log("The π is faster than the π just as the π¦ does not chasse les πͺ°") | |
console.table({part1Result, part2Result, part2BisResult}); |
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
/*Phoquing jour maudit il s'est rien passΓ© lΓ tirez vous maintenant ...*/ |
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 initialState = document.body.innerText.trim().split(/\n/g).map(s => Array.from(s)); | |
const applyRules = crowdTolerance => (s, neighbours) => { | |
const occupiedSeats = neighbours.filter(n => n === "#").length; | |
if (s === `L`) { | |
if (occupiedSeats === 0) { | |
return `#`; | |
} | |
} | |
if (s === `#`) { | |
if (occupiedSeats >= crowdTolerance) { | |
return `L`; | |
} | |
} | |
return s; | |
}; | |
const gol = (crowdTolerance, neighbouringHeuristic)=> grid => grid.map((l, i, t) => l.map((s, j, w) => applyRules(crowdTolerance)(s, neighbouringHeuristic(grid, i, j)))); | |
function printForTheLols(grid) { | |
document.querySelector(`pre`).innerHTML = grid.map(e => e.join(``)).join(`\n`).replaceAll(`L`,`πͺ`).replaceAll(`#`,`π`).replaceAll(`.`,`π¦`) | |
} | |
const cardinals = [-1, 0, 1] | |
.flatMap((h, _, t) => t.map(v => [h, v]).filter(cardinal => cardinal.some(component => component !== 0))); | |
function neighbours(grid, x, y) { | |
return cardinals.map(([e, d]) => grid[x + e]?.[y + d]) | |
} | |
function rayCast(grid, x, y, h, v) { | |
const nextElem = grid[x + h]?.[y + v]; | |
if(nextElem!==`.`){ | |
return nextElem; | |
} | |
return rayCast(grid, x+h, y+v, h, v); | |
} | |
function remoteNeighbours(grid, x, y) { | |
return cardinals | |
.map(c => rayCast(grid, x, y, ...c)) | |
} | |
function run(states, mapper, delay = 30) { | |
return new Promise(resolve => { | |
printForTheLols(states[states.length - 1]) | |
if (states[states.length - 1].toString() !== states[states.length - 2]?.toString()) { | |
states.push(mapper(states[states.length - 1])); | |
setTimeout(_ => resolve(run(states, mapper, delay)), delay) | |
} else { | |
resolve(Array.from(states[states.length - 1].toString()).filter(x => x === `#`).length) | |
} | |
}) | |
} | |
function runPart1(states, delay) { | |
return run(states, gol(4, neighbours), delay) | |
} | |
function runPart2(states, delay) { | |
return run(states, gol(5, remoteNeighbours), delay) | |
} | |
runPart1([initialState]) | |
.then(console.log) | |
.then(_=>runPart2([initialState])) | |
.then(console.log) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment