Last active
December 10, 2017 00:45
-
-
Save ericlifka/5b5b3d46d76137d9877567f8806b6895 to your computer and use it in GitHub Desktop.
advent of code
This file contains hidden or 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
let numbers = | |
`... snip ...` | |
.split('') | |
.map(n => parseInt(n, 10)) | |
let sum = 0 | |
for (let index = 0; index < numbers.length; index++) | |
if (numbers[index] === numbers[(index + 1) % numbers.length]) | |
sum += numbers[index] | |
console.log('part1', sum) | |
let jump = numbers.length / 2 | |
sum = 0 | |
numbers.forEach((num, index, arr) => { | |
if (num === arr[(index + jump) % arr.length]) | |
sum += num | |
}) | |
console.log('part2', sum) |
This file contains hidden or 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
grid = | |
`... snip ...` | |
.split('\n') | |
.map(row => row | |
.split(/\s+/) | |
.map(n => parseInt(n, 10)) | |
.sort((l, r) => r - l)) | |
console.log('part1', | |
grid.reduce((total, row) => | |
total + Math.max.apply(null, row) - Math.min.apply(null, row) | |
, 0)) | |
console.log('part2', | |
grid.reduce((total, row) => { | |
let result = 0 | |
for (let outer = 0; outer <= row.length - 2; outer++) | |
for (let inner = outer + 1; inner <= row.length - 1; inner++) | |
if (row[outer] % row[inner] === 0) | |
result += row[outer] / row[inner] | |
return total + result | |
}, 0)) |
This file contains hidden or 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
let cache = { '0.0': 1 } | |
const coordToKey = ({x, y}) => `${x}.${y}` | |
const getVal = (coord) => cache[ coordToKey(coord) ] || 0 | |
const setVal = (coord, val) => cache[ coordToKey(coord) ] = val | |
const neighborCoords = ({x, y}) => | |
[ [1, 0], [-1, 0], [0, 1], [0, -1], [-1, 1], [1, -1], [1, 1], [-1, -1] ] | |
.map(([dx, dy]) => ({ x: x + dx, y: y + dy })) | |
function sequenceGenerator(start = 0) { | |
let seq = [ 1, 0, -1, 0 ] | |
let cur = start | |
return function () { | |
let val = seq[ cur ] | |
cur = (cur + 1) % seq.length | |
return val | |
} | |
} | |
function iterateSpiralNumbers(callback) { | |
let current = 1 | |
let blockSize = 1 | |
let coord = { x: 0, y: 0 } | |
let directionGenerators = { | |
x: sequenceGenerator(), | |
y: sequenceGenerator(3) | |
} | |
let direction = { | |
x: directionGenerators.x(), | |
y: directionGenerators.y() | |
} | |
while (true) { | |
for (let doTwice = 0; doTwice < 2; doTwice++) { | |
for (let blockIndex = 0; blockIndex < blockSize; blockIndex++) { | |
current++ | |
coord.x += direction.x | |
coord.y += direction.y | |
let result = callback(current, coord) | |
if (result !== undefined) | |
return result | |
} | |
direction.x = directionGenerators.x() | |
direction.y = directionGenerators.y() | |
} | |
blockSize++ | |
} | |
} | |
console.log('part1', | |
iterateSpiralNumbers((number, coord) => { | |
if (number === 312051) | |
return { distance: Math.abs(coord.x) + Math.abs(coord.y), coord } | |
})) | |
console.log('part2', | |
iterateSpiralNumbers((number, coord) => { | |
let sum = neighborCoords(coord) | |
.map(getVal) | |
.reduce((total, val) => total + val) | |
setVal(coord, sum) | |
if (sum > 312051) | |
return { sum, coord } | |
})) |
This file contains hidden or 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
let words = | |
`... snip ...` | |
console.log('part1', | |
words | |
.split('\n') | |
.map(passphrase => passphrase | |
.split(' ') | |
.sort()) | |
.reduce((total, passphrase) => { | |
for (let i = 0; i < passphrase.length - 1; i++) | |
if (passphrase[ i ] === passphrase[ i + 1 ]) | |
return total | |
return total + 1 | |
}, 0)) | |
console.log('part2', | |
words | |
.split('\n') | |
.map(passphrase => passphrase | |
.split(' ') | |
.map(word => word.split('').sort().join('')) | |
.sort()) | |
.reduce((total, passphrase) => { | |
for (let i = 0; i < passphrase.length - 1; i++) | |
if (passphrase[ i ] === passphrase[ i + 1 ]) | |
return total | |
return total + 1 | |
}, 0)) |
This file contains hidden or 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
let maze = | |
`...snip...` | |
.split('\n') | |
.map(n => parseInt(n, 10)) | |
let position = 0 | |
let steps = 0 | |
while (maze[ position ] !== undefined) { | |
let instruction = maze[ position ] | |
maze[ position ] += instruction >= 3 ? -1 : 1 | |
position += instruction | |
steps++ | |
} | |
console.log(steps) |
This file contains hidden or 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
let data = | |
`... snip ...` | |
.split(/\s+/) | |
.map(n => parseInt(n, 10)) | |
let cycles = 0 | |
let cache = { } | |
const saveState = () => cache[ data.join(',') ] = cycles | |
const stateRepeated = () => cache[ data.join(',') ] | |
const max = () => | |
data.indexOf(Math.max.apply(null, data)) | |
function distribute({ position, value }) { | |
while ( value > 0 ) { | |
position = (position + 1) % data.length | |
data[ position ]++ | |
value-- | |
} | |
} | |
function removeMax() { | |
let position = max() | |
let value = data[ position ] | |
data[ position ] = 0 | |
return { position, value } | |
} | |
while (!stateRepeated()) { | |
saveState() | |
distribute(removeMax()) | |
cycles++ | |
} | |
console.log(`cycles: ${cycles}, cycle time: ${cycles - stateRepeated()}`) |
This file contains hidden or 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 removeComma = str => | |
str[ str.length - 1 ] === ',' ? | |
str.slice(0, -1) : | |
str | |
const NODE_CACHE = { } | |
const cache = node => NODE_CACHE[ node.name ] = node | |
const lookup = name => NODE_CACHE[ name ] | |
const buildNode = ([ name, weight, arrow, ...children ]) => cache({ | |
name, | |
weight: parseInt(weight.slice(1, -1), 10), | |
children: arrow ? children.map(removeComma) : [ ] | |
}) | |
function link(node) { | |
node.children = node.children.map(lookup) | |
node.children.forEach(child => child.parent = node) | |
return node | |
} | |
const calcWeight = node => node.totalWeight = | |
node.children.length === 0 ? | |
node.weight : | |
node.children.map(calcWeight) | |
.reduce((total, weight) => total + weight, node.weight) | |
function findImbalance(node) { | |
let {children, children: {length}} = node | |
if (length === 0) // no children base case, assume self | |
return node | |
let weightBuckets = { } | |
children.forEach(child => weightBuckets[ child.totalWeight ] ? | |
weightBuckets[ child.totalWeight ].push(child) : | |
weightBuckets[ child.totalWeight ] = [ child ]) | |
let weights = Object.keys(weightBuckets) | |
if (weights.length === 1) // all children are balanced so _this_ is the node that's wrong | |
return node | |
let rightWeight = weights.find(weight => weightBuckets[ weight ].length !== 1) | |
let wrongWeight = weights.find(weight => weightBuckets[ weight ].length === 1) | |
let tree = weightBuckets[ wrongWeight ][ 0 ] | |
let wrongNode = findImbalance(tree) | |
if (tree === wrongNode) // we only want to do this on the one where we've found the exact wrong node, not heigher in the tree | |
console.log(`part2: ${wrongNode.name} weighs ${wrongNode.weight} should weigh ${rightWeight - wrongWeight + wrongNode.weight}`) | |
return wrongNode | |
} | |
let nodes = input() | |
.split('\n') | |
.map(desc => desc.split(' ')) | |
.map(buildNode) | |
.map(link) | |
let top = nodes[ 0 ] // pick any node and find the top of the tree | |
while (top.parent) | |
top = top.parent | |
console.log(`part1: ${top.name} is the top of the tree`) | |
calcWeight(top) | |
findImbalance(top) | |
function input() { | |
return `... snip ...` | |
} |
This file contains hidden or 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
let maxSeen = 0 | |
const registers = { } | |
const getR = register => registers[ register ] | |
const setR = (register, value) => { | |
registers[ register ] = value | |
if (value > maxSeen) | |
maxSeen = value | |
} | |
const splitChar = char => | |
str => str.split(char) | |
const actionFn = (register, direction, value) => | |
() => | |
setR(register, direction === 'inc' ? | |
getR(register) + value : | |
getR(register) - value) | |
const comparatorFn = (register, comparator, compValue) => | |
() => { | |
let regValue = getR(register) | |
switch (comparator) { | |
case '>': return regValue > compValue | |
case '<': return regValue < compValue | |
case '>=': return regValue >= compValue | |
case '<=': return regValue <= compValue | |
case '==': return regValue == compValue | |
case '!=': return regValue != compValue | |
} | |
} | |
const buildInstruction = ([ register, direction, value, _if, condRegister, comparator, compValue ]) => ({ | |
register, | |
action: actionFn(register, direction, parseInt(value, 10)), | |
predicate: comparatorFn(condRegister, comparator, parseInt(compValue, 10)) | |
}) | |
let instructions = input() | |
.split('\n') | |
.map(splitChar(' ')) | |
.map(buildInstruction) | |
instructions.forEach(({register}) => setR(register, 0)) | |
instructions.forEach(({register, action, predicate}) => { | |
if (predicate()) | |
action() | |
}) | |
let max = | |
Object.keys(registers) | |
.sort((l, r) => getR(r) - getR(l)) | |
.map(reg => ({reg, value: getR(reg)}))[ 0 ] | |
console.log('part1 max: ', max) | |
console.log('part2 max: ', maxSeen) | |
function input() { | |
return `... snip ...` | |
} |
This file contains hidden or 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 makeStream = (string, position = 0) => | |
() => string[ position++ ] | |
const makeGroup = parent => { | |
let group = { parent, children: [ ] } | |
if (parent) | |
parent.children.push(group) | |
return group | |
} | |
let char | |
let group | |
let inTrash = false | |
let trashCount = 0 | |
let stream = makeStream(getInput()) | |
while (char = stream()) { | |
if (inTrash && char === ">") | |
inTrash = false | |
else if (inTrash && char === "!") | |
stream() | |
else if (inTrash) | |
trashCount++ | |
else if (char === "<") | |
inTrash = true | |
else if (char === "{") | |
group = makeGroup(group) | |
else if (char === "}" && group.parent) | |
group = group.parent | |
} | |
const calcScore = (group, scoreLevel = 1) => | |
scoreLevel + group.children.reduce((score, group) => score + calcScore(group, scoreLevel + 1), 0) | |
console.log(`group score: ${calcScore(group)}, trash count: ${trashCount}`) | |
function getInput() { | |
return `... snip ...` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment