Skip to content

Instantly share code, notes, and snippets.

@ZeikJT
Last active December 27, 2017 18:09
Show Gist options
  • Save ZeikJT/5510b783ad180792cf3964ee49afbfc2 to your computer and use it in GitHub Desktop.
Save ZeikJT/5510b783ad180792cf3964ee49afbfc2 to your computer and use it in GitHub Desktop.
Advent of Code 2017 - Days 1 through 22 (skipped 21)
function adventOfCode2017_Day01_Part1(str) {
str += str[0]
let sum = 0
for (let i = 0; i < str.length - 1; i++) {
if (str[i] == str[i + 1]) {
sum += Number(str[i])
}
}
return sum
}
function adventOfCode2017_Day01_Part2(str) {
let sum = 0
for (let i = 0; i < str.length - 1; i++) {
console.log(i, (i + (str.length / 2)) % str.length)
if (str[i] == str[(i + (str.length / 2)) % str.length]) {
sum += Number(str[i])
}
}
return sum
}
function adventOfCode2017_Day02_Part1(text) {
return text.split('\n').reduce((sum, row) => {
const sortedNums = row.split('\t').map(Number).sort((a, b) => a > b ? 1 : a < b ? -1 : 0)
return sum + sortedNums[sortedNums.length - 1] - sortedNums[0]
}, 0)
}
function adventOfCode2017_Day02_Part2(text) {
return text.split('\n').reduce((sum, row) => {
const sortedNums = row.split('\t').map(Number).sort((a, b) => a > b ? 1 : a < b ? -1 : 0)
console.log(sortedNums)
for (let i = 0; i < sortedNums.length; i++) {
const iNum = sortedNums[i]
for (let j = sortedNums.length - 1; j > i; j--) {
const result = sortedNums[j] / iNum
if (result === Math.floor(result)) {
return sum + result
}
}
}
}, 0)
}
function adventOfCode2017_Day03_Part1(num) {
if (num < 1) {return NaN}
if (num === 1) {return 0}
// Determine which box region we are in:
// 4 4 4 4 4 4 4
// 4 3 3 3 3 3 4
// 4 3 2 2 2 3 4
// 4 3 2 1 2 3 4
// 4 3 2 2 2 3 4
// 4 3 3 3 3 3 4
// 4 4 4 4 4 4 4
const regionIndex = Math.ceil((Math.sqrt(num) + 1) / 2)
// Knowing which box region lets us figure out the start:
// ~ ~ ~ ~ ~
// ~ ~ ~ ~ ~
// ~ ~ 1 2 ~
// ~ ~ ~ ~ 10
// ~ ~ ~ ~ ~
const regionStart = Math.pow(((regionIndex - 1) * 2) - 1, 2) + 1
// Position along the box region:
// 7 6 5 4 3
// 8 3 2 1 2
// 9 4 0 0 1
// 10 5 6 7 0
// 11 12 13 14 15
const position = num - regionStart
const countInRegion = (regionIndex - 1) * 8
// We divide the box up into 8 regions to figure out the distance from the center.
const countPerPart = countInRegion / 8
// Determine which part of the box (0-7) the number is at:
// 3 3 3 2 2 2 1
// 4 3 3 2 2 1 1
// 4 4 3 2 1 1 1
// 4 4 4 0 0 0 0
// 5 5 5 6 7 0 0
// 5 5 6 6 7 7 0
// 5 6 6 6 7 7 7
const boxPart = Math.floor(position / countPerPart)
// Distance of number:
// 6 5 4 3 4 5 6
// 5 4 3 2 3 4 5
// 4 3 2 1 2 3 4
// 3 2 1 0 1 2 3
// 4 3 2 1 2 3 4
// 5 4 3 2 3 4 5
// 6 5 4 3 4 5 6
const baseRegionDistance = regionIndex - 1
const positionOffset = position % countPerPart
// Even and odd regions have slightly different calculations.
if (boxPart & 1) {
return baseRegionDistance + positionOffset + 1
} else {
return baseRegionDistance + (countPerPart - positionOffset)
}
}
function adventOfCode2017_Day03_Part2(num) {
let box = 1
const pos = [box, -box]
const values = new Map([['0,0', 1]])
function getNeighboringSums([x, y]) {
let sum = 0
for (let yOff = -1; yOff <= 1; yOff++) {
for (let xOff = -1; xOff <= 1; xOff++) {
sum += values.get((x + xOff) + ',' + (y + yOff)) || 0
}
}
return sum
}
while (true) {
for (let part = 0; part < 4; part++) {
for (let times = 0; times < box * 2; times++) {
switch (part) {
case 0:
pos[1] += 1
break
case 1:
pos[0] -= 1
break
case 2:
pos[1] -= 1
break
case 3:
pos[0] += 1
break
}
const value = getNeighboringSums(pos)
if (value > num) {
return value
}
values.set(pos.join(','), value)
}
}
box++
pos[0]++
pos[1]--
}
}
function adventOfCode2017_Day04_Part1(text) {
return text.split('\n').reduce((count, words) => {
const set = new Set()
for (const word of words.split(' ')) {
if (set.has(word)) {
return count
}
set.add(word)
}
return count + 1
}, 0)
}
function adventOfCode2017_Day04_Part2(text) {
return text.split('\n').reduce((count, words) => {
const set = new Set()
for (const word of words.split(' ')) {
const letters = word.split('').sort().join('')
if (set.has(letters)) {
return count
}
set.add(letters)
}
return count + 1
}, 0)
}
function adventOfCode2017_Day05_Part1(str) {
const instructions = str.split('\n').map(Number)
let index = 0
let step = 0
while (true) {
step++
index += instructions[index]++
if (index < 0 || index >= instructions.length) {
return step
}
}
}
function adventOfCode2017_Day05_Part2(str) {
const instructions = str.split('\n').map(Number)
let index = 0
let step = 0
while (true) {
step++
let oldIndex = index
index += instructions[index]
if (instructions[oldIndex] >= 3) {
instructions[oldIndex]--
} else {
instructions[oldIndex]++
}
if (index < 0 || index >= instructions.length) {
return step
}
}
}
function adventOfCode2017_Day06_Part1(str) {
const banks = str.split('\t').map(Number)
const seen = new Set([str])
while (true) {
let {index} = banks.reduce(({index, max}, num, currentIndex) => {
if (num > max) {
return {index: currentIndex, max: num}
}
return {index, max}
}, {index: -1, max: -1})
let blocks = banks[index]
banks[index] = 0
while (blocks > 0) {
index = (++index) % banks.length
banks[index]++
blocks--
}
const state = banks.join('\t')
if (seen.has(state)) {
return seen.size
}
seen.add(state)
}
}
function adventOfCode2017_Day06_Part2(str) {
const banks = str.split('\t').map(Number)
const seen = new Map([[str, 0]])
while (true) {
let {index} = banks.reduce(({index, max}, num, currentIndex) => {
if (num > max) {
return {index: currentIndex, max: num}
}
return {index, max}
}, {index: -1, max: -1})
let blocks = banks[index]
banks[index] = 0
while (blocks > 0) {
index = (++index) % banks.length
banks[index]++
blocks--
}
const state = banks.join('\t')
if (seen.has(state)) {
return seen.size - seen.get(state)
}
seen.set(state, seen.size)
}
}
// My first time cheesing it on purpose!
function adventOfCode2017_Day07_Part1(str) {
for (const row of str.split('\n')) {
const name = row.substr(0, row.indexOf(' '))
const first = str.indexOf(name)
if (first !== -1 && first == str.lastIndexOf(name)) {
return name
}
}
}
function adventOfCode2017_Day07_Part2(str) {
const nameMap = new Map()
class Node {
constructor(name) {
this.name = name
this.parent = null
this.weight = -1
this.children = []
this.totalWeight = -1
}
setParent(parent = null) {
this.parent = parent
return this
}
setWeight(weight = 0) {
this.weight = weight
return this
}
setChildren(childrenNames = []) {
this.children = childrenNames.map((childName) => {
let childNode
if (nameMap.has(childName)) {
childNode = nameMap.get(childName)
} else {
childNode = new Node(childName)
nameMap.set(childName, childNode)
}
childNode.setParent(this)
return childNode
})
return this
}
calculateTotalWeight() {
return this.totalWeight = this.weight + this.children.map((childNode) => childNode.calculateTotalWeight()).reduce((sum, value) => sum + value, 0)
}
}
const rowRegexp = /^(\w+) \((\d+)\)(?: \-> (.*))?$/
for (const row of str.split('\n')) {
const [, name, weightStr, childrenNames = ''] = row.match(rowRegexp)
let node
if (nameMap.has(name)) {
node = nameMap.get(name)
} else {
node = new Node(name)
nameMap.set(name, node)
}
node.setWeight(Number(weightStr))
if (childrenNames) {
node.setChildren(childrenNames.split(', '))
}
}
let rootNode = nameMap.values().next().value
while (rootNode.parent) {
rootNode = rootNode.parent
}
rootNode.calculateTotalWeight()
// Do a manual inspection at this point until the culprit node is found
console.log(rootNode)
}
function adventOfCode2017_Day08_Part1(str) {
const vars = new Map()
const rowRegexp = /^(\w+) (inc|dec) (\-?\d+) if (\w+) ([<>]=?|[!=]=) (\-?\d+)$/
for (const row of str.split('\n')) {
const [, changeVar, changeDir, changeValueStr, ifVar, ifCheck, ifValueStr] = row.match(rowRegexp)
const ifValue = Number(ifValueStr)
const ifVarValue = vars.get(ifVar) || 0
let checkSuccess = false
switch (ifCheck) {
case '>':
checkSuccess = ifVarValue > ifValue
break;
case '>=':
checkSuccess = ifVarValue >= ifValue
break;
case '<':
checkSuccess = ifVarValue < ifValue
break;
case '<=':
checkSuccess = ifVarValue <= ifValue
break;
case '==':
checkSuccess = ifVarValue == ifValue
break;
case '!=':
checkSuccess = ifVarValue != ifValue
break;
}
if (checkSuccess) {
vars.set(changeVar, (vars.get(changeVar) || 0) + ((changeDir == 'inc' ? 1 : -1) * Number(changeValueStr)))
}
}
let maxValue = Number.MIN_SAFE_INTEGER
for (const curValue of vars.values()) {
if (curValue > maxValue) {
maxValue = curValue
}
}
return maxValue
}
function adventOfCode2017_Day08_Part2(str) {
const vars = new Map()
const rowRegexp = /^(\w+) (inc|dec) (\-?\d+) if (\w+) ([<>]=?|[!=]=) (\-?\d+)$/
let maxValue = 0
for (const row of str.split('\n')) {
const [, changeVar, changeDir, changeValueStr, ifVar, ifCheck, ifValueStr] = row.match(rowRegexp)
const ifValue = Number(ifValueStr)
const ifVarValue = vars.get(ifVar) || 0
let checkSuccess = false
switch (ifCheck) {
case '>':
checkSuccess = ifVarValue > ifValue
break;
case '>=':
checkSuccess = ifVarValue >= ifValue
break;
case '<':
checkSuccess = ifVarValue < ifValue
break;
case '<=':
checkSuccess = ifVarValue <= ifValue
break;
case '==':
checkSuccess = ifVarValue == ifValue
break;
case '!=':
checkSuccess = ifVarValue != ifValue
break;
}
if (checkSuccess) {
const newValue = (vars.get(changeVar) || 0) + ((changeDir == 'inc' ? 1 : -1) * Number(changeValueStr))
vars.set(changeVar, newValue)
if (newValue > maxValue) {
maxValue = newValue
}
}
}
return maxValue
}
function adventOfCode2017_Day09_Part1(str) {
let inGarbage = false
let inGroup = 0
let totalScore = 0
for (let i = 0, char = ''; i < str.length, char = str[i]; i++) {
if (char == '!') {
i++
continue
}
if (inGarbage) {
if (char == '>') {
inGarbage = false
}
continue
}
if (char == '{') {
totalScore += ++inGroup
} else if (char == '}') {
inGroup--
} else if (char == '<') {
inGarbage = true
continue
}
}
return totalScore
}
function adventOfCode2017_Day09_Part2(str) {
let inGarbage = false
let garbageCharCount = 0
for (let i = 0, char = ''; i < str.length, char = str[i]; i++) {
if (char == '!') {
i++
continue
}
if (inGarbage) {
if (char == '>') {
inGarbage = false
} else {
garbageCharCount++
}
continue
}
if (char == '<') {
inGarbage = true
continue
}
}
return garbageCharCount
}
function adventOfCode2017_Day10_Part1(str) {
const list = []
const listLen = 256
for (let i = 0; i < listLen; i++) {
list.push(i)
}
let pos = 0
let skip = 0
for (const lenStr of str.split(',')) {
const len = Number(lenStr)
const lenHalf = Math.floor(len/2)
for (let i = 0; i < lenHalf; i++) {
const leftIndex = (i + pos) % listLen
const rightIndex = (((len - 1) - i) + pos) % listLen
const oldLeft = list[leftIndex]
list[leftIndex] = list[rightIndex]
list[rightIndex] = oldLeft
}
pos += (len + skip++) % listLen
}
return list[0] * list[1]
}
function adventOfCode2017_Day10_Part2(str) {
const list = []
const listLen = 256
for (let i = 0; i < listLen; i++) {
list.push(i)
}
let pos = 0
let skip = 0
function *appended() {
for (const char of str) {
yield char.charCodeAt(0)
}
for (const num of [17, 31, 73, 47, 23]) {
yield num
}
}
for (let round = 0; round < 64; round++) {
for (const charCode of appended()) {
const lenHalf = Math.floor(charCode/2)
for (let i = 0; i < lenHalf; i++) {
const leftIndex = (i + pos) % listLen
const rightIndex = (((charCode - 1) - i) + pos) % listLen
const oldLeft = list[leftIndex]
list[leftIndex] = list[rightIndex]
list[rightIndex] = oldLeft
}
pos += (charCode + skip++) % listLen
}
}
const denseHash = []
for (let i = 0; i < listLen; i += 16) {
let hash = list[i]
for (let offset = 1; offset < 16; offset++) {
hash ^= list[i + offset]
}
denseHash.push(hash)
}
return denseHash.map((num) => {
return num.toString(16).padStart(2, '0')
}).join('')
}
function adventOfCode2017_Day11_Part1(str) {
const dirs = new Array(6).fill(0)
const dirToIndex = ['n', 'ne', 'se', 's', 'sw', 'nw'].reduce((obj, key, index) => {obj[key] = index; return obj}, {})
function addToIndex(index) {
const oppositeIndex = (index + 3) % 6
const compl1Index = (index + 2) % 6
const compl2Index = (index + 4) % 6
if (dirs[oppositeIndex]) {
dirs[oppositeIndex]--
} else if (dirs[compl1Index]) {
dirs[compl1Index]--
addToIndex((index + 1) % 6)
} else if (dirs[compl2Index]) {
dirs[compl2Index]--
addToIndex((index + 5) % 6)
} else {
dirs[index]++
}
}
for (const dir of str.split(',')) {
addToIndex(dirToIndex[dir])
}
return Object.values(dirs).reduce((sum, value) => sum + value, 0)
}
function adventOfCode2017_Day11_Part2(str) {
const dirs = new Array(6).fill(0)
const dirToIndex = ['n', 'ne', 'se', 's', 'sw', 'nw'].reduce((obj, key, index) => {obj[key] = index; return obj}, {})
function addToIndex(index) {
const oppositeIndex = (index + 3) % 6
const compl1Index = (index + 2) % 6
const compl2Index = (index + 4) % 6
if (dirs[oppositeIndex]) {
dirs[oppositeIndex]--
} else if (dirs[compl1Index]) {
dirs[compl1Index]--
addToIndex((index + 1) % 6)
} else if (dirs[compl2Index]) {
dirs[compl2Index]--
addToIndex((index + 5) % 6)
} else {
dirs[index]++
}
}
let max = 0
for (const dir of str.split(',')) {
addToIndex(dirToIndex[dir])
const distance = dirs.reduce((sum, value) => sum + value, 0)
if (distance > max) {
max = distance
}
}
return max
}
function adventOfCode2017_Day12_Part1(str) {
class Node {
constructor(name) {
this.name = name
this.connectedTo = new Set()
}
connect(node) {
this.connectedTo.add(node)
return this
}
}
const nodeMap = new Map()
const lineRegexp = /^(\d+) <\-> ((?:\d+(?:, )?)+)$/
for (const line of str.split('\n')) {
const [, start, ends] = line.match(lineRegexp)
const endArr = ends.split(', ')
let startNode
if (nodeMap.has(start)) {
startNode = nodeMap.get(start)
} else {
nodeMap.set(start, startNode = new Node(start))
}
for (const end of endArr) {
let endNode
if (nodeMap.has(end)) {
endNode = nodeMap.get(end).connect(startNode)
} else {
nodeMap.set(end, endNode = new Node(end).connect(startNode))
}
startNode.connect(endNode)
}
}
const group0 = new Set()
function getConnections(node) {
group0.add(node)
for (const connectedNode of node.connectedTo) {
if (!group0.has(connectedNode)) {
getConnections(connectedNode)
}
}
}
getConnections(nodeMap.get('0'))
return group0.size
}
function adventOfCode2017_Day12_Part2(str) {
class Node {
constructor(name) {
this.name = name
this.connectedTo = new Set()
}
connect(node) {
this.connectedTo.add(node)
return this
}
}
const nodeMap = new Map()
const lineRegexp = /^(\d+) <\-> ((?:\d+(?:, )?)+)$/
for (const line of str.split('\n')) {
const [, start, ends] = line.match(lineRegexp)
const endArr = ends.split(', ')
let startNode
if (nodeMap.has(start)) {
startNode = nodeMap.get(start)
} else {
nodeMap.set(start, startNode = new Node(start))
}
for (const end of endArr) {
let endNode
if (nodeMap.has(end)) {
endNode = nodeMap.get(end).connect(startNode)
} else {
nodeMap.set(end, endNode = new Node(end).connect(startNode))
}
startNode.connect(endNode)
}
}
const groups = []
function getConnections(node, set) {
set.add(node)
for (const connectedNode of node.connectedTo) {
if (!set.has(connectedNode)) {
getConnections(connectedNode, set)
}
}
return set
}
// Wow, I've read about labels in JS before but this is my first legitimate usage of it.
outer: for (const node of nodeMap.values()) {
for (const group of groups) {
if (group.has(node)) {
continue outer
}
}
groups.push(getConnections(node, new Set()))
}
return groups.length
}
function adventOfCode2017_Day13_Part1(str) {
const lineRegexp = /^(\d+): (\d+)$/
let severity = 0
for (const line of str.split('\n')) {
const [, depthStr, rangeStr] = line.match(lineRegexp)
const depth = Number(depthStr)
const range = Number(rangeStr)
if (depth % ((range - 1) * 2) == 0) {
severity += depth * range
}
}
return severity
}
function adventOfCode2017_Day13_Part2(str) {
const lineRegexp = /^(\d+): (\d+)$/
const points = []
for (const line of str.split('\n')) {
const [, depthStr, rangeStr] = line.match(lineRegexp)
const depth = Number(depthStr)
const range = Number(rangeStr)
points.push([depth, range])
}
let i = 0
// I'm addicted to labels now, uh oh.
outer: do {
for (const [depth, range] of points) {
if ((depth + i) % ((range - 1) * 2) == 0) {
continue outer
}
}
break
} while (++i)
return i
}
function adventOfCode2017_Day14_Part1(str) {
let used = 0
for (let i = 0; i < 128; i++) {
for (const char of adventOfCode2017_Day10_Part2(`${str}-${i}`)) {
for (const bit of Number(`0x${char}`).toString(2)) {
if (bit == '1') {
used++
}
}
}
}
return used
}
function adventOfCode2017_Day14_Part2(str) {
let grid = []
for (let i = 0; i < 128; i++) {
let row = ''
for (const char of adventOfCode2017_Day10_Part2(`${str}-${i}`)) {
row += Number(`0x${char}`).toString(2).padStart(4, '0')
}
grid.push(row)
}
const surrounding = [
// TM
// ML [] MR
// BM
[ 0, -1], // TM
[-1, 0], // ML
[ 1, 0], // MR
[ 0, 1], // BM
]
const map = new Map()
function addToSet(x, y, setNum) {
if (x < 0 || y < 0 || x >= 128 || y >= 128) {
return false
}
const coord = `${x},${y}`
if (map.has(coord) || grid[y][x] === '0') {
return false
}
map.set(coord, setNum)
for (const [xOff, yOff] of surrounding) {
addToSet(x + xOff, y + yOff, setNum)
}
return true
}
let setCount = 0
for (let y = 0; y < 128; y++) {
for (let x = 0; x < 128; x++) {
if (addToSet(x, y, setCount)) {
setCount++
}
}
}
return setCount
}
function adventOfCode2017_Day15_Part1(aStart, bStart) {
let a = aStart
let b = bStart
const aMultiplier = 16807
const bMultiplier = 48271
const divisor = 2147483647
const lower16 = 0b1111111111111111
let matches = 0
for (let i = 0; i < 40000000; i++) {
a = (a * aMultiplier) % divisor
b = (b * bMultiplier) % divisor
if ((a & lower16) === (b & lower16)) {
matches++
}
}
return matches
}
function adventOfCode2017_Day15_Part2(aStart, bStart) {
let a = aStart
let b = bStart
const aMultiplier = 16807
const bMultiplier = 48271
const divisor = 2147483647
const lower16 = 0b1111111111111111
let matches = 0
for (let i = 0; i < 5000000; i++) {
do {
a = (a * aMultiplier) % divisor
} while (a % 4 !== 0)
do {
b = (b * bMultiplier) % divisor
} while (b % 8 !== 0)
if ((a & lower16) === (b & lower16)) {
matches++
}
}
return matches
}
function adventOfCode2017_Day16_Part1(str) {
let line = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
const commandRegexp = /^(\w)([\w\d]+)(?:\/([\w\d]+))?$/
for (const command of str.split(',')) {
let [, action, arg1, arg2] = command.match(commandRegexp)
switch (action) {
case 's':
const swapNum = Number(arg1)
line = line.splice(swapNum * -1).concat(line)
break
case 'p':
arg1 = line.indexOf(arg1)
arg2 = line.indexOf(arg2)
case 'x':
const swap1 = Number(arg1)
const swap2 = Number(arg2)
const swap1Value = line[swap1]
line[swap1] = line[swap2]
line[swap2] = swap1Value
break
}
}
return line.join('')
}
function adventOfCode2017_Day16_Part2(str) {
let letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
let lettersMoved = letters.slice()
let line = letters.map((value, index) => index)
let remap = letters.reduce((obj, value) => (obj[value] = value, obj), {})
const commands = []
const commandRegexp = /^(\w)([\w\d]+)(?:\/([\w\d]+))?$/
for (const command of str.split(',')) {
let [, action, arg1, arg2] = command.match(commandRegexp)
switch (action) {
case 's':
const swapNum = Number(arg1)
line = line.splice(swapNum * -1).concat(line)
break
case 'x':
const swap1 = Number(arg1)
const swap2 = Number(arg2)
const swap1Value = line[swap1]
line[swap1] = line[swap2]
line[swap2] = swap1Value
break
case 'p':
const arg1Value = remap[arg1]
remap[arg1] = remap[arg2]
remap[arg2] = arg1Value
break
}
}
remap = letters.reduce((obj, value) => (obj[remap[value]] = value, obj), {})
for (let i = 0; i < 1000000000; i++) {
for (let j = 0; j < 16; j++) {
lettersMoved[j] = remap[letters[line[j]]]
}
const prevLetters = letters
letters = lettersMoved
lettersMoved = prevLetters
}
return letters.join('')
}
function adventOfCode2017_Day17_Part1(steps) {
const max = 2018
const buffer = [0]
let index = 0
for (let i = 1; i < max; i++) {
index = ((index + steps) % i) + 1
buffer.splice(index, 0, i)
}
return buffer[(index + 1) % max]
}
function adventOfCode2017_Day17_Part2(steps) {
let index = 0
let valueAfter0 = -1
for (let i = 1; i < 50000000; i++) {
index = ((index + steps) % i) + 1
if (index === 1) {
valueAfter0 = i
}
}
return valueAfter0
}
function adventOfCode2017_Day18_Part1(str) {
const tablet = new class Tablet extends Map {
constructor(...args) {
super(...args)
this.lastPlayed = -1
}
get(key) {
if (typeof key === 'number') {
return key
}
if (this.has(key)) {
return super.get(key)
}
return 0
}
snd(x) {
this.lastPlayed = this.get(x)
return this
}
set(x, y) {
return super.set(x, this.get(y))
}
add(x, y) {
return super.set(x, this.get(x) + this.get(y))
}
mul(x, y) {
return super.set(x, this.get(x) * this.get(y))
}
mod(x, y) {
return super.set(x, this.get(x) % this.get(y))
}
rcv(x) {
return this.lastPlayed
}
jgz(x, y) {
return this.get(x) > 0 ? this.get(y) : 0
}
}
const lineRegexp = /^(\w+) (\-?\d+|\w)(?: (\-?\d+|\w))?$/
const code = str.split('\n').map((line) => {
const arr = line.match(lineRegexp)
const arg2 = Number(arr[2])
const arg3 = Number(arr[3])
if (!Number.isNaN(arg2)) {
arr[2] = arg2
}
if (!Number.isNaN(arg3)) {
arr[3] = arg3
}
return arr
})
let i = 0
while (i >= 0 && i < code.length) {
const [, command, x, y] = code[i]
let increment = true
switch (command) {
case 'rcv':
const recovered = tablet.rcv(x)
if (recovered) {
return recovered
}
break
case 'jgz':
const offset = tablet.jgz(x, y)
if (offset) {
i += offset
increment = false
}
break
default:
tablet[command](x, y)
break
}
if (increment) {
i++
}
}
console.log('out of bounds')
return tablet.lastPlayed
}
function adventOfCode2017_Day18_Part2(str) {
class Tablet extends Map {
constructor(p, ...args) {
super(...args)
super.set('p', p)
this.p = p
this.i = 0
this.terminated = false
this.rcvQueue = []
}
get(key) {
if (typeof key === 'number') {
return key
}
if (this.has(key)) {
return super.get(key)
}
return 0
}
snd(x) {
return this.get(x)
}
set(x, y) {
return super.set(x, this.get(y))
}
add(x, y) {
return super.set(x, this.get(x) + this.get(y))
}
mul(x, y) {
return super.set(x, this.get(x) * this.get(y))
}
mod(x, y) {
return super.set(x, this.get(x) % this.get(y))
}
rcv(x) {
if (!this.rcvQueue.length) {
return false
}
super.set(x, this.rcvQueue.shift())
return true
}
jgz(x, y) {
return this.get(x) > 0 ? this.get(y) : 0
}
}
const tablets = [new Tablet(0), new Tablet(1)]
const lineRegexp = /^(\w+) (\-?\d+|\w)(?: (\-?\d+|\w))?$/
const code = str.split('\n').map((line) => {
const arr = line.match(lineRegexp)
const arg2 = Number(arr[2])
const arg3 = Number(arr[3])
if (!Number.isNaN(arg2)) {
arr[2] = arg2
}
if (!Number.isNaN(arg3)) {
arr[3] = arg3
}
return arr
})
let program1SndCount = 0
while (true) {
let stuck = true
for (const tablet of tablets) {
if (tablet.terminated) {
continue
}
const [, command, x, y] = code[tablet.i]
let increment = true
switch (command) {
case 'rcv':
increment = tablet.rcv(x)
break
case 'snd':
if (tablet.p === 1) {
program1SndCount++
}
tablets[1 - tablet.p].rcvQueue.push(tablet.snd(x))
break
case 'jgz':
const offset = tablet.jgz(x, y)
if (offset) {
tablet.i += offset
increment = false
stuck = false
}
break
default:
tablet[command](x, y)
break
}
if (increment) {
tablet.i++
stuck = false
}
if (tablet.i < 0 || tablet.i >= code.length) {
tablet.terminated = true
console.log(`${tablet.p} terminated`)
}
}
if (stuck) {
console.log('deadlock')
break
}
}
return program1SndCount
}
function adventOfCode2017_Day19(str) {
const map = str.split('\n')
const maxWidth = map[0].length
const maxHeight = map.length
let x = 0
let y = 0
for (; x < map[0].length; x++) {
if (map[0][x] === '|') {
break
}
}
const DIRS = {
NORTH: [ 0, -1],
SOUTH: [ 0, 1],
WEST: [-1, 0],
EAST: [ 1, 0],
}
const TURN_DIR = new Map([
[DIRS.NORTH, [DIRS.WEST, DIRS.EAST]],
[DIRS.SOUTH, [DIRS.WEST, DIRS.EAST]],
[DIRS.WEST, [DIRS.NORTH, DIRS.SOUTH]],
[DIRS.EAST, [DIRS.NORTH, DIRS.SOUTH]],
])
let dir = DIRS.SOUTH
const letters = []
let steps = 0
while (true) {
x += dir[0]
y += dir[1]
steps++
const nextChar = map[y][x]
switch (nextChar) {
default:
letters.push(nextChar)
case '|':
case '-':
break
case '+':
let foundNewDir = false
const turnDirs = TURN_DIR.get(dir)
for (const otherDir of turnDirs) {
const otherX = x + otherDir[0]
const otherY = y + otherDir[1]
if (otherX < 0 || otherX >= maxWidth || otherY < 0 || otherY >= maxHeight) {
continue
}
const otherChar = map[otherY][otherX]
if (otherChar !== ' ') {
dir = otherDir
foundNewDir = true
}
}
if (!foundNewDir) {
throw new Error(`no new dir found at + pos [${x},${y}]`)
}
break
case ' ':
return {letters: letters.join(''), steps}
}
}
}
function adventOfCode2017_Day20_Part1(str) {
const lineRegexp = /^p=<(\-?\d+),(\-?\d+),(\-?\d+)>, v=<(\-?\d+),(\-?\d+),(\-?\d+)>, a=<(\-?\d+),(\-?\d+),(\-?\d+)>$/
return str.split('\n').map((line) => {
let [, px, py, pz, vx, vy, vz, ax, ay, az] = line.match(lineRegexp).map(Number)
return Math.abs(ax) + Math.abs(ay) + Math.abs(az)
}).reduce(([lowestIndex, lowestValue], value, index) => {
if (value < lowestValue) {
return [index, value]
}
return [lowestIndex, lowestValue]
}, [-1, Number.POSITIVE_INFINITY])
}
function adventOfCode2017_Day20_Part2(str) {
const lineRegexp = /^p=<(\-?\d+),(\-?\d+),(\-?\d+)>, v=<(\-?\d+),(\-?\d+),(\-?\d+)>, a=<(\-?\d+),(\-?\d+),(\-?\d+)>$/
let points = str.split('\n').map((line) => {
let [, px, py, pz, vx, vy, vz, ax, ay, az] = line.match(lineRegexp).map(Number)
return {px, py, pz, vx, vy, vz, ax, ay, az}
})
for (let i = 0; i < 10000; i++) {
const positions = new Map()
const remove = new Set()
for (const point of points) {
const pos = `${point.px},${point.py},${point.pz}`
if (positions.has(pos)) {
remove.add(point)
remove.add(positions.get(pos))
} else {
positions.set(pos, point)
}
point.px += point.vx += point.ax
point.py += point.vy += point.ay
point.pz += point.vz += point.az
}
points = points.filter((point) => !remove.has(point))
}
return points.length
}
// Need to finish this
function adventOfCode2017_Day21_Part1(str) {
function splitGrid(grid) {
const splitGrid = []
if (grid.length & 1 === 0) {
// Evens
const sectionsPerAxis = grid.length / 2
for (let y = 0; y < sectionsPerAxis; y++) {
for (let x = 0; x < sectionsPerAxis; x++) {
if (!splitGrid[y]) {
splitGrid[y] = ''
}
}
}
} else {
// Odds
}
}
const grid = '.#.\n..#\n###'.split('\n')
}
function adventOfCode2017_Day22_Part1(str) {
const grid = str.split('\n').map((line) => Array.from(line).map((value) => value === '#'))
function getPos(x, y) {
if (!grid[y]) {
grid[y] = []
}
return grid[y][x] = !!grid[y][x]
}
const DIR = {
UP: [ 0, -1],
DOWN: [ 0, 1],
LEFT: [-1, 0],
RIGHT: [ 1, 0],
}
const TURN = new Map([
[DIR.UP, {CCW: DIR.LEFT, CW: DIR.RIGHT}],
[DIR.DOWN, {CCW: DIR.RIGHT, CW: DIR.LEFT}],
[DIR.LEFT, {CCW: DIR.DOWN, CW: DIR.UP}],
[DIR.RIGHT, {CCW: DIR.UP, CW: DIR.DOWN}],
])
let facing = DIR.UP
let infectionBursts = 0
const pos = [Math.floor(grid[0].length / 2), Math.floor(grid.length / 2)]
for (let i = 0; i < 10000; i++) {
const wasInfected = getPos(...pos)
facing = TURN.get(facing)[wasInfected ? 'CW' : 'CCW']
grid[pos[1]][pos[0]] = !wasInfected
infectionBursts += wasInfected ? 0 : 1
pos[0] += facing[0]
pos[1] += facing[1]
}
return infectionBursts
}
function adventOfCode2017_Day22_Part2(str) {
const grid = str.split('\n').map((line) => Array.from(line))
function getPos(x, y) {
if (!grid[y]) {
grid[y] = []
}
return grid[y][x] = grid[y][x] || '.'
}
const DIR = {
UP: [ 0, -1],
DOWN: [ 0, 1],
LEFT: [-1, 0],
RIGHT: [ 1, 0],
}
const TURN = new Map([
[DIR.UP, {CCW: DIR.LEFT, CW: DIR.RIGHT, REV: DIR.DOWN, NONE: DIR.UP}],
[DIR.DOWN, {CCW: DIR.RIGHT, CW: DIR.LEFT, REV: DIR.UP, NONE: DIR.DOWN}],
[DIR.LEFT, {CCW: DIR.DOWN, CW: DIR.UP, REV: DIR.RIGHT, NONE: DIR.LEFT}],
[DIR.RIGHT, {CCW: DIR.UP, CW: DIR.DOWN, REV: DIR.LEFT, NONE: DIR.RIGHT}],
])
let facing = DIR.UP
const NEXT_STATE = {
'.': {TURN: 'CCW', CELL: 'W', INFECTED: 0},
'W': {TURN: 'NONE', CELL: '#', INFECTED: 1},
'#': {TURN: 'CW', CELL: 'F', INFECTED: 0},
'F': {TURN: 'REV', CELL: '.', INFECTED: 0},
}
let infectionBursts = 0
const pos = [Math.floor(grid[0].length / 2), Math.floor(grid.length / 2)]
for (let i = 0; i < 10000000; i++) {
const nextState = NEXT_STATE[getPos(...pos)]
facing = TURN.get(facing)[nextState.TURN]
grid[pos[1]][pos[0]] = nextState.CELL
infectionBursts += nextState.INFECTED
pos[0] += facing[0]
pos[1] += facing[1]
}
return infectionBursts
}
function adventOfCode2017_Day23_Part1(str) {
class Tablet extends Map {
constructor(...args) {
super(...args)
this.mulCount = 0
}
get(key) {
if (typeof key === 'number') {
return key
}
if (this.has(key)) {
return super.get(key)
}
return 0
}
set(x, y) {
return super.set(x, this.get(y))
}
sub(x, y) {
return super.set(x, this.get(x) - this.get(y))
}
mul(x, y) {
this.mulCount++
return super.set(x, this.get(x) * this.get(y))
}
jnz(x, y) {
return this.get(x) !== 0 ? this.get(y) : 0
}
}
const tablet = new Tablet()
const lineRegexp = /^(\w+) (\-?\d+|\w)(?: (\-?\d+|\w))?$/
const code = str.split('\n').map((line) => {
const arr = line.match(lineRegexp)
const arg2 = Number(arr[2])
const arg3 = Number(arr[3])
if (!Number.isNaN(arg2)) {
arr[2] = arg2
}
if (!Number.isNaN(arg3)) {
arr[3] = arg3
}
return arr
})
let i = 0
while (i >= 0 && i < code.length) {
const [, command, x, y] = code[i]
let increment = true
switch (command) {
case 'jnz':
const offset = tablet.jnz(x, y)
if (offset) {
i += offset
increment = false
}
break
default:
tablet[command](x, y)
break
}
if (increment) {
i++
}
}
console.log(`line ${i} is out of bounds`)
return tablet.mulCount
}
// Hmm, need to analyze and skip the repetitive code.
function adventOfCode2017_Day23_Part2(str) {
class Tablet extends Map {
constructor(...args) {
super(...args)
this.mulCount = 0
}
get(key) {
if (typeof key === 'number') {
return key
}
if (this.has(key)) {
return super.get(key)
}
return 0
}
set(x, y) {
return super.set(x, this.get(y))
}
sub(x, y) {
return super.set(x, this.get(x) - this.get(y))
}
mul(x, y) {
this.mulCount++
return super.set(x, this.get(x) * this.get(y))
}
jnz(x, y) {
return this.get(x) !== 0 ? this.get(y) : 0
}
}
const tablet = new Tablet([['a', 1]])
const lineRegexp = /^(\w+) (\-?\d+|\w)(?: (\-?\d+|\w))?$/
const code = str.split('\n').map((line) => {
const arr = line.match(lineRegexp)
const arg2 = Number(arr[2])
const arg3 = Number(arr[3])
if (!Number.isNaN(arg2)) {
arr[2] = arg2
}
if (!Number.isNaN(arg3)) {
arr[3] = arg3
}
return arr
})
let ran = 0
let i = 0
while (i >= 0 && i < code.length) {
const [, command, x, y] = code[i]
let increment = true
switch (command) {
case 'jnz':
const offset = tablet.jnz(x, y)
if (offset) {
i += offset
increment = false
}
break
default:
tablet[command](x, y)
break
}
if (increment) {
i++
}
ran++
if (ran % 10000 === 0) {
console.log(Array.from(tablet.entries()))
}
}
console.log(`line ${i} is out of bounds`)
return tablet.get('h')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment