Skip to content

Instantly share code, notes, and snippets.

@gulhe
Last active December 12, 2020 00:45
Show Gist options
  • Save gulhe/508a5eabbf45d406b9c1120e5aef7b95 to your computer and use it in GitHub Desktop.
Save gulhe/508a5eabbf45d406b9c1120e5aef7b95 to your computer and use it in GitHub Desktop.
Advent Of Code 2020
/*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)
/*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
/*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)
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))
/*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])
/*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)
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")
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]
}
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});
/*Phoquing jour maudit il s'est rien passΓ© lΓ  tirez vous maintenant ...*/
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