Last active
January 5, 2021 22:36
-
-
Save lantius/808a7b0c5f1ca55851a503668ecb2b87 to your computer and use it in GitHub Desktop.
AoC 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
4.2 | |
let a = s.split('\n\n'); | |
let valid = 0; | |
let rng = (v, min, max) => { return parseInt(v, 10) >= min && parseInt(v, 10) <= max; } | |
let byr = (v) => /^\d{4}$/.exec(v) && rng(v, 1920, 2002); | |
let iyr = (v) => /^\d{4}$/.exec(v) && rng(v, 2010, 2020); | |
let eyr = (v) => /^\d{4}$/.exec(v) && rng(v, 2020, 2030); | |
let hgt = (v) => /^\d+(?:cm|in)$/.exec(v) && (v.includes('cm') ? rng(v, 150, 193) : rng(v, 59, 76)); | |
let hcl = (v) => /^#[0-9a-f]{6}$/.exec(v); | |
let ecl = (v) => /^(?:amb|blu|brn|gry|grn|hzl|oth)$/.exec(v); | |
let pid = (v) => /^\d{9}$/.exec(v); | |
for (const p of a) { | |
let vf = 0; | |
let n,v; | |
for (const f of p.split(/\s/)) { | |
[n,v] = f.split(':'); | |
switch(n) { | |
case 'byr': | |
if (byr(v)) vf++; | |
break; | |
case 'iyr': | |
if (iyr(v)) vf++; | |
break; | |
case 'eyr': | |
if (eyr(v)) vf++; | |
break; | |
case 'hgt': | |
if (hgt(v)) vf++; | |
break; | |
case 'hcl': | |
if (hcl(v)) vf++; | |
break; | |
case 'ecl': | |
if (ecl(v)) vf++; | |
break; | |
case 'pid': | |
if (pid(v)) vf++; | |
break; | |
} | |
} | |
if (vf == 7) { | |
valid++; | |
console.log(p.split(/\s/).filter((f) => !f.includes('cid')).sort().map((f) => f.split(':')[1]).join('\t')); | |
} | |
} | |
valid; | |
6.1 | |
let t = 0; for (g of s.split('\n\n')) { for (let i = 0; i < 26; ++i) { const l = String.fromCharCode(97+i); if (g.includes(l)) t++ } } console.log(t); | |
6.2 | |
let t = 0; | |
let testGroup = (g, l) => { for (p of g.split('\n')) { if (!p.includes(l)) return false; } return true;}; | |
for (g of s.split('\n\n')) { for (let i = 0; i < 26; ++i) { const l = String.fromCharCode(97+i); if (testGroup(g, l)) { t++; } } } console.log(t); | |
7.1 | |
let a = s.split('\n').map((v) => v.split(" bags contain")).map((v) => { v[1] = v[1].trim(); return v; }).filter((v) => { return v[1] != "no other bags." }); | |
let tested = {}; | |
let q = []; | |
let test = (target) => { | |
for (const [b, c] of a) { | |
if (c.includes(target) && !tested[b]) { tested[b] = true; q.push(b); } | |
} | |
} | |
test('shiny gold'); | |
while(q.length) test(q.pop()); | |
console.log(Object.keys(tested).length); | |
7.2 | |
let a = s.split('\n').map((v) => v.split(" bags contain")).map((v) => { v[1] = v[1].trim(); return v; }).map((v) => { v[1] = v[1].split(','); return v; }); | |
let o = {}; | |
for (const [b, c] of a) o[b] = c; | |
let q = [['shiny gold', 1]]; | |
let sum = 0; | |
while (q.length) { | |
let [c, n] = q.pop(); | |
console.log(c, n); | |
sum += n; | |
for (b of o[c]) { | |
m = parseInt(b, 10); | |
for (cn of Object.keys(o)) { | |
if(b.includes(cn)) q.push([cn, m*n]) | |
} | |
} | |
} | |
console.log(sum - 1) | |
8.1 | |
let a = s.split('\n') | |
let acc = 0; | |
let run = (instr) => { | |
let i, v; [i, v] = instr.split(" "); | |
v = parseInt(v, 10); | |
console.log(i, v); | |
switch(i) { | |
case "nop": | |
return 1; | |
case "acc": | |
acc += v; | |
return 1; | |
case "jmp": | |
return v; | |
}}; | |
let cur = 0; | |
while (a[cur] !== undefined) { let instr = a[cur]; a[cur] = undefined; cur += run(instr); } console.log(acc); | |
8.2 | |
let poss = []; | |
let runatt = (swp) => { | |
let a = s.split('\n') | |
if (swp > 0) { | |
let instr = a[swp]; | |
let i, v; | |
[i, v] = instr.split(" "); | |
i === "nop" ? a[swp] = `jmp ${v}` : a[swp] = `nop ${v}`; | |
} | |
let acc = 0; | |
let run = (instr, cur) => { | |
let i, v; [i, v] = instr.split(" "); | |
v = parseInt(v, 10); | |
switch(i) { | |
case "nop": | |
if (swp < 0) poss.push(cur); | |
return 1; | |
case "acc": | |
acc += v; | |
return 1; | |
case "jmp": | |
if (swp < 0) poss.push(cur); | |
return v; | |
}}; | |
let cur = 0; | |
while (a[cur] !== undefined) { let instr = a[cur]; a[cur] = undefined; cur += run(instr, cur); if(cur >= a.length) return acc; } return undefined; | |
} | |
runatt(-1); | |
let finalval; for (let p of poss) { finalval = runatt(p); if (finalval !== undefined) break; } console.log(finalval); | |
9.1: | |
let a = s.split('\n').map(n => parseInt(n, 10)) | |
let win = 25; | |
let test = (pre, v) => { pre.sort(); for (let i = 0; i < pre.length; i++) for (let j = i; j < pre.length; j++) { if (pre[i] + pre[j] === v) return true; } return false; }; | |
for (let i = win; i < a.length; ++i) { let pre = a.slice(i - win, i); if (!test(pre, a[i])) { console.log(a[i]); break; } } | |
9.2: | |
let a = s.split('\n').map(n => parseInt(n, 10)); | |
let v = 1124361034; let l = 0; let r = 1; let t = a[0] + a[1]; while(r < a.length && t != v) { if (t < v) t+= a[++r]; if (t > v) t-= a[l++]; } g = a.slice(l, r+1).sort(); console.log(g[0] + g[g.length-1]) | |
10.1 | |
let a = s.split('\n').map(n => parseInt(n, 10)).sort((a, b) => { return a - b } ); | |
let diffs = [0, 0, 0, 1]; | |
let tj = 0; | |
for (j of a) { diffs[j - tj]++; tj = j }; console.log(diffs) | |
10.2 | |
let a = s.split('\n').map(n => parseInt(n, 10)).sort((a, b) => { return a-b } ); | |
let b = new Array(a.length); | |
a.unshift(0); | |
b.unshift(1); | |
let p = 0; | |
for (let i = 1; i < a.length; i++) { b[i] = 0; for (let j = i - 1; j >= 0 && a[i] - a[j] <= 3; j--) { console.log(i, a[i], a[j]); b[i]+=b[j]}} | |
11.1 | |
let a = s.split('\n').map((r) => r.split('')); | |
let o = (r, c, a) => { | |
let s = 0; | |
let row = a[r]; | |
if (c > 0 && row[c-1] === '#') s++; | |
if (row[c+1] === '#') s++; | |
if (r > 0) { | |
let row = a[r-1]; | |
if (c > 0 && row[c-1] === '#') s++; | |
if (row[c] === '#') s++; | |
if (row[c+1] === '#') s++; | |
} | |
if (r < a.length - 1) { | |
let row = a[r+1]; | |
if (c > 0 && row[c-1] === '#') s++; | |
if (row[c] === '#') s++; | |
if (row[c+1] === '#') s++; | |
} | |
return s; | |
} | |
let ua = (a, b) => { | |
let changed = false; | |
for (let r = 0; r < a.length; r++) for (c = 0; c < a[r].length; c++) changed = u(r, c, a, b) || changed; | |
return changed; | |
} | |
let u = (r, c, a, b) => { | |
if (a[r][c] === '.') return false; | |
if (a[r][c] === 'L' && o(r, c, a) === 0) { b[r][c] = '#'; return true; } | |
if (a[r][c] === '#' && o(r, c, a) >= 4) { b[r][c] = 'L'; return true; } | |
return false; | |
} | |
let changed = true; | |
let i = 0; | |
for (i = 0; i < 100000 && changed; i++) { | |
let b = JSON.parse(JSON.stringify(a)); | |
changed = ua(a, b); | |
a = b; | |
} | |
f = a.map((r) => r.join('')).join('\n'); | |
console.log(`${i} iterations`); | |
f.match(/#/g).length; | |
11.2 | |
let a = s.split('\n').map((r) => r.split('')); | |
let ray = (r, c, a, u, v) => { | |
let row = r + u; | |
let col = c + v; | |
while(row >= 0 && row < a.length && col >= 0 & col < a[row].length) { | |
if (a[row][col] === '#') return 1; | |
if (a[row][col] === 'L') return 0; | |
row += u; | |
col += v; | |
} | |
return 0; | |
} | |
let o = (r, c, a) => { | |
let seen = 0; | |
seen += ray(r, c, a, -1, -1); | |
seen += ray(r, c, a, -1, 0); | |
seen += ray(r, c, a, -1, 1); | |
seen += ray(r, c, a, 0, -1); | |
seen += ray(r, c, a, 0, 1); | |
seen += ray(r, c, a, 1, -1); | |
seen += ray(r, c, a, 1, 0); | |
seen += ray(r, c, a, 1, 1); | |
return seen; | |
} | |
let ua = (a, b) => { | |
let changed = false; | |
for (let r = 0; r < a.length; r++) for (c = 0; c < a[r].length; c++) changed = u(r, c, a, b) || changed; | |
return changed; | |
} | |
let u = (r, c, a, b) => { | |
if (a[r][c] === '.') return false; | |
if (a[r][c] === 'L' && o(r, c, a) === 0) { b[r][c] = '#'; return true; } | |
if (a[r][c] === '#' && o(r, c, a) >= 5) { b[r][c] = 'L'; return true; } | |
return false; | |
} | |
let changed = true; | |
let i = 0; | |
for (i = 0; i < 100000 && changed; i++) { | |
let b = JSON.parse(JSON.stringify(a)); | |
changed = ua(a, b); | |
a = b; | |
} | |
f = a.map((r) => r.join('')).join('\n'); | |
console.log(`${i} iterations`); | |
f.match(/#/g).length; | |
12.1 | |
let a = s.split('\n'); | |
let pos = [0,0]; | |
let h = 0; | |
let hvec = [Math.round(Math.cos(0 * Math.PI/180)), Math.round(Math.sin(0 * Math.PI/180))]; | |
for (c of a) { | |
let t = c.match(/F(\d+)/); | |
if (t) { | |
pos[0] += hvec[0] * parseInt(t[1], 10); | |
pos[1] += hvec[1] * parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/N(\d+)/); | |
if (t) { | |
pos[1] += parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/S(\d+)/); | |
if (t) { | |
pos[1] -= parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/E(\d+)/); | |
if (t) { | |
pos[0] += parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/W(\d+)/); | |
if (t) { | |
pos[0] -= parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/R(\d+)/); | |
if (t) { | |
let r = parseInt(t[1], 10); | |
h = (h - r) % 360; | |
hvec = [Math.round(Math.cos(h * Math.PI/180)), Math.round(Math.sin(h * Math.PI/180))] | |
continue; | |
} | |
t = c.match(/L(\d+)/); | |
if (t) { | |
let r = parseInt(t[1], 10); | |
h = (h + r) % 360; | |
hvec = [Math.round(Math.cos(h * Math.PI/180)), Math.round(Math.sin(h * Math.PI/180))] | |
continue; | |
} | |
} | |
Math.abs(pos[0]) + Math.abs(pos[1]); | |
12.2 | |
let a = s.split('\n'); | |
let pos = [0,0]; | |
let wpt = [10, 1]; | |
for (c of a) { | |
let t = c.match(/F(\d+)/); | |
if (t) { | |
pos[0] += wpt[0] * parseInt(t[1], 10); | |
pos[1] += wpt[1] * parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/N(\d+)/); | |
if (t) { | |
wpt[1] += parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/S(\d+)/); | |
if (t) { | |
wpt[1] -= parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/E(\d+)/); | |
if (t) { | |
wpt[0] += parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/W(\d+)/); | |
if (t) { | |
wpt[0] -= parseInt(t[1], 10); | |
continue; | |
} | |
t = c.match(/R(\d+)/); | |
if (t) { | |
let r = -parseInt(t[1], 10) * Math.PI/180; | |
let sinr = Math.round(Math.sin(r)); | |
let cosr = Math.round(Math.cos(r)); | |
wpt = [wpt[0] * cosr - wpt[1] * sinr, | |
wpt[0] * sinr + wpt[1] * cosr] | |
continue; | |
} | |
t = c.match(/L(\d+)/); | |
if (t) { | |
let r = parseInt(t[1], 10) * Math.PI/180; | |
let sinr = Math.round(Math.sin(r)); | |
let cosr = Math.round(Math.cos(r)); | |
wpt = [wpt[0] * cosr - wpt[1] * sinr, | |
wpt[0] * sinr + wpt[1] * cosr] | |
continue; | |
} | |
} | |
13.1 | |
let t, d; | |
[t, d] = s.split('\n'); | |
t = parseInt(t, 10); | |
d = d.split(',').filter((v) => v !== 'x').map((v) => parseInt(v, 10)).map((v) => [v, v - t % v]).sort((a, b) => a[1] - b[1]); | |
d[0][0] * d[0][1]; | |
13.2 | |
d = s.split(',').map((v) => parseInt(v, 10)); | |
let e = []; | |
for (let i = 0; i < d.length; i++) if (!isNaN(d[i])) e.push([d[i], d[i] - i % d[i]]); | |
let prod = e.map((v) => v[0]).reduce((acc, cur) => acc * cur); | |
let gcde = (a, b) => { | |
let x = 0; | |
let y = 1; | |
let gcd = b; | |
if (a === 0) return [gcd, x, y]; | |
[gcd, x, y] = gcde(b % a, a); | |
return [gcd, y - Math.floor(b/a) * x, x]; | |
} | |
let mi = (a, m) => { | |
[gcd, x, y] = gcde(a, m); | |
return (x % m + m) % m | |
} | |
result = BigInt(0); | |
for (const v of e) { | |
let pn = (prod / v[0]); | |
let inv = mi(pn, v[0]); | |
result += BigInt(BigInt(v[1]) * BigInt(inv) * BigInt(pn)) % BigInt(prod) | |
} | |
result % BigInt(prod); | |
14.1 | |
let p = s.split('\n'); | |
let mask = ''; | |
let memory = new Array(36); | |
let tobin = (v) => { | |
let a = []; | |
for (let i = 0; i < 36; i++) { | |
a.unshift(Math.floor(v / Math.pow(2,i)) % 2) | |
} | |
return a; | |
} | |
let frombin = (a) => { | |
return a.reverse().reduce((acc, cur, i) => acc += cur * Math.pow(2,i)); | |
} | |
for (const l of p) { | |
let mg = l.match(/mask = ([X10]+)/); | |
if (mg) { | |
mask = mg[1]; | |
} else { | |
let mem = l.match(/mem\[(\d+)\] = (\d+)/); | |
let addr = mem[1]; | |
let val = mem[2]; | |
let binv = tobin(val); | |
binv = binv.map((v, i) => mask[i] === 'X' ? v : parseInt(mask[i], 2)); | |
memory[addr] = frombin(binv); | |
} | |
} | |
memory.reduce((acc, cur) => acc += cur); | |
14.2 | |
let p = s.split('\n'); | |
let mask = ''; | |
let maskbits = []; | |
let memory = {}; | |
let tobin = (v) => { | |
let a = []; | |
for (let i = 0; i < 36; i++) { | |
a.unshift(Math.floor(v / Math.pow(2,i)) % 2) | |
} | |
return a; | |
} | |
let frombin = (a) => { | |
return a.slice().reverse().reduce((acc, cur, i) => acc += cur * Math.pow(2,i)); | |
} | |
for (const l of p) { | |
let mg = l.match(/mask = ([X10]+)/); | |
if (mg) { | |
mask = mg[1]; | |
maskbits = mask.split('').reverse().map((v, i) => v === 'X' ? i : null).filter((v) => v !== null); | |
maskmul = maskbits.map((v) => Math.pow(2, v)); | |
perms = []; | |
for (let i = 0; i < Math.pow(2, maskmul.length); ++i) { | |
let perm = 0; | |
for (let j = 0; j < maskmul.length; j++) { | |
let m = Math.floor(i / Math.pow(2,j)) % 2; | |
perm += m * maskmul[j]; | |
} | |
perms.push(perm); | |
} | |
} else { | |
let mem = l.match(/mem\[(\d+)\] = (\d+)/); | |
let addr = parseInt(mem[1], 10); | |
let val = parseInt(mem[2], 10); | |
let binaddr = tobin(addr); | |
binaddr = binaddr.map((v, i) => mask[i] === '1' ? 1 : v); | |
binaddr = binaddr.map((v, i) => mask[i] === 'X' ? 0 : v); | |
let oa = frombin(binaddr); | |
for (let perm of perms) { | |
memory[(oa + perm).toString(2)] = val; | |
} | |
} | |
} | |
let t = 0; | |
for (v of Object.values(memory)) t+= v; | |
t; | |
15.1 15.2 | |
let a = s.split(','); | |
let sp = new Map(); | |
let last = 0; | |
for (let i = 1; i < a.length + 1; i++) { | |
last = parseInt(a[i-1], 10); | |
sp.set(last, i); | |
} | |
let next = 0; | |
for (let i = a.length + 1; i < 30000000; i++) { | |
let v = sp.get(next); | |
sp.set(next, i); | |
if (v === undefined) { | |
next = 0; | |
} else { | |
next = i - v; | |
} | |
} | |
next; | |
16.1 | |
let a = s.split('\n'); | |
let rules = []; | |
let i = 0; | |
for (; i < a.length && a[i] != ""; i++) { | |
let r = a[i].match(/(\d+)-(\d+) or (\d+)-(\d+)/); | |
rules.push({la: r[1], ha: r[2], lb: r[3], hb: r[4]}); | |
} | |
while (a[i] != 'nearby tickets:' && i < a.length) i++; | |
let err = 0; | |
for (i+=1; i < a.length; i++) { | |
let t = a[i].split(','); | |
for (let v of t) { | |
v = parseInt(v, 10); | |
let valid = false; | |
for (const {la, ha, lb, hb} of rules) { | |
if ((v >= la && v <= ha) || (v >= lb && v <= hb)) valid = true; | |
} | |
if (!valid) err += v; | |
} | |
} | |
err; | |
16.2 | |
let target = 'departure'; | |
let a = s.split('\n'); | |
let rules = []; | |
let i = 0; | |
for (; i < a.length && a[i] != ""; i++) { | |
let r = a[i].match(/(\d+)-(\d+) or (\d+)-(\d+)/); | |
let rule = {la: r[1], ha: r[2], lb: r[3], hb: r[4]}; | |
if (a[i].startsWith(target)) rule['target'] = true; | |
rules.push(rule); | |
} | |
for (let j = 0; j < rules.length; j++) { | |
rules[j]['possiblefields'] = new Set([...rules.keys()]); | |
} | |
while (a[i] != 'nearby tickets:' && i < a.length) i++; | |
for (i+=1; i < a.length; i++) { | |
let t = a[i].split(',').map(v => parseInt(v, 10)); | |
let tvr = []; | |
for (let v of t) { | |
let validrules = []; | |
for (let j = 0; j < rules.length; j++) { | |
let {la, ha, lb, hb} = rules[j]; | |
if ((v >= la && v <= ha) || (v >= lb && v <= hb)) { | |
validrules.push(j); | |
} | |
} | |
if (validrules.length) tvr.push(validrules); | |
} | |
if (tvr.length === t.length) { | |
for (let j = 0; j < rules.length; j++) { | |
let rp = rules[j]['possiblefields']; | |
for (let k = 0; k < tvr.length; k++) { | |
let vr = new Set(tvr[k]); | |
if(!vr.has(j)) rp.delete(k); | |
} | |
} | |
} | |
} | |
for (let r of rules) r['opf'] = [...r['possiblefields']]; | |
for (let i = 0; i < rules.length; i++) { | |
for (let j = 0; j < rules.length; j++) { | |
let r = rules[j]; | |
if (r['possiblefields'].size === 1) { | |
let f = [...r['possiblefields']][0]; | |
r['field'] = f; | |
for (let k = 0; k < rules.length; k++) { | |
rules[k]['possiblefields'].delete(f); | |
} | |
break; | |
} | |
} | |
} | |
i = 0; | |
while (a[i] != 'your ticket:' && i < a.length) i++; | |
let yt = a[i+1].split(',').map(v => parseInt(v, 10)); | |
let tot = 1; | |
for (let r of rules) { | |
if (r['target']) { | |
let field = r['field']; | |
console.log(`field ${field}: ${yt[field]}`); | |
tot *= yt[field]; | |
} | |
} | |
tot; | |
18.1 | |
let a = s.split('\n').map(l => l.split('')); | |
let m = (x) => { | |
let r = 0; | |
let op = '+'; | |
for (let i = 0; i < x.length; i++) { | |
let t = x[i].trim(); | |
if (t == '') continue; | |
if (t == '+' || t == '*') { | |
op = t; | |
} else if (t == '(') { | |
let sx = []; | |
let np = 1; | |
for (i+=1; i < x.length && np > 0; i++) { | |
if (x[i].trim() == ')') np--; | |
if (x[i].trim() == '(') np++; | |
if (np > 0) sx.push(x[i]); | |
} | |
let sr = m(sx); | |
r = op == '+' ? r + sr : r * sr; | |
} else { | |
let v = parseInt(t, 10); | |
if (isNaN(v)) console.log(`${t} NaN at position ${i}`); | |
r = op == '+' ? r + v : r * v; | |
} | |
} | |
return r; | |
}; | |
let tot = 0; | |
for (let x of a) { | |
tot += m(x); | |
} | |
tot; | |
18.2 | |
let a = s.split('\n').map(l => l.split('')); | |
let p = {'+': 1, '*': 0}; | |
let m = (x) => { | |
let q = []; | |
let s = []; | |
for (let t of x) { | |
t = t.trim(); | |
let v = parseInt(t, 10); | |
if (!isNaN(v)) { | |
q.push(v); | |
} else if (t === '*' || t === '+') { | |
while(s.length > 0 && p[s[0]] > p[t] && p[s[0]] != '(') { | |
q.push(s.shift()); | |
} | |
s.unshift(t); | |
} | |
else if (t === '(') { | |
s.unshift(t); | |
} | |
else if (t === ')') { | |
while(s.length > 0 && s[0] != '(') { | |
q.push(s.shift()); | |
} | |
if (s.length === 0) console.log('unbalanced parens'); | |
if (s[0] == '(') s.shift(); | |
} | |
} | |
while (s.length > 0) { | |
q.push(s.shift()); | |
} | |
s = []; | |
for (let t of q) { | |
if (t !== '*' && t !== '+') s.push(t); | |
else if (t === '+') s.push(s.pop() + s.pop()); | |
else if (t === '*') s.push(s.pop() * s.pop()); | |
} | |
return s[0]; | |
} | |
let tot = 0; | |
for (let x of a) { | |
tot += m(x); | |
} | |
tot; | |
19.1 | |
let a = s.split('\n\n'); | |
let ra = a[0].split('\n').map(r => r.split(':')); | |
let mst = a[1].split('\n'); | |
let c = ''; | |
let rules = []; | |
for (let r of ra) { | |
rules[parseInt(r[0], 10)] = r[1].trim(); | |
} | |
let er = (m, rt) => { | |
// console.log(`${m} ${rt}`); | |
if (m.length === 0) return 0; | |
let r = rt.split('|'); | |
if (r.length > 1) { | |
let v0 = er(m, r[0].trim()); | |
let v1 = er(m, r[1].trim()); | |
if (v0 && v1) console.log('huh?'); | |
if (v0) return v0; | |
if (v1) return v1; | |
return 0; | |
} | |
r = rt.split(' '); | |
let cons = 0; | |
for (let i = 0; i < r.length; i++) { | |
let rn = parseInt(r[i], 10); | |
if (isNaN(rn)) { | |
if (r[i] == `"${m[0]}"`) return 1; | |
return 0; | |
} | |
let v = er(m.slice(cons), rules[rn]); | |
if (!v) return 0; | |
cons += v; | |
} | |
return cons; | |
} | |
let tot = 0; | |
for (let m of mst) { | |
let v = er(m, rules[0]); | |
if (v == m.length) tot++; | |
} | |
tot; | |
19.2 | |
let a = s.split('\n\n'); | |
let ra = a[0].split('\n').map(r => r.split(':')); | |
let mst = a[1].split('\n'); | |
let c = ''; | |
let rules = []; | |
for (let r of ra) { | |
let pr = r[1].trim(); | |
if (!pr.includes('"')) { | |
pr = pr.split('|').map(v => v.trim().split(' ').map(v => parseInt(v, 10))); | |
} | |
rules[parseInt(r[0], 10)] = pr; | |
} | |
rules[8] = [[42], [42,8]]; | |
rules[11] = [[42, 31], [42, 11, 31]]; | |
let er = (m, rr) => { | |
if (!m.length || !rr.length) return !m.length && !rr.length; | |
r = rules[rr[0]]; | |
if (r.includes('"')) { | |
if (r != `"${m[0]}"`) return false; | |
return er(m.slice(1), rr.slice(1)); | |
} else { | |
return r.some(t => { let rt = t.concat(rr.slice(1)); return er(m, rt); }); | |
} | |
} | |
let tot = 0; | |
for (let m of mst) { | |
if (er(m, [0])) tot++; | |
} | |
tot; | |
20.1 | |
let ta = s.split('\n\n').map(t => t.split(':\n')); | |
let tb = []; | |
for (let t of ta) { | |
let b = []; | |
b[0] = parseInt(t[0].slice(5), 10); | |
b[1] = []; | |
let tr = t[1].split('\n'); | |
let tc = tr.map(r => r.split('')); | |
b[1][0] = tr[0]; | |
b[1][1] = tc.reduce((acc, v) => acc + v[tr[0].length - 1], '') | |
b[1][2] = tr[tr.length - 1]; | |
b[1][3] = tc.reduce((acc, v) => acc + v[0], '') | |
tb.push(b); | |
} | |
let edges = {}; | |
for (let t of tb) { | |
let tn = t[0]; | |
let te = t[1]; | |
for (let e of te) { | |
if (!edges[e]) edges[e] = []; | |
edges[e].push(tn); | |
let re = e.split('').reverse().join(''); | |
if (!edges[re]) edges[re] = []; | |
edges[re].push(tn); | |
} | |
} | |
let tsec = {}; | |
for (let v of Object.values(edges)) { | |
if (v.length > 1) continue; | |
let tn = v[0]; | |
if (!tsec[tn]) tsec[tn] = 0; | |
tsec[tn]++; | |
} | |
let tot = BigInt(1); | |
for (let k of Object.keys(tsec)) { | |
if(tsec[k] == '4') { | |
tot *= BigInt(k); | |
} | |
} | |
tot; | |
20.2 | |
let ta = s.split('\n\n').map(t => t.split(':\n')); | |
for (let t of ta) { | |
t[0] = parseInt(t[0].slice(5), 10); | |
} | |
let tb = {}; | |
for (let t of ta) { | |
let b = []; | |
let tr = t[1].split('\n'); | |
let tc = tr.map(r => r.split('')); | |
b[0] = tr[0]; | |
b[1] = tc.reduce((acc, v) => acc + v[tr[0].length - 1], '') | |
b[2] = tr[tr.length - 1]; | |
b[3] = tc.reduce((acc, v) => acc + v[0], '') | |
tb[t[0]] = b; | |
} | |
let edges = {}; | |
for (let tn of Object.keys(tb)) { | |
tn = parseInt(tn, 10); | |
let te = tb[tn]; | |
for (let i = 0; i < te.length; i++) { | |
let e = te[i]; | |
if (!edges[e]) edges[e] = []; | |
edges[e].push([tn, i]); | |
let re = e.split('').reverse().join(''); | |
if (!edges[re]) edges[re] = []; | |
edges[re].push([tn, i]); | |
} | |
} | |
let tm = {}; | |
for (let ek of Object.keys(edges)) { | |
let ma = edges[ek]; | |
if (ma.length == 1) { | |
let [tn, dir] = ma[0]; | |
if (!tm[tn]) tm[tn] = []; | |
tm[tn][dir] = [undefined, ek]; | |
} | |
if (ma.length == 2) { | |
let [tna, dira] = ma[0]; | |
let [tnb, dirb] = ma[1]; | |
if (!tm[tna]) tm[tna] = []; | |
if (!tm[tnb]) tm[tnb] = []; | |
tm[tna][dira] = [tnb, ek]; | |
tm[tnb][dirb] = [tna, ek]; | |
} | |
} | |
let ti = {}; | |
for (let t of ta) { | |
ti[t[0]] = t[1]; | |
} | |
let flipv = (img) => { | |
return img.split('\n').reverse().join('\n'); | |
} | |
let fliph = (img) => { | |
return img.split('\n').map(r => r.split('').reverse().join('')).join('\n'); | |
} | |
let rotr = (img) => { | |
img = img.split('\n'); | |
let newimg = []; | |
let d = img.length - 1; | |
for (let i = 0; i < img[0].length; i++) { | |
newimg[i] = []; | |
for (let j = 0; j < img.length; j++) { | |
newimg[i][d - j] = img[j][i]; | |
} | |
} | |
return newimg.map(r => r.join('')).join('\n'); | |
} | |
let dorotr = (n) => { | |
ti[n] = rotr(ti[n]); | |
tm[n] = [tm[n][3], tm[n][0], tm[n][1], tm[n][2]]; | |
tb[n] = [tb[n][3], tb[n][0], tb[n][1], tb[n][2]]; | |
}; | |
let tf = (t, n) => { | |
let ip = (tm[t].indexOf(n) + 2) % 4; | |
let rp = tm[n].indexOf(t); | |
while (ip != rp) { | |
dorotr(n); | |
rp = tm[n].indexOf(t); | |
} | |
let te = tb[t][ip]; | |
let ne = tb[n][ip]; | |
if (te == ne) return; | |
if (te !== ne.split('').reverse().join('')) console.log('no match?') | |
if (ip % 2 == 1) { | |
let tmp = tm[n][0]; | |
tm[n][0] = tm[n][2]; | |
tm[n][2] = tmp; | |
ti[n] = flipv(ti[n]); | |
} else { | |
let tmp = tm[n][1]; | |
tm[n][1] = tm[n][3]; | |
tm[n][3] = tmp; | |
ti[n] = fliph(ti[n]); | |
} | |
} | |
21.1 | |
let a = s.split('\n').map(v => v.split('(contains ')); | |
let agns = new Set(); | |
let igds = new Set(); | |
for (let i of a) { | |
if (i[1].includes(')')) i[1] = i[1].slice(0, i[1].length - 1); | |
i[0] = new Set(i[0].trim().split(' ')); | |
i[1] = new Set(i[1].split(',').map(v => v.trim())); | |
for (let igd of i[0]) { | |
igds.add(igd); | |
} | |
for (let agn of i[1]) { | |
agns.add(agn); | |
} | |
} | |
let d = {}; | |
for (let agn of agns) { | |
let igd = undefined; | |
for (let r of a) { | |
if (!r[1].has(agn)) continue; | |
if (!igd) igd = new Set([...r[0]]); | |
igd = new Set([...r[0]].filter(x => igd.has(x))); | |
} | |
d[agn] = igd; | |
} | |
let oki = igds; | |
for (let agn of agns) { | |
oki = new Set([...oki].filter(x => !d[agn].has(x))); | |
} | |
let tot = 0; | |
for (let i of a) { | |
tot += new Set([...i[0]].filter(x => oki.has(x))).size; | |
} | |
tot; | |
21.2 | |
let a = s.split('\n').map(v => v.split('(contains ')); | |
let agns = new Set(); | |
let igds = new Set(); | |
for (let i of a) { | |
if (i[1].includes(')')) i[1] = i[1].slice(0, i[1].length - 1); | |
i[0] = new Set(i[0].trim().split(' ')); | |
i[1] = new Set(i[1].split(',').map(v => v.trim())); | |
for (let igd of i[0]) { | |
igds.add(igd); | |
} | |
for (let agn of i[1]) { | |
agns.add(agn); | |
} | |
} | |
let d = {}; | |
for (let agn of agns) { | |
let igd = undefined; | |
for (let r of a) { | |
if (!r[1].has(agn)) continue; | |
if (!igd) igd = new Set([...r[0]]); | |
igd = new Set([...r[0]].filter(x => igd.has(x))); | |
} | |
d[agn] = igd; | |
} | |
for (let i = 0; i < 1000 && [...Object.values(d)].reduce((acc, cur) => acc + cur.size, 0) > [...Object.values(d)].length; i++) { | |
for (let k of Object.keys(d)) { | |
if (d[k].size == 1) { | |
for (let j of Object.keys(d)) { | |
if (k === j) continue; | |
d[j].delete([...d[k]][0]); | |
} | |
} | |
} | |
} | |
let r = []; | |
for (let k of Object.keys(d).sort()) { | |
r.push([...d[k]][0]); | |
} | |
r.join(',') | |
22.1 | |
let [p1, p2] = s.split('\n\n').map(p => p.split('\n').slice(1).map(v => parseInt(v, 10))); | |
for (let i = 0; i < 1000 && p1.length && p2.length; i++) { | |
let c1 = p1.shift(); | |
let c2 = p2.shift(); | |
if (c1 > c2) { | |
p1.push(c1); | |
p1.push(c2); | |
} else { | |
p2.push(c2); | |
p2.push(c1); | |
} | |
} | |
let w = p1.length ? p1 : p2; | |
let sc = 0; | |
for (let i = 0; i < w.length; i++) { | |
sc += w[i] * (w.length - i); | |
} | |
sc; | |
23.1 | |
let a = s.split('').map(v => parseInt(v, 10)); | |
let cp = 0; | |
let max = Math.max(...a); | |
let min = Math.min(...a); | |
for (let i = 0; i < 100; i++) { | |
let p1 = (cp + 1) % a.length; | |
let p2 = (cp + 2) % a.length; | |
let p3 = (cp + 3) % a.length; | |
let p = [a[p1], a[p2], a[p3]]; | |
console.log(`a ${a.map((v, i) => i == cp ? `(${v})` : v).join(' ')}`); | |
a[p1] = a[p2] = a[p3] = undefined; | |
console.log(`p ${p.join(', ')}`); | |
let cv = a[cp]; | |
let d = cv - 1; | |
let di = a.indexOf(d); | |
while (di == -1) { | |
d--; | |
if (d < min) d = max; | |
di = a.indexOf(d); | |
} | |
console.log(`d ${d}`); | |
if (di === -1) console.log(`no ${d}?`); | |
a.splice(di + 1, 0, ...p); | |
a = a.filter(v => v !== undefined); | |
cp = a.indexOf(cv); | |
cp = (cp + 1) % a.length; | |
} | |
let tot = ''; | |
let off = a.indexOf(1) + 1; | |
for (let i = 0; i < a.length - 1; i++) { | |
tot += a[(off + i) % a.length]; | |
} | |
tot; | |
23.2 | |
let a = s.split('').map(v => parseInt(v, 10)); | |
let om = 1000000; | |
let min = 1; | |
let max = om; | |
for (let i = a.length + 1; i <= om; i++) { | |
a.push(i); | |
} | |
let b = new Uint32Array(a.length + 1); | |
for (let i = 0; i < a.length - 1; i++) { | |
b[a[i]] = a[i+1]; | |
} | |
b[a[a.length - 1]] = a[0]; | |
let pb = (l) => { | |
let x = []; | |
x.push(1); | |
let v = b[1]; | |
for(let i = 0; i < l; i++) { | |
x.push(v); | |
v = b[v]; | |
} | |
return x; | |
} | |
let cp = a[0]; | |
for (let i = 0; i < 10*om; i++) { | |
let p1 = b[cp]; | |
let p2 = b[p1]; | |
let p3 = b[p2]; | |
let d = cp - 1; | |
while (d === p1 || d === p2 || d === p3 || d === 0) { d--; if (d < min) d = max; } | |
let q = b[d]; | |
b[d] = p1; | |
b[cp] = b[p3]; | |
b[p3] = q; | |
cp = b[cp]; | |
} | |
let v1 = b[1]; | |
let v2 = b[v1]; | |
console.log(`${v1} x ${v2} = ${v1 * v2}`); | |
24.1 | |
let a = s.split('\n'); | |
let parse = (dir) => { | |
dir = dir.split(''); | |
let da = []; | |
while (dir.length) { | |
let c = dir.shift(); | |
if (c == 'e' || c == 'w') { | |
da.push(c); | |
} else { | |
c += dir.shift(); | |
da.push(c); | |
} | |
} | |
return da; | |
} | |
let coords = {}; | |
let hex = { | |
'e': { q: 1, r: 0}, | |
'ne': { q: 1, r: -1}, | |
'nw': { q: 0, r: -1}, | |
'w': { q: -1, r: 0}, | |
'sw': { q: -1, r: 1}, | |
'se': { q: 0, r: 1}, | |
} | |
for (let d of a) { | |
let da = parse(d); | |
let r = 0; | |
let q = 0; | |
for (let step of da){ | |
let s = hex[step]; | |
r += s.r; | |
q += s.q; | |
} | |
let coord = `${q},${r}`; | |
if (!coords[coord]) { | |
coords[coord] = true; | |
} else { | |
coords[coord] = false; | |
} | |
} | |
Object.values(coords).filter(v => v).length; | |
24.2 | |
let a = s.split('\n'); | |
let parse = (dir) => { | |
dir = dir.split(''); | |
let da = []; | |
while (dir.length) { | |
let c = dir.shift(); | |
if (c == 'e' || c == 'w') { | |
da.push(c); | |
} else { | |
c += dir.shift(); | |
da.push(c); | |
} | |
} | |
return da; | |
} | |
let coords = {}; | |
let hex = { | |
'e': { q: 1, r: 0}, | |
'ne': { q: 1, r: -1}, | |
'nw': { q: 0, r: -1}, | |
'w': { q: -1, r: 0}, | |
'sw': { q: -1, r: 1}, | |
'se': { q: 0, r: 1}, | |
} | |
let hexf = (q, r, d) => { | |
let s = hex[d]; | |
return [q + s.q, r + s.r]; | |
} | |
for (let d of a) { | |
let da = parse(d); | |
let r = 0; | |
let q = 0; | |
for (let step of da){ | |
[q, r] = hexf(q, r, step); | |
} | |
let coord = `${q},${r}`; | |
if (!coords[coord]) { | |
coords[coord] = true; | |
} else { | |
coords[coord] = false; | |
} | |
} | |
let cbn = (q, r) => { | |
let bn = 0; | |
for (dir in hex) { | |
let cc = hexf(q, r, dir).join(','); | |
if (coords[cc]) bn++; | |
} | |
return bn; | |
} | |
for (let i = 0; i < 100; i++) { | |
let newc = {}; | |
for (let c of Object.keys(coords)) { | |
if (coords[c]) { | |
let [q, r] = c.split(',').map(v => parseInt(v, 10)); | |
let bn = cbn(q, r); | |
if (bn == 1 || bn == 2) newc[c] = true; | |
for (dir in hex) { | |
let [qn, rn] = hexf(q, r, dir); | |
let cn = [qn, rn].join(','); | |
if (!coords[cn]) { | |
let bn = cbn(qn, rn); | |
if (bn === 2) newc[cn] = true; | |
} | |
} | |
} | |
} | |
coords = JSON.parse(JSON.stringify(newc)) | |
} | |
Object.values(coords).filter(v => v).length; | |
25.1 | |
let [c, d] = s.split('\n').map(v => parseInt(v, 10)); | |
let t = (s, l) => { | |
let v = 1; | |
for (let i = 0; i < l; i++) { | |
v = (v * s) % 20201227; | |
} | |
return v; | |
} | |
let cl = 0; | |
let dl = 0; | |
let v = 1; | |
for (let l = 1; l < 10000000; l++) { | |
v = (7 * v) % 20201227; | |
if (!cl && v === c) cl = l; | |
if (!dl && v === d) dl = l; | |
if (cl && dl) break; | |
} | |
if (cl && dl) { | |
let ce = t(d, cl); | |
let de = t(c, dl); | |
console.log(ce, de); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment