Skip to content

Instantly share code, notes, and snippets.

@ZeikJT
Last active December 18, 2017 16:35
Show Gist options
  • Save ZeikJT/8525aa987b86a6db8ca9b513cf89c8ba to your computer and use it in GitHub Desktop.
Save ZeikJT/8525aa987b86a6db8ca9b513cf89c8ba to your computer and use it in GitHub Desktop.
Advent of Code 2015 - Days 1 - 12 (#9 unsolved)
function adventOfCode2015_Day01_Part1(str) {
return Array.prototype.reduce.call(str, (floor, char) => (floor + (char === '(' ? 1 : -1)), 0)
}
function adventOfCode2015_Day01_Part2(str) {
let floor = 0
let position = 1
for (const char of str) {
floor += char === '(' ? 1 : -1
if (floor === -1) {
return position
}
position++
}
}
function adventOfCode2015_Day02_Part1(str) {
let sum = 0
const rowRegexp = /^(\d+)x(\d+)x(\d+)$/
for (const row of str.split('\n')) {
const [, l, w, h] = row.match(rowRegexp)
const side1 = l*w
const side2 = w*h
const side3 = h*l
let smallestSide = side1
if (side2 < smallestSide) {smallestSide = side2}
if (side3 < smallestSide) {smallestSide = side3}
sum += 2*side1 + 2*side2 + 2*side3 + smallestSide
}
return sum
}
function adventOfCode2015_Day02_Part2(str) {
let sum = 0
const rowRegexp = /^(\d+)x(\d+)x(\d+)$/
for (const row of str.split('\n')) {
const [, lStr, wStr, hStr] = row.match(rowRegexp)
const l = Number(lStr)
const w = Number(wStr)
const h = Number(hStr)
const side1 = 2*(l+w)
const side2 = 2*(w+h)
const side3 = 2*(h+l)
let smallestSide = side1
if (side2 < smallestSide) {smallestSide = side2}
if (side3 < smallestSide) {smallestSide = side3}
sum += smallestSide + l*w*h
}
return sum
}
function adventOfCode2015_Day03_Part1(str) {
const houses = new Map([['0,0', 1]])
const position = [0, 0]
for (const dir of str.split('')) {
switch (dir) {
case '>':
position[0]++
break
case '<':
position[0]--
break
case '^':
position[1]++
break
case 'v':
position[1]--
break
}
houses.set(position.join(','), (houses.get(position.join(',')) || 0) + 1)
}
return houses.size
}
function adventOfCode2015_Day03_Part2(str) {
const houses = new Map([['0,0', 2]])
const position1 = [0, 0]
const position2 = [0, 0]
let usePosition1 = true
for (const dir of str.split('')) {
const position = usePosition1 ? position1 : position2
switch (dir) {
case '>':
position[0]++
break
case '<':
position[0]--
break
case '^':
position[1]++
break
case 'v':
position[1]--
break
}
houses.set(position.join(','), (houses.get(position.join(',')) || 0) + 1)
usePosition1 = !usePosition1
}
return houses.size
}
# Using Python3 for this one because JS lacks a native MD5 function....
import hashlib
def adventOfCode2015_Day04_Part1(prefix):
num = 0
while True:
if hashlib.md5((prefix + str(num)).encode('utf-8')).hexdigest().startswith('00000'):
return num
num = num + 1
def adventOfCode2015_Day04_Part2(prefix):
num = 0
while True:
if hashlib.md5((prefix + str(num)).encode('utf-8')).hexdigest().startswith('000000'):
return num
num = num + 1
function adventOfCode2015_Day05_Part1(str) {
const vowels = /(?:[aeiou]\w*){3}/
const double = /(\w)\1/
const banned = /(?:ab|cd|pq|xy)/
let count = 0
for (const string of str.split('\n')) {
if (vowels.test(string) && double.test(string) && !banned.test(string)) {
count++
}
}
return count
}
function adventOfCode2015_Day05_Part2(str) {
const doublePair = /(\w\w)\w*\1/
const repeatGap = /(\w)\w\1/
let count = 0
for (const string of str.split('\n')) {
if (doublePair.test(string) && repeatGap.test(string)) {
count++
}
}
return count
}
function adventOfCode2015_Day06_Part1(str) {
const lights = new Map()
const rowRegexp = /(toggle|turn (?:on|off)) (\d+),(\d+) through (\d+),(\d+)/
for (const row of str.split('\n')) {
const [, action, startXStr, startYStr, endXStr, endYStr] = row.match(rowRegexp)
const startX = Number(startXStr)
const startY = Number(startYStr)
const endX = Number(endXStr)
const endY = Number(endYStr)
for (let y = startY; y <= endY; y++) {
for (let x = startX; x <= endX; x++) {
const coord = `${x},${y}`
switch (action) {
case 'toggle':
lights.set(coord, !(lights.get(coord) || false))
break
case 'turn on':
lights.set(coord, true)
break
case 'turn off':
lights.set(coord, false)
break
}
}
}
}
return [...lights.values()].reduce((sum, on) => sum + on, 0)
}
function adventOfCode2015_Day06_Part2(str) {
const lights = new Map()
const rowRegexp = /(toggle|turn (?:on|off)) (\d+),(\d+) through (\d+),(\d+)/
for (const row of str.split('\n')) {
const [, action, startXStr, startYStr, endXStr, endYStr] = row.match(rowRegexp)
const startX = Number(startXStr)
const startY = Number(startYStr)
const endX = Number(endXStr)
const endY = Number(endYStr)
for (let y = startY; y <= endY; y++) {
for (let x = startX; x <= endX; x++) {
const coord = `${x},${y}`
const curValue = lights.get(coord) || 0
switch (action) {
case 'toggle':
lights.set(coord, curValue + 2)
break
case 'turn on':
lights.set(coord, curValue + 1)
break
case 'turn off':
lights.set(coord, curValue > 0 ? curValue - 1 : 0)
break
}
}
}
}
return [...lights.values()].reduce((sum, value) => sum + value, 0)
}
function adventOfCode2015_Day07_Part1(str) {
const max = 0b1111111111111111
const gates = new Map()
class Gate {
constructor() {
this.in1 = undefined
this.action = undefined
this.in2 = undefined
this.out = undefined
this.value = undefined
this.loaded = false
this.blocks = null
}
getInputs() {
let unresolvedDeps = false
const [in1, in2] = [this.in1, this.in2].map((input) => {
if (input === undefined || typeof input === 'number') {
return input
}
let depGate = gates.get(input)
if (!depGate) {
depGate = new Gate()
gates.set(input, depGate)
}
if (!depGate.loaded) {
(depGate.blocks = depGate.blocks || new Set()).add(this.out)
unresolvedDeps = true
return input
}
return depGate.value
})
return {unresolvedDeps, in1, in2}
}
canResolve() {
return !this.loaded && !this.getInputs().unresolvedDeps
}
maybeResolve() {
if (this.loaded) {
return null
}
const {action, out} = this
let {unresolvedDeps, in1, in2} = this.getInputs()
if (unresolvedDeps) {
return null
}
switch (action) {
case 'SET':
this.value = in2
break
case 'AND':
this.value = in1 & in2
break
case 'OR':
this.value = in1 | in2
break
case 'LSHIFT':
this.value = (in1 << in2) & max
break
case 'RSHIFT':
this.value = in1 >> in2
break
case 'NOT':
this.value = in2 ^ max
break
}
this.loaded = true
if (!this.blocks || this.blocks.size == 0) {
return null
}
const resolvedBlocks = []
for (const name of this.blocks) {
if (gates.get(name).canResolve()) {
resolvedBlocks.push(name)
}
}
return resolvedBlocks
}
}
const rowRegexp = /^(?:([a-z]+|\d+) )?(?:([A-Z]+) )?([a-z]+|\d+) \-> ([a-z]+)$/
const blockersToResolve = []
for (const row of str.split('\n')) {
const [, in1, action = 'SET', in2, out] = row.match(rowRegexp)
let in1Num = Number(in1)
let in2Num = Number(in2)
const gate = gates.get(out) || new Gate()
gate.in1 = Number.isNaN(in1Num) ? in1 : in1Num
gate.action = action
gate.in2 = Number.isNaN(in2Num) ? in2 : in2Num
gate.out = out
gates.set(out, gate)
const newlyResolved = gate.maybeResolve()
if (newlyResolved && newlyResolved.length) {
for (const resolved of newlyResolved) {
blockersToResolve.push(resolved)
}
}
}
for (const name of blockersToResolve) {
const gate = gates.get(name)
const newlyResolved = gate.maybeResolve()
if (newlyResolved && newlyResolved.length) {
for (const resolved of newlyResolved) {
blockersToResolve.push(resolved)
}
}
}
console.log(gates.get('a').value)
}
function adventOfCode2015_Day07_Part2(str) {
const max = 0b1111111111111111
const gates = new Map()
class Gate {
constructor() {
this.in1 = undefined
this.action = undefined
this.in2 = undefined
this.out = undefined
this.value = undefined
this.loaded = false
this.blocks = null
}
getInputs() {
let unresolvedDeps = false
const [in1, in2] = [this.in1, this.in2].map((input) => {
if (input === undefined || typeof input === 'number') {
return input
}
let depGate = gates.get(input)
if (!depGate) {
depGate = new Gate()
gates.set(input, depGate)
}
if (!depGate.loaded) {
(depGate.blocks = depGate.blocks || new Set()).add(this.out)
unresolvedDeps = true
return input
}
return depGate.value
})
return {unresolvedDeps, in1, in2}
}
canResolve() {
return !this.loaded && !this.getInputs().unresolvedDeps
}
maybeResolve() {
if (this.loaded) {
return null
}
const {action, out} = this
let {unresolvedDeps, in1, in2} = this.getInputs()
if (unresolvedDeps) {
return null
}
switch (action) {
case 'SET':
this.value = this.out == 'b' ? 46065 : in2
break
case 'AND':
this.value = in1 & in2
break
case 'OR':
this.value = in1 | in2
break
case 'LSHIFT':
this.value = (in1 << in2) & max
break
case 'RSHIFT':
this.value = in1 >> in2
break
case 'NOT':
this.value = in2 ^ max
break
}
this.loaded = true
if (!this.blocks || this.blocks.size == 0) {
return null
}
const resolvedBlocks = []
for (const name of this.blocks) {
if (gates.get(name).canResolve()) {
resolvedBlocks.push(name)
}
}
return resolvedBlocks
}
}
const rowRegexp = /^(?:([a-z]+|\d+) )?(?:([A-Z]+) )?([a-z]+|\d+) \-> ([a-z]+)$/
const blockersToResolve = []
for (const row of str.split('\n')) {
const [, in1, action = 'SET', in2, out] = row.match(rowRegexp)
let in1Num = Number(in1)
let in2Num = Number(in2)
const gate = gates.get(out) || new Gate()
gate.in1 = Number.isNaN(in1Num) ? in1 : in1Num
gate.action = action
gate.in2 = Number.isNaN(in2Num) ? in2 : in2Num
gate.out = out
gates.set(out, gate)
const newlyResolved = gate.maybeResolve()
if (newlyResolved && newlyResolved.length) {
for (const resolved of newlyResolved) {
blockersToResolve.push(resolved)
}
}
}
for (const name of blockersToResolve) {
const gate = gates.get(name)
const newlyResolved = gate.maybeResolve()
if (newlyResolved && newlyResolved.length) {
for (const resolved of newlyResolved) {
blockersToResolve.push(resolved)
}
}
}
console.log(gates.get('a').value)
}
function adventOfCode2015_Day08_Part1(str) {
return str.split('\n').reduce((diff, line) => diff + (line.length - eval(line).length), 0)
}
function adventOfCode2015_Day08_Part2(str) {
return str.split('\n').reduce((diff, line) => diff + (JSON.stringify(line).length - line.length), 0)
}
function adventOfCode2015_Day09_Part1(str) {
const places = []
const placeToIndex = new Map()
const distances = []
const lineRegexp = /^(\w+) to (\w+) = (\d+)$/
for (const line of str.split('\n')) {
const [, start, end, distanceStr] = line.match(lineRegexp)
for (const place of [start, end]) {
if (!placeToIndex.has(place)) {
const index = places.length
placeToIndex.set(place, index)
places.push(place)
const newDist = []
newDist[index] = 0
distances[index] = newDist
}
}
const startIndex = placeToIndex.get(start)
const endIndex = placeToIndex.get(end)
const distance = Number(distanceStr)
distances[startIndex][endIndex] = distance
distances[endIndex][startIndex] = distance
}
const count = distances.length
for (let k = 0; k < count; k++) {
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
const sum = distances[i][k] + distances[k][j]
if (distances[i][j] > sum) {
distances[i][j] = sum
}
}
}
}
// Where do I go from here? Starting to think Floyd-Warshall isn't what I want or is incomplete.
return distances[0].map((first, x) => {
let sum = first
for (let y = 1; y < count; y++) {
sum += distances[y][x]
}
return sum
})
}
function adventOfCode2015_Day09_Part2(str) {
}
function adventOfCode2015_Day10_Part1(str) {
let curStr = str
for (let i = 0; i < 40; i++) {
const nextStr = [0, curStr[0]]
for (const char of curStr) {
if (char === nextStr[nextStr.length - 1]) {
nextStr[nextStr.length - 2]++
} else {
nextStr.push(1, char)
}
}
curStr = nextStr.join('')
}
return curStr.length
}
function adventOfCode2015_Day10_Part2(str) {
let curStr = str
for (let i = 0; i < 50; i++) {
const nextStr = [0, curStr[0]]
for (const char of curStr) {
if (char === nextStr[nextStr.length - 1]) {
nextStr[nextStr.length - 2]++
} else {
nextStr.push(1, char)
}
}
curStr = nextStr.join('')
}
return curStr.length
}
// Parts 1 and 2!
function adventOfCode2015_Day11(str) {
const start = 'a'.charCodeAt(0)
const end = 'z'.charCodeAt(0)
const pass = Array.prototype.map.call(str, (char) => char.charCodeAt(0))
const bannedCharCodes = new Set(['i', 'o', 'l'].map((char) => char.charCodeAt(0)))
outer: while (true) {
for (let i = pass.length - 1; i >= 0; i--) {
pass[i]++
if (pass[i] <= end) {
break
}
pass[i] = start
}
let lastCharCode = 0
let straightCount = 0
let straight = false
let letterPairs = new Set()
for (const charCode of pass) {
if (bannedCharCodes.has(charCode)) {
continue outer
}
if (!straight) {
if (charCode != lastCharCode + 1) {
straightCount = 1
} else {
straightCount++
if (straightCount == 3) {
straight = true
}
}
}
if (letterPairs.size < 2 && charCode == lastCharCode && !letterPairs.has(charCode)) {
letterPairs.add(charCode)
}
lastCharCode = charCode
}
if (straight && letterPairs.size >= 2) {
break
}
}
return pass.map((charCode) => String.fromCharCode(charCode)).join('')
}
// Cheesing it via string.
function adventOfCode2015_Day12_part1(str) {
let sum = 0
str.replace(/\-?\d+/g, (numStr) => {
sum += Number(numStr)
return numStr
})
return sum
}
function adventOfCode2015_Day12_part2(str) {
function sumAll(input) {
switch (Array.isArray(input) ? 'array' : typeof input) {
case 'array':
return input.reduce((sum, value) => sum + sumAll(value), 0)
case 'object':
let sum = 0
for (const value of Object.values(input)) {
if (value === 'red') {
return 0
}
sum += sumAll(value)
}
return sum
case 'number':
return input
default:
return 0
}
}
return sumAll(JSON.parse(str))
}
function adventOfCode2015_Day13_part1(str) {
}
function adventOfCode2015_Day14_part1(str) {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment