Skip to content

Instantly share code, notes, and snippets.

@carpusherw
Last active December 25, 2022 08:29
Show Gist options
  • Save carpusherw/67687b60d979b2ab8052962c8d610fbc to your computer and use it in GitHub Desktop.
Save carpusherw/67687b60d979b2ab8052962c8d610fbc to your computer and use it in GitHub Desktop.

Advent of Code 2022

https://adventofcode.com/2022

Coding in browser developer tools.

Get input

var line = document.querySelector('pre').innerText.split('\n').filter(s => s)

Day 1 - part 1

var arr = document.querySelector('pre').innerText.split('\n\n')
  .map(a => a.split('\n').map(s => parseInt(s)).reduce((a, b) => a+b))
  .sort((a, b) => b-a)
arr[0]

Day 1 - part 2

arr[0] + arr[1] + arr[2]

Day 2 - part 1

line.map(s => s.split(' ')).map(([p1, p2]) => {
  const p1n = p1.charCodeAt() - 'A'.charCodeAt() + 1
  const p2n = p2.charCodeAt() - 'X'.charCodeAt() + 1
  const diff = p2n - p1n;
  let score = p2n;
  const result = diff === 0 
    ? 0
    : diff === 1 || diff === -2
      ? 1
      : -1
  if (result === 0) score += 3;
  else if (result === 1) score += 6;
  return score
}).reduce((sum, n) => sum+n, 0)

Day 2 - part 2

line.map(s => s.split(' ')).map(([p1, p2]) => {
  const p1n = p1.charCodeAt() - 'A'.charCodeAt() + 1
  const result = p2.charCodeAt() - 'X'.charCodeAt()
  let p2n = result === 0 
    ? ((p1n-1) > 0 ? (p1n-1) : 3)
    : result === 1
      ? p1n
      : ((p1n+1) < 4 ? (p1n+1): 1)
  let score = p2n;
  if (result === 1) score += 3;
  else if (result === 2) score += 6;
  return score
}).reduce((sum, n) => sum+n, 0)

Day 3 - part 1

line.map(s => {
    const map = {}
    for (let i=0; i<s.length/2; i++) {
        const c1 = s.charAt(i)
        const c2 = s.charAt(i+s.length/2)
        if (map[c1] === -1) return c1
        map[c1] = 1
        if (map[c2] === 1) return c2
        map[c2] = -1
    }
}).map(c => {
    let code = c.charCodeAt() - 'a'.charCodeAt() + 1
    return code < 0 ? code+58 : code
}).reduce((s, n) => s+n)

Day 3 - part 2

line.reduce((r, l) => {
    let last = r[r.length-1]
    if (last.length === 3) {
        last = []
        r.push(last)
    }
    last.push(l)
    return r
}, [[]]).map(three => {
    const map = {}
    for (let c of three[0])
        map[c] = 1
    for (let c of three[1])
        if (map[c])
            map[c] = 2
    for (let c of three[2])
        if (map[c] === 2)
            return c
}).map(c => {
    let code = c.charCodeAt() - 'a'.charCodeAt() + 1
    return code < 0 ? code+58 : code
}).reduce((s, n) => s+n)

Day 4 - part 1

line.map(l => l.split(',').map(a => a.split('-').map(s => parseInt(s))).sort((a, b) => a[0]-b[0] ? a[0]-b[0] : b[1]-a[1]))
    .filter(arr => arr[0][1] >= arr[1][1])
    .length

Day 4 - part 2

line.map(l => l.split(',').map(a => a.split('-').map(s => parseInt(s))).sort((a, b) => a[0]-b[0]))
    .filter(arr => arr[0][1] >= arr[1][0])
    .length

Day 5 - part 1

var line = document.querySelector('pre').innerText.split('\n\n')
var diagram = line[0].split('\n')
var stacks = [[],[],[],[],[],[],[],[],[]]
for (let i=diagram.length-2; i>=0; i--) {
  let pos = 1;
  for (let j=0; j<9; j++) {
      const char = diagram[i].charAt(pos)
      if (char !== ' ') stacks[j].push(char)
      pos += 4
  }
}

line[1].split('\n').filter(s => s).map(s => s.split(' ')).map(([_, r, __, f, ___, t]) => [parseInt(r), parseInt(f), parseInt(t)])
    .forEach(([repeat, from, to]) => {
        stacks[to-1] = stacks[to-1].concat(stacks[from-1].slice(-repeat).reverse())
        stacks[from-1] = stacks[from-1].slice(0, -repeat)
    })
stacks.map(arr => arr[arr.length-1]).reduce((r, x) => r+x)

Day 5 - part 2

line[1].split('\n').filter(s => s).map(s => s.split(' ')).map(([_, r, __, f, ___, t]) => [parseInt(r), parseInt(f), parseInt(t)])
    .forEach(([repeat, from, to]) => {
        stacks[to-1] = stacks[to-1].concat(stacks[from-1].slice(-repeat))
        stacks[from-1] = stacks[from-1].slice(0, -repeat)
    })
stacks.map(arr => arr[arr.length-1]).reduce((r, x) => r+x)

Day 6 - part 1

var chars = line[0].split('')
var map = {}
for (let i=0; i<4; i++) map[chars[i]] = (map[chars[i]] ? map[chars[i]] : 0 ) + 1
for (let i=4; i<chars.length; i++) {
    map[chars[i]] = (map[chars[i]] ? map[chars[i]] : 0 ) + 1
    map[chars[i-4]]--
    if (Object.values(map).every(n => n < 2)) {
        console.log(i+1)
        break
    }
}

Day 6 - part 2

same as above but replace 4 with 14

Day 7 - part 1

var tree = {}
var dirs = [tree]
line.forEach(s => {
    const curDir = dirs[dirs.length-1]
    const cmd = s.split(' ')
    if (cmd[0] === '$') {
        if (cmd[1] === 'cd') {
            if (cmd[2] === '..') {
                dirs.pop()
            } else {
                const newDir = {}
                curDir[cmd[2]] = newDir
                dirs.push(newDir)
            }
        }
    } else if (cmd[0] !== 'dir') {
        const fileSize = parseInt(cmd[0])
        curDir[cmd[1]] = fileSize
        curDir.size = (curDir.size ? curDir.size : 0) + fileSize
    }
})
var result = 0
var dfs = dir => {
    for (const [key, value] of Object.entries(dir)) {
        if (typeof value === 'object') {
            dir.size = (dir.size ? dir.size : 0) + dfs(value)
        }
    }
    if (dir.size <= 100000) result+= dir.size
    return dir.size
}
dfs(tree['/'])
result

Day 7 - part 2

var sizes = []
var dfs = dir => {
    for (const [key, value] of Object.entries(dir)) {
        if (typeof value === 'object') {
            dir.size = (dir.size ? dir.size : 0) + dfs(value)
        }
    }
    if (dir.size <= 100000) result+= dir.size
    sizes.push(dir.size)
    return dir.size
}
var total = dfs(tree['/'])
sizes.sort((a, b) => a-b).filter(s => s > total-40000000)[0]

Day 8 - part 1

var map = line.map(s => s.split('').map(n => parseInt(n)))
var visible = new Set()
for (let i=1; i<map.length-1; i++) {
    let tallest = 0
    let positions = { [map[i][tallest]]: tallest }
    for (let j=1; j<map.length-1; j++) {
        if (map[i][j] >= [map[i][tallest]]) {
            if (map[i][j] > [map[i][tallest]]) visible.add(`${i},${j}`)
            tallest = j
            positions = { [map[i][tallest]]: tallest }
        } else {
            positions[map[i][j]] = j
        }
    }
    positions[map[i][map.length-1]] = map.length-1
    let previous = -1
    for (let k=map[i][tallest]; k>map[i][map.length-1]; k--) {
        if (positions[k]) {
            if (previous === -1 || positions[k] > positions[previous]) {
                visible.add(`${i},${positions[k]}`)
                previous = k
            }
        }
    }
}
for (let i=1; i<map.length-1; i++) {
    let tallest = 0
    let positions = { [map[tallest][i]]: tallest }
    for (let j=1; j<map.length-1; j++) {
        if (map[j][i] >= [map[tallest][i]]) {
            if (map[j][i] > [map[tallest][i]]) visible.add(`${j},${i}`)
            tallest = j
            positions = { [map[tallest][i]]: tallest }
        } else {
            positions[map[j][i]] = j
        }
    }
    positions[map[map.length-1][i]] = map.length-1
    let previous = -1
    for (let k=map[tallest][i]; k>map[map.length-1][i]; k--) {
        if (positions[k]) {
            if (previous === -1 || positions[k] > positions[previous]) {
                visible.add(`${positions[k]},${i}`)
                previous = k
            }
        }
    }
}
visible.size + map.length*4 - 4

Day 8 - part 2

var map = line.map(s => s.split('').map(n => parseInt(n)))
var scores = new Array(map.length-2)
for (let i = 0; i < map.length-2; i++) {
  scores[i] = new Array(map.length-2)
}
for (let i=1; i<map.length-1; i++) {
    let positions = { [map[i][0]]: 0 }
    for (let j=1; j<map.length-1; j++) {
        let nearMost = 0;
        for (let k=map[i][j]; k<10; k++) {
            if (positions[k] != null) nearMost = Math.max(nearMost, positions[k])
        }
        scores[i-1][j-1] = {}
        scores[i-1][j-1].left = j - nearMost
        positions[map[i][j]] = j
    }
    positions = { [map[i][map.length-1]]: map.length-1 }
    for (let j=map.length-2; j>0; j--) {
        let nearMost = 98;
        for (let k=map[i][j]; k<10; k++) {
            if (positions[k] != null) nearMost = Math.min(nearMost, positions[k])
        }
        scores[i-1][j-1].right = nearMost - j
        positions[map[i][j]] = j
    }
}
for (let j=1; j<map.length-1; j++) {
    let positions = { [map[0][j]]: 0 }
    for (let i=1; i<map.length-1; i++) {
        let nearMost = 0;
        for (let k=map[i][j]; k<10; k++) {
            if (positions[k] != null) nearMost = Math.max(nearMost, positions[k])
        }
        scores[i-1][j-1].above = i - nearMost
        positions[map[i][j]] = i
    }
    positions = { [map[map.length-1][j]]: map.length-1 }
    for (let i=map.length-2; i>0; i--) {
        let nearMost = 98;
        for (let k=map[i][j]; k<10; k++) {
            if (positions[k] != null) nearMost = Math.min(nearMost, positions[k])
        }
        score = scores[i-1][j-1]
        scores[i-1][j-1] = (nearMost - i) * score.above * score.left * score.right
        positions[map[i][j]] = i
    }
}
scores.reduce((max, arr) => Math.max(max, arr.reduce((max, n) => Math.max(max, n), 0)), 0)

Day 9 - part 1

var dirs = { R: [1, 0], L: [-1, 0], U: [0, 1], D: [0, -1] }
var head = [0, 0]
var tail = [0, 0]
var set = new Set()
set.add('0,0')
line.forEach(motion => {
    const [dir, n] = motion.split(' ')
    const step = parseInt(n)
    for (let i in [0, 1])
        head[i] += dirs[dir][i] * step
    const diffs = head.map((v, i) => v - tail[i])
    if (diffs.every(diff => Math.abs(diff) <= 1)) return
    else if (diffs[0] === 0 || Math.abs(diffs[0]) === 1) {
        tail[0] = head[0]
        const diffSign = diffs[1] / Math.abs(diffs[1])
        const newTail = tail[1] + diffSign * (Math.abs(diffs[1])-1)
        for (let i=tail[1]+diffSign; i != newTail; i+=diffSign) {
            set.add(`${tail[0]},${i}`)
        }
        tail[1] = newTail
        set.add(`${tail[0]},${tail[1]}`)
    } else if (diffs[1] === 0 || Math.abs(diffs[1]) === 1) {
        tail[1] = head[1]
        const diffSign = diffs[0] / Math.abs(diffs[0])
        const newTail = tail[0] + diffSign * (Math.abs(diffs[0])-1)
        for (let i=tail[0]+diffSign; i != newTail; i+=diffSign) {
            set.add(`${i},${tail[1]}`)
        }
        tail[0] = newTail
        set.add(`${tail[0]},${tail[1]}`)
    }
})
set.size

Day 9 - part 2

var dirs = { R: [1, 0], L: [-1, 0], U: [0, 1], D: [0, -1] }
var knots = [[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]]
var set = new Set()
set.add('0,0')
var followKnot = (lead, follow, isLast) => {
    const diffs = lead.map((v, i) => v - follow[i])
    if (diffs.every(diff => Math.abs(diff) <= 1)) return
    else if (diffs[0] === 0 || Math.abs(diffs[0]) < Math.abs(diffs[1])) {
        follow[0] = lead[0]
        const diffSign = diffs[1] / Math.abs(diffs[1])
        const newFollow = follow[1] + diffSign * (Math.abs(diffs[1])-1)
        if (isLast) {
            for (let i=follow[1]+diffSign; i != newFollow; i+=diffSign) {
                set.add(`${follow[0]},${i}`)
            }
            set.add(`${follow[0]},${newFollow}`)
        }
        follow[1] = newFollow
    } else if (diffs[1] === 0 || Math.abs(diffs[0]) > Math.abs(diffs[1])) {
        follow[1] = lead[1]
        const diffSign = diffs[0] / Math.abs(diffs[0])
        const newFollow = follow[0] + diffSign * (Math.abs(diffs[0])-1)
        if (isLast) {
            for (let i=follow[0]+diffSign; i != newFollow; i+=diffSign) {
                set.add(`${i},${follow[1]}`)
            }
            set.add(`${newFollow},${follow[1]}`)
        }
        follow[0] = newFollow
    } else {
        const diffSigns = [diffs[0] / Math.abs(diffs[0]), diffs[1] / Math.abs(diffs[1])]
        for (let i=1; i<Math.abs(diffs[0]); i++) {
            for (let j in [0, 1])
                follow[j] += diffSigns[j]
            if (isLast) set.add(`${follow[0]},${follow[1]}`)
        }
    }
}
line.forEach(motion => {
    const [dir, n] = motion.split(' ')
    const step = parseInt(n)
    for (let n=0; n<step; n++) {
        for (let i in [0, 1])
            knots[0][i] += dirs[dir][i]
        for (let i=0; i<9; i++) {
            followKnot(knots[i], knots[i+1], i === 8)
        }
    }
})
set.size

Day 10 - part 1

var x = 1
var cycle = []
var hist = [1]
line.forEach(cmd => {
    cycle.push(0)
    const segs = cmd.split(' ')
    if (segs.at(1)) {
        cycle.push(parseInt(segs[1]))
    }
})
cycle.forEach(c => {
    x += c
    hist.push(x)
})
var res = 0
for(let i=19; i<hist.length; i+=40) {
    res += hist[i]*(i+1)
}
res

Day 10 - part 2

var crt = []
for (let i=0; i<240; i++) {
    const p = (i+1) % 40
    crt.push(hist[i] <= p && p <= hist[i]+2 ? '#' : '.')
}
console.log(...crt.slice(0, 40))
console.log(...crt.slice(40, 80))
console.log(...crt.slice(80, 120))
console.log(...crt.slice(120, 160))
console.log(...crt.slice(160, 200))
console.log(...crt.slice(200, 240))

Day 11 - part 1

var monkeys = [
    {
        items: [63, 57],
        op: n =>  Math.floor(n*11/3),
        throwTo: n => monkeys[n % 7 === 0 ? 6 : 2].items.push(n),
        count: 0,
    },
    {
        items: [82, 66, 87, 78, 77, 92, 83],
        op: n =>  Math.floor((n+1)/3),
        throwTo: n => monkeys[n % 11 === 0 ? 5 : 0].items.push(n),
        count: 0,
    },
    {
        items: [97, 53, 53, 85, 58, 54],
        op: n =>  Math.floor(n*7/3),
        throwTo: n => monkeys[n % 13 === 0 ? 4 : 3].items.push(n),
        count: 0,
    },
    {
        items: [50],
        op: n =>  Math.floor((n+3)/3),
        throwTo: n => monkeys[n % 3 === 0 ? 1 : 7].items.push(n),
        count: 0,
    },
    {
        items: [64, 69, 52, 65, 73],
        op: n =>  Math.floor((n+6)/3),
        throwTo: n => monkeys[n % 17 === 0 ? 3 : 7].items.push(n),
        count: 0,
    },
    {
        items: [57, 91, 65],
        op: n =>  Math.floor((n+5)/3),
        throwTo: n => monkeys[n % 2 === 0 ? 0 : 6].items.push(n),
        count: 0,
    },
    {
        items: [67, 91, 84, 78, 60, 69, 99, 83],
        op: n =>  Math.floor(n*n/3),
        throwTo: n => monkeys[n % 5 === 0 ? 2 : 4].items.push(n),
        count: 0,
    },
    {
        items: [58, 78, 69, 65],
        op: n =>  Math.floor((n+7)/3),
        throwTo: n => monkeys[n % 19 === 0 ? 5 : 1].items.push(n),
        count: 0,
    },
]
for (let r=0; r<20; r++) {
    for (let monkey of monkeys) {
        const throwTos = monkey.items.map(monkey.op).forEach(monkey.throwTo)
        monkey.count += monkey.items.length
        monkey.items = []
    }
}
var sortedCount = monkeys.map(m => m.count).sort((a, b) => b-a)
sortedCount[0] * sortedCount[1]

Day 11 - part 2

Manage worry level by lcm.

var lcm = 7*11*13*3*17*2*5*19
var monkeys = [
    {
        items: [63, 57],
        op: n => n*11 % lcm,
        throwTo: n => monkeys[n % 7 === 0 ? 6 : 2].items.push(n),
        count: 0,
    },

Day 12 - part 1

var map = line.map(l => l.split('').map(c => c.charCodeAt() - 'a'.charCodeAt()))
var S, E
for (let i=0; i<map.length; i++) {
    for (let j=0; j<map[0].length; j++) {
        if (map[i][j] === -14) { // S
            S = [i, j]
            map[i][j] = -1
        }
        if (map[i][j] === -28) { // E
            E = [i, j]
            map[i][j] = 25
        }
    }
}

var queue = [[...S, 0, 0]]
while (queue.length !== 0) {
    const [i, j, current, depth] = queue.shift()
    if (i === E[0] && j === E[1]) {
        console.log(depth)
        break
    }
    const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]]
    dirs.forEach(dir => {
        const targetI = i+dir[0]
        const targetJ = j+dir[1]
        const target = map[targetI]?.[targetJ]
        if (target !== undefined && target != -1 && target <= current+1) {
            queue.push([targetI, targetJ, target, depth+1])
            map[targetI][targetJ] = -1
        }
    })
}

Day 12 - part 2

var map = line.map(l => l.split('').map(c => c.charCodeAt() - 'a'.charCodeAt()))
var E
for (let i=0; i<map.length; i++) {
    for (let j=0; j<map[0].length; j++) {
        if (map[i][j] === -14) {
            map[i][j] = 0
        }
        if (map[i][j] === -28) { // E
            E = [i, j]
            map[i][j] = -1
        }
    }
}

var queue = [[...E, 25, 0]]
while (queue.length !== 0) {
    const [i, j, current, depth] = queue.shift()
    if (current === 0) {
        console.log(depth)
        break
    }
    const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]]
    dirs.forEach(dir => {
        const targetI = i+dir[0]
        const targetJ = j+dir[1]
        const target = map[targetI]?.[targetJ]
        if (target !== undefined && target != -1 && target >= current-1) {
            queue.push([targetI, targetJ, target, depth+1])
            map[targetI][targetJ] = -1
        }
    })
}

Day 13 - part 1

var line = document.querySelector('pre').innerText.split('\n\n').map(pair => pair.split('\n').filter(s => s).map(JSON.parse))
var compare = (left, right) => {
    if (right === undefined) return false
    if (typeof left !== 'object') left = [left]
    if (typeof right !== 'object') right = [right]
    for (let i=0; i<Math.min(left.length, right.length); i++) {
        if (typeof left[i] === 'object' || typeof right[i] === 'object') {
            const res = compare(left[i], right[i])
            if (res !== null) return res
        } else if (left[i] > right[i]) return false
        else if (left[i] < right[i]) return true
    }
    if (left.length < right.length) return true
    else if (left.length > right.length) return false
    return null;
}
line.map(pair => compare(...pair)).reduce((s, b, i) => b ? s+i+1 : s, 0)

Day 13 - part 2

var line = document.querySelector('pre').innerText.split('\n').filter(s => s).map(s => JSON.parse(s))
var compare = (left, right) => {
    if (right === undefined) return 1
    if (typeof left !== 'object') left = [left]
    if (typeof right !== 'object') right = [right]
    for (let i=0; i<Math.min(left.length, right.length); i++) {
        if (typeof left[i] === 'object' || typeof right[i] === 'object') {
            const res = compare(left[i], right[i])
            if (res !== 0) return res
        } else if (left[i] > right[i]) return 1
        else if (left[i] < right[i]) return -1
    }
    if (left.length < right.length) return -1
    else if (left.length > right.length) return 1
    return 0;
}
var res = 1
line.concat([[[2]], [[6]]]).sort(compare).forEach((a, i) => {
    if ((a[0]?.[0] === 2 || a[0]?.[0] === 6) && a.length === 1 && a[0].length === 1) res *= (i+1)
})
res

Day 14 - part 1

var line = document.querySelector('pre').innerText.split('\n').filter(s => s).map(s => s.split(' -> ').map(p => p.split(',').map(Number)))
var MAX_HEIGHT = 170
var map = new Array(509)
for (let i=0; i<map.length; i++) map[i] = new Array(MAX_HEIGHT).fill('.')
line.forEach(paths => {
    for (let i=0; i<paths.length-1; i++) {
        const diff = [paths[i+1][0]-paths[i][0], paths[i+1][1]-paths[i][1]]
        const length = Math.max(Math.abs(diff[0]), Math.abs(diff[1]))
        const step = diff.map(d => d/length)
        for (let j=0; j<length+1; j++) {
            map[paths[i][0]+step[0]*j][paths[i][1]+step[1]*j] = '#'
        }
    }
})
var fall = ([x, y]) => {
    while (y<MAX_HEIGHT) {
        if (map[x][y+1] !== '#') y++
        else if (map[x-1][y+1] !== '#') {
            x--
            y++
        } else if (map[x+1][y+1] !== '#') {
            x++
            y++
        } else break
    }
    if (y === MAX_HEIGHT) return null
    map[x][y] = '#'
    return [x, y]
}
var count = 0
while (true) {
    if (fall([500, 0]) === null) break
    count++
}
count

Day 14 - part 2

var line = document.querySelector('pre').innerText.split('\n').filter(s => s).map(s => s.split(' -> ').map(p => p.split(',').map(Number)))
var MAX_HEIGHT = 172
var map = new Array(1000)
for (let i=0; i<map.length; i++) {
    map[i] = new Array(MAX_HEIGHT).fill('.')
    map[i][MAX_HEIGHT-1] = '#'
}
line.forEach(paths => {
    for (let i=0; i<paths.length-1; i++) {
        const diff = [paths[i+1][0]-paths[i][0], paths[i+1][1]-paths[i][1]]
        const length = Math.max(Math.abs(diff[0]), Math.abs(diff[1]))
        const step = diff.map(d => d/length)
        for (let j=0; j<length+1; j++) {
            map[paths[i][0]+step[0]*j][paths[i][1]+step[1]*j] = '#'
        }
    }
})
var fall = ([x, y]) => {
    while (y<MAX_HEIGHT) {
        if (map[x][y+1] !== '#') y++
        else if (map[x-1][y+1] !== '#') {
            x--
            y++
        } else if (map[x+1][y+1] !== '#') {
            x++
            y++
        } else break
    }
    if (x === 500 && y === 0) return null
    map[x][y] = '#'
    return [x, y]
}
var count = 1
while (true) {
    if (fall([500, 0]) === null) break
    count++
}
count

Day 15 - part 1

var line = document.querySelector('pre').innerText.split('\n').filter(s => s).map(s => {
    let [_, sensor, beacon] = s.split('at ')
    sensor = sensor.split(':')[0]
    const parseCoor = s => s.split(', ').map(each => each.split('=')[1]).map(Number)
    return [parseCoor(sensor), parseCoor(beacon)]
})
var Y = 2000000
var yRow = {}
line.forEach(([senosr, beacon]) => {
    if (senosr[1] == Y) yRow[senosr[0]] = 'S'
    if (beacon[1] == Y) yRow[beacon[0]] = 'B'
    const mDist = Math.abs(senosr[0]-beacon[0]) + Math.abs(senosr[1]-beacon[1])
    const yDist = Math.abs(Y-senosr[1])
    if (yDist <= mDist) {
        const xDist = mDist - yDist
        for (let i=senosr[0]-xDist; i<=senosr[0]+xDist; i++) {
            if (!yRow[i]) yRow[i] = '#'
        }
    }
})
Object.values(yRow).filter(p => p === '#').length

Day 15 - part 2

var line = document.querySelector('pre').innerText.split('\n').filter(s => s).map(s => {
    let [_, sensor, beacon] = s.split('at ')
    sensor = sensor.split(':')[0]
    const parseCoor = s => s.split(', ').map(each => each.split('=')[1]).map(Number)
    sensor = parseCoor(sensor)
    beacon = parseCoor(beacon)
    const mDist = Math.abs(sensor[0]-beacon[0]) + Math.abs(sensor[1]-beacon[1])
    return [sensor, mDist]
})
var MAX = 4000000
var X = []
var mergeRange = (r1, r2) => {
    if (r1[1]+1 < r2[0] || r1[0] > r2[1]+1) return [r1, r2]
    else return [Math.min(r1[0], r2[0]), Math.max(r1[1], r2[1])]
}
line.forEach(([sensor, mDist]) => {
    for (let x=Math.max(0, sensor[0]-mDist); x<=Math.min(sensor[0]+mDist, MAX); x++) {
        const yDist = mDist - Math.abs(sensor[0]-x)
        let yRange = [Math.max(0, sensor[1]-yDist), Math.min(MAX, sensor[1]+yDist)]
        let result = []
        if (!X[x]) X[x] = []
        X[x].forEach(range => {
            const merged = mergeRange(range, yRange)
            if (typeof merged[0] === 'object') result.push(merged[0])
            else yRange = merged
        })
        result.push(yRange)
        X[x] = result
    }
})
X.map((x, index) => {
    const result = []
    const sorted = x.sort((a, b) => a[0] - b[0])
    for (let i=0; i<sorted.length-1; i++) {
        result.push(`${index},${sorted[i][1]+1}`)
    }
    return result
}).filter(x => x.length)[0].forEach(p => {
    const [x, y] = p.split(',')
    console.log(x*4000000 + parseInt(y))
})

Day 16 - part 1

var graph = {}
var line = document.querySelector('pre').innerText.split('\n').filter(s => s).forEach(s => {
    let bySemi = s.split(';')
    graph[bySemi[0].split(' ')[1]] = {
        rate: parseInt(bySemi[0].split('=')[1]),
        to: bySemi[1].split(', ').map((v, i) => i === 0 ? v.split(' ')[5] : v)
    }
})
var bfs = start => {
    const walked = new Set()
    walked.add(start)
    const queue = [[start, 0]]
    while (queue.length !== 0) {
        const [target, cost] = queue.shift()
        const node = graph[target]
        if (node.rate !== 0 && start !== target) {
            graph[start][target] = cost+1
        } 
        node.to.forEach(t => {
            if (!walked.has(t)) {
                walked.add(t)
                queue.push([t, cost+1])
            }
        })
    }
}
Object.keys(graph).forEach(bfs)
Object.keys(graph).forEach(node => {
    if (graph[node].rate === 0 && node !== 'AA') delete graph[node]
})

var walked = new Set()
walked.add('AA')
var dfs = (node, mins) => {
    const [rate, to, ...targets] = Object.keys(graph[node])
    const release = graph[node].rate * mins
    const candidates = targets.filter(t => !walked.has(t)).map(t => {
        if (mins < graph[node][t]) return 0
        walked.add(t)
        const candidate = dfs(t, mins-graph[node][t])
        walked.delete(t)
        return candidate
    })
    return release + (candidates.length == 0 ? 0 : Math.max(...candidates))
}
dfs('AA', 30)

Day 16 - part 2

var walked = { 'AA': true }
var memo = {}
var dfs = (p, pMins, e, eMins) => {
    let pRelease = graph[p].rate * pMins
    let eRelease = graph[e].rate * eMins
    const comb = `${p},${e},${pMins},${eMins},${Object.entries(walked).filter(([k, v]) => v).map(([k, v]) => k).join(':')}`
    if (memo[comb]) return pRelease + eRelease + memo[comb]
    let [rate, to, ...pTargets] = Object.keys(graph[p])
    let [_rate, _to, ...eTargets] = Object.keys(graph[e])
    let max = 0
    for (let i=0; i<pTargets.length; i++) {
        const pTarget = pTargets[i]
        if (walked[pTarget] || pMins <= graph[p][pTarget]) continue
        walked[pTarget] = true
        for (let j=0; j<eTargets.length; j++) {
            const eTarget = eTargets[j]
            if (walked[eTarget] || eMins < graph[e][eTarget]) continue
            walked[eTarget] = true
            const candidate = dfs(pTarget, pMins-graph[p][pTarget], eTarget, eMins-graph[e][eTarget])
            if (candidate > max) max = candidate
            walked[eTarget] = false
        }
        walked[pTarget] = false
    }
    memo[comb] = max
    return pRelease + eRelease + max
}
dfs('AA', 26, 'AA', 26)

Day 17 - part 1

var jets = document.querySelector('pre').innerText.split('\n').filter(s => s)[0].split('').map(a => a === '>' ? 1 : -1)
var test = `>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>`.split('').map(a => a === '>' ? 1 : -1)
var chamber = []
for (let i=0; i<7; i++) chamber.push({})
var rocks = [
    {
        units: [[0, 0], [1, 0], [2, 0], [3, 0]],
        bottomChecks: [[0, -1], [1, -1], [2, -1], [3, -1]],
        leftChecks: [[-1, 0]],
        rightChecks: [[4, 0]],
    },
    {
        units: [[0, 1], [1, 1], [2, 1], [1, 0], [1, 2]],
        bottomChecks: [[0, 0], [1, -1], [2, 0]],
        leftChecks: [[0, 0], [-1, 1], [0, 2]],
        rightChecks: [[2, 0], [3, 1], [2, 2]],
    },
    {
        units: [[0, 0], [1, 0], [2, 0], [2, 1], [2, 2]],
        bottomChecks: [[0, -1], [1, -1], [2, -1]],
        leftChecks: [[-1, 0], [1, 1], [1, 2]],
        rightChecks: [[3, 0], [3, 1], [3, 2]],
    },
    {
        units: [[0, 0], [0, 1], [0, 2], [0, 3]],
        bottomChecks: [[0, -1]],
        leftChecks: [[-1, 0], [-1, 1], [-1, 2], [-1, 3]],
        rightChecks: [[1, 0], [1, 1], [1, 2], [1, 3]],
    },
    {
        units: [[0, 0], [1, 0], [0, 1], [1, 1]],
        bottomChecks: [[0, -1], [1, -1]],
        leftChecks: [[-1, 0], [-1, 1]],
        rightChecks: [[2, 0], [2, 1]],
    },
]
var jet = 0
var peak = 0
for (let i=0; i<2022; i++) {
    const rock = rocks[i%rocks.length]
    const pos = [2, peak+4]
    while (true) {
        const dir = jets[jet++ % jets.length]
        if (dir === 1) {
            if (rock.rightChecks.every(([x, y]) => x+pos[0] < 7 && !chamber[x+pos[0]]?.[y+pos[1]])) {
                pos[0] += dir
            }
        } else {
            if (rock.leftChecks.every(([x, y]) => x+pos[0] >= 0 && !chamber[x+pos[0]]?.[y+pos[1]])) {
                pos[0] += dir
            }
        }
        if (rock.bottomChecks.every(([x, y]) => y+pos[1] > 0 && !chamber[x+pos[0]]?.[y+pos[1]])) {
            pos[1]--
        } else break
    }
    rock.units.forEach(([x, y]) => {
        chamber[x+pos[0]][y+pos[1]] = 1
        peak = Math.max(peak, y+pos[1])
    })
}
peak

Day 17 - part 2

var run = (times, memo) => {
    var jet = 0
    var peak = 0
    var chamber = []
    for (let i=0; i<7; i++) chamber.push({})
    
    for (let i=0; i<times; i++) {
        const rock = rocks[i%rocks.length]
        const pos = [2, peak+4]
        while (true) {
            const dir = jets[jet++ % jets.length]
            if (dir === 1) {
                if (rock.rightChecks.every(([x, y]) => x+pos[0] < 7 && !chamber[x+pos[0]]?.[y+pos[1]])) {
                    pos[0] += dir
                }
            } else {
                if (rock.leftChecks.every(([x, y]) => x+pos[0] >= 0 && !chamber[x+pos[0]]?.[y+pos[1]])) {
                    pos[0] += dir
                }
            }
            if (rock.bottomChecks.every(([x, y]) => y+pos[1] > 0 && !chamber[x+pos[0]]?.[y+pos[1]])) {
                pos[1]--
            } else break
        }
        rock.units.forEach(([x, y]) => {
            chamber[x+pos[0]][y+pos[1]] = 1
            peak = Math.max(peak, y+pos[1])
        })
        if (memo) {
            const key = `${jet%jets.length}:${i%rocks.length}`
            if (memo[key]) {
                console.log(jet, i, key, memo[key])
            }
            memo[key] = i
        }
    }
    return peak
}
run(2022, {}) // found from memo that from 90 it starts to loop until 1780
var firstLoop = run(1780)
var beforeLoop = run(90)
var loop = 1780-90
var loopsHeight = Math.floor(1000000000000/loop) * (firstLoop-beforeLoop)
var afterLoops = run((1000000000000 % loop))
loopsHeight + afterLoops

Day 18 - part 1

var map = {}
var LENGTH = 20
for (let x=0; x<LENGTH; x++) {
    map[x] = {}
    for (let y=0; y<LENGTH; y++) {
        map[x][y] = {}
    }
}
line.map(s => s.split(',').map(Number)).forEach(([x,y,z]) => map[x][y][z] = 1)

var count = 0
for (let x=0; x<LENGTH; x++) {
    for (let y=0; y<LENGTH; y++) {
        for (let z=0; z<LENGTH; z++) {
            if (map[x][y][z] === 1) {
                const dirs = [[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]]
                count += dirs.filter(([_x, _y, _z]) => {
                    const X = x + _x
                    const Y = y + _y
                    const Z = z + _z
                    if (X < 0 || X >=LENGTH || Y < 0 || Y >=LENGTH || Z < 0 || Z >=LENGTH) return true
                    return !map[X][Y][Z]
                }).length
            }
        }
    }
}
count

Day 18 - part 2

var map = {}
var LENGTH = 20
for (let x=0; x<LENGTH; x++) {
    map[x] = {}
    for (let y=0; y<LENGTH; y++) {
        map[x][y] = {}
    }
}
line.map(s => s.split(',').map(Number)).forEach(([x,y,z]) => map[x][y][z] = 1)

var dirs = [[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]]
var countSurfaces = (x, y, z) => dirs.filter(([_x, _y, _z]) => {
    const X = x + _x
    const Y = y + _y
    const Z = z + _z
    if (X < 0 || X >=LENGTH || Y < 0 || Y >=LENGTH || Z < 0 || Z >=LENGTH) return true
    return map[X][Y][Z] === 2
}).length
var dfs = (x, y, z, walked) => {
    for (let d=0; d<dirs.length; d++) {
        const [_x, _y, _z] = dirs[d]
        const X = x + _x
        const Y = y + _y
        const Z = z + _z
        if (X < 0 || X >=LENGTH || Y < 0 || Y >=LENGTH || Z < 0 || Z >=LENGTH) {
            return 2
        }
        let type = map[X][Y][Z]
        if (!type && !walked[`${X},${Y},${Z}`]) {
            walked[`${X},${Y},${Z}`] = true
            type = dfs(X, Y, Z, walked)
            map[X][Y][Z] = type
        }
        if (!type || type === 1) continue
        return type
    }
}
for (let x=0; x<LENGTH; x++) {
    for (let y=0; y<LENGTH; y++) {
        for (let z=0; z<LENGTH; z++) {
            if (!map[x][y][z]) {
                map[x][y][z] = dfs(x, y, z, { [`${x},${y},${z}`]: true })
            }
        }
    }
}
var count = 0
for (let x=0; x<LENGTH; x++) {
    for (let y=0; y<LENGTH; y++) {
        for (let z=0; z<LENGTH; z++) {
            if (map[x][y][z] === 1) {
                count += countSurfaces(x, y, z)
            }
        }
    }
}
count

Day 19 - part 1

var blueprints = line.map(s => {
    const parts = s.split('.').map(sentence => sentence.split(' '))
    return {
        0: [parseInt(parts[0][6]), 0, 0],
        1: [parseInt(parts[1][5]), 0, 0],
        2: [parseInt(parts[2][5]), parseInt(parts[2][8]), 0],
        3: [parseInt(parts[3][5]), 0, parseInt(parts[3][8])],
    }
})

var dfs = (inventory, robots, blueprint, mins, walked) => {
    if (mins === 0) return inventory[3]
    const key = inventory.join(',') + ':' + robots.join(',')
    if (walked[key]) {
        return walked[key]
    }
    
    const newInventory = [...inventory]
    robots.forEach((r, i) => newInventory[i] += r)
    let option
    let maxGeodes = 0
    for (let robot=3; robot>=0; robot--) {
        const requirements = blueprint[robot]
        if (requirements.some((r, i) => inventory[i] < r)) continue
        
        const optionInventory = [...newInventory]
        requirements.forEach((r, i) => optionInventory[i] -= r)
        const newRobots = [...robots]
        newRobots[robot]++
        const geodes = dfs(optionInventory, newRobots, blueprint, mins-1, walked)
        if (geodes > maxGeodes) {
            maxGeodes = geodes
        }
        option = robot
        if (robot !== 1) break
    }
    let options = Object.entries(blueprint).filter(([_, requirements]) => requirements.every((r, i) => inventory[i] >= r))

    if (option != 3) {
        const optionsIfPause = Object.entries(blueprint).filter(([_, requirements]) => requirements.every((r, i) => newInventory[i] >= r))
        const pause2Inventory = [...newInventory]
        robots.forEach((r, i) => pause2Inventory[i] += r)
        const optionsIfPause2 = Object.entries(blueprint).filter(([_, requirements]) => requirements.every((r, i) => pause2Inventory[i] >= r))
        if (options.length === 0 || optionsIfPause.length > options.length) {
            const pause = dfs(newInventory, robots, blueprint, mins-1, walked)
            if (pause > maxGeodes) {
                maxGeodes = pause
                option = 'pause'
            }
        } else if (optionsIfPause2.length > options.length && mins-2 >= 0) {
            const pause2 = dfs(pause2Inventory, robots, blueprint, mins-2, walked)
            if (pause2 > maxGeodes) {
                maxGeodes = pause2
                option = 'pause2'
            }
        }
    }
    walked[key] = maxGeodes
    return maxGeodes
}

let res = 0
for (let i=0; i<blueprints.length; i++) {
    res += dfs([0, 0, 0, 0], [1, 0, 0, 0], blueprints[i], 24, {}) * (i+1)
}
res

Day 19 - part 2

let res = 1
for (let i=0; i<3; i++) {
    res *= dfs([0, 0, 0, 0], [1, 0, 0, 0], line[i], 32, {})
}
res

Day 20 - part 1

var arr = document.querySelector('pre').innerText.split('\n').filter(s => s)
var head
var ZERO
for (let i=0; i<arr.length; i++) {
    const n = parseInt(arr[i])
    arr[i] = { n }
    if (i === 0) {
        head = arr[i]
    } else if (i === arr.length-1) {
        head.prev = arr[i]
        arr[i].next = head
        arr[i-1].next = arr[i]
        arr[i].prev = arr[i-1]
    } else {
        arr[i-1].next = arr[i]
        arr[i].prev = arr[i-1]
    }
    if (n === 0) ZERO = arr[i]
}
for (let i=0; i<arr.length; i++) {
    const n = arr[i].n
    const step = n % (arr.length-1)
    if (step === 0) continue
    let dir = 'next'
    let target = arr[i]
    if (step < 0) {
        dir = 'prev'
        target = target.prev
    }
    for (let j=0; j<Math.abs(step); j++) {
        target = target[dir]
    }
    arr[i].next.prev = arr[i].prev
    arr[i].prev.next = arr[i].next
    target.next.prev = arr[i]
    arr[i].next = target.next
    target.next = arr[i]
    arr[i].prev = target
}
let res = 0
for (let i=1000; i<=3000; i+=1000) {
    const step = i % arr.length
    let target = ZERO
    for (let j=0; j<step; j++) target = target.next
    res += target.n
}
res

Day 20 - part 2

// ...
    arr[i] = { n*811589153 }
//...
for (let t=0; t<10; t++)
for (let i=0; i<arr.length; i++) {
// ...

Day 21 - part 1

eval(line.map(s => {
    let [monkey, operation] = s.split(': ')
    monkey = `var ${monkey} = () => `
    const operationParts = operation.split(' ')
    if (operationParts.length !== 1) {
        operation = `${operationParts[0]}() ${operationParts[1]} ${operationParts[2]}()`
    }
    return monkey + operation
}).join('\n') + '\n root()')

Day 21 - part 2

var map = line.reduce((res, s) => {
    const [monkey, operation] = s.split(': ')
    res[monkey] = operation.split(' ')
    return res
}, {})
var REPLACE = 'REPLACE'
var reverseOP = {
    left: {
        ['+']: '-',
        ['*']: '/',
        ['-']: '+',
        ['/']: '*',
    },
    right: {
        ['+']: '-',
        ['*']: '/',
        ['-']: '-',
        ['/']: '/',
    },
}
var dfs = (monkey) => {
    let [left, op, right] = map[monkey]
    if (monkey === 'humn') return REPLACE
    if (op == null) return left
    left = dfs(left)
    right = dfs(right)
    if (left.includes(REPLACE)) {
        return left.replace(REPLACE, `(${REPLACE}) ${reverseOP.left[op]} ${right}`)
    } else if (right.includes('REPLACE')) {
        const newLeft = op === '+' || op === '*' ? `(${REPLACE})` : left
        const newRight = op === '+' || op === '*' ? left : `(${REPLACE})`
        return right.replace(REPLACE, `${newLeft} ${reverseOP.right[op]} ${newRight}`)
    } else return `${eval([left, op, right].join(' '))}`
}
var humn = dfs(map.root[0])
eval(humn.replace(REPLACE, eval(map.root[2] + '()')))

Day 22 - part 1

With while loop

var line = document.querySelector('pre').innerText.split('\n\n')
var map = line[0].split('\n').map(s => s.split(''))
var pos = [0, map[0].indexOf('.')]
var paths = []
var temp = ''
for (let c of line[1].trim()) {
    if (['L', 'R'].includes(c)) {
        if (temp.length !== 0) {
            paths.push(parseInt(temp))
            temp = ''
        }
        paths.push(c)
    } else temp += c
}
if (temp.length !== 0) {
    paths.push(parseInt(temp))
}
var faces = [[0, 1], [1, 0], [0, -1], [-1, 0]] // R, D, L, U
var face = 0
for (let p=0; p<paths.length; p++) {
    const path = paths[p]
    if (path === 'L') {
        face = (face+faces.length-1) % faces.length
    } else if (path === 'R') {
        face = (face+1) % faces.length
    } else {
        let [x, y] = pos
        const [dX, dY] = faces[face]
        for (let i=0; i<path; i++) {
            let newX = x
            let newY = y
            while (true) {
                newX += dX
                newY += dY
                if (newX >= map.length) newX = 0
                else if (newX < 0) newX = map.length-1
                else if (newY >= map[0].length) newY = 0
                else if (newY < 0) newY = map[newX].length-1
                if (map[newX][newY] && map[newX][newY] !== ' ') break
            }
            if (map[newX][newY] === '#') break
            else {
                x = newX
                y = newY
            }
            map[newX][newY] = 'X'
        }
        pos = [x, y]
    }
}
(pos[0]+1)*1000 + (pos[1]+1)*4 + face

Without while loop

var line = document.querySelector('pre').innerText.split('\n\n')
var test = `        ...#
        .#..
        #...
        ....
...#.......#
........#...
..#....#....
..........#.
        ...#....
        .....#..
        .#......
        ......#.

10R5L5R10L4R5L5`.split('\n\n')
var map = line[0].split('\n').map(s => s.split('').map(n => n === ' ' ? undefined : n))
var mapWidth = map[8].length
var swapMap = []
for (let j=0; j<mapWidth; j++) {
    swapMap[j] = []
    for (let i=0; i<map.length; i++) {
        swapMap[j][i] = map[i][j]
    }
}
var pos = [0, map[0].indexOf('.')]
var paths = []
var temp = ''
for (let c of line[1].trim()) {
    if (['L', 'R'].includes(c)) {
        if (temp.length !== 0) {
            paths.push(parseInt(temp))
            temp = ''
        }
        paths.push(c)
    } else temp += c
}
if (temp.length !== 0) {
    paths.push(parseInt(temp))
}
var faces = [[0, 1], [1, 0], [0, -1], [-1, 0]] // R, D, L, U
var face = 0
for (let p=0; p<paths.length; p++) {
    const path = paths[p]
    if (path === 'L') {
        face = (face+faces.length-1) % faces.length
    } else if (path === 'R') {
        face = (face+1) % faces.length
    } else {
        let [x, y] = pos
        const [dX, dY] = faces[face]
        for (let i=0; i<path; i++) {
            let newX = x + dX
            let newY = y + dY
            if (!map[newX]?.[newY] || map[newX][newY] === ' ') {
                if (face === 0) newY = Math.min(map[newX].indexOf('.'), map[newX].indexOf('#'))
                else if (face === 1) newX = Math.min(swapMap[newY].indexOf('.'), swapMap[newY].indexOf('#'))
                else if (face === 2) newY = Math.max(map[newX].lastIndexOf('.'), map[newX].lastIndexOf('#'), map[newX].lastIndexOf('X'))
                else newX = Math.max(swapMap[newY].lastIndexOf('.'), swapMap[newY].lastIndexOf('#'), swapMap[newY].lastIndexOf('X'))
            }
            if (map[newX][newY] === '#') break
            else {
                x = newX
                y = newY
            }
        }
        pos = [x, y]
    }
}
(pos[0]+1)*1000 + (pos[1]+1)*4 + face

Day 22 - part 2

var transformR50to99 = x => [49, x+50, 3]
var transformD100to149 = y => [y-50, 99, 2]
var transformL50to99 = x => [100, x-50, 1]
var transformU0to49 = y => [y+50, 50, 0]
var transformR0to49 = x => [149-x, 99, 2]
var transformR100to149 = x => [149-x, 149, 2]
var transformL0to49 = x => [149-x, 0, 0]
var transformL100to149 = x => [149-x, 50, 0]
var transformD50to99 = y => [y+100, 49, 2]
var transformR150to199 = x => [149, x-100, 3]
var transformU50to99 = y => [y+100, 0, 0]
var transformL150to199 = x => [0, x-100, 1]
var transformU100to149 = y => [199, y-100, 3]
var transformD0to49 = y => [0, y+100, 1]
for (let p=0; p<paths.length; p++) {
    const path = paths[p]
    if (path === 'L') {
        face = (face+faces.length-1) % faces.length
    } else if (path === 'R') {
        face = (face+1) % faces.length
    } else {
        let [x, y] = pos
        for (let i=0; i<path; i++) {
            const [dX, dY] = faces[face]
            let newX = x
            let newY = y
            let newFace = face
            while (true) {
                newX += dX
                newY += dY
                if (newX >= map.length) {
                    const transformed = y < 50
                        ? transformD0to49(y)
                        : y < 100
                            ? transformD50to99(y)
                            : transformD100to149(y)
                    newX = transformed[0]
                    newY = transformed[1]
                    newFace = transformed[2]
                } else if (newX < 0) {
                    const transformed = y < 50
                        ? transformU0to49(y)
                        : y < 100
                            ? transformU50to99(y)
                            : transformU100to149(y)
                    newX = transformed[0]
                    newY = transformed[1]
                    newFace = transformed[2]
                } else if (newY >= map[0].length) {
                    const transformed = x < 50
                        ? transformR0to49(x)
                        : x < 100
                            ? transformR50to99(x)
                            : x < 150
                                ? transformR100to149(x)
                                : transformR150to199(x)
                    newX = transformed[0]
                    newY = transformed[1]
                    newFace = transformed[2]
                } else if (newY < 0) {
                    const transformed = x < 50
                        ? transformL0to49(x)
                        : x < 100
                            ? transformL50to99(x)
                            : x < 150
                                ? transformL100to149(x)
                                : transformL150to199(x)
                    newX = transformed[0]
                    newY = transformed[1]
                    newFace = transformed[2]
                }
                if (map[newX][newY] && map[newX][newY] !== ' ') break
            }
            if (map[newX][newY] === '#') break
            else {
                x = newX
                y = newY
                face = newFace
            }
        }
        pos = [x, y]
    }
}
(pos[0]+1)*1000 + (pos[1]+1)*4 + face

Day 23 - part 1

var elves = []
var map = {}
line.forEach((row, i) => {
    map[i] = {}
    row.split('').forEach((p, j) => {
        if (p === '#') {
            elves.push([i, j])
            map[i][j] = '#'
        }
    })
    return map
})
var DIRS = {
    N: [-1, 0],
    S: [1, 0],
    E: [0, 1],
    W: [0, -1],
    NE: [-1, 1],
    NW: [-1, -1],
    SE: [1, 1],
    SW: [1, -1],
}
var lookDirs = [
    [ DIRS.N, DIRS.NE, DIRS.NW ],
    [ DIRS.S, DIRS.SE, DIRS.SW ],
    [ DIRS.W, DIRS.NW, DIRS.SW ],
    [ DIRS.E, DIRS.NE, DIRS.SE ]
]
var run = () => {
    const targets = {}
    elves.forEach((elf, i) => {
        for (let l=0; l<lookDirs.length; l++) {
            if (Object.values(DIRS).every(dir => map[elf[0]+dir[0]]?.[elf[1]+dir[1]] !== '#')) break
            if (lookDirs[l].every(dir => map[elf[0]+dir[0]]?.[elf[1]+dir[1]] !== '#')) {
                const [dX, dY] = lookDirs[l][0]
                const newX = elf[0]+dX
                const newY = elf[1]+dY
                if (!targets[newX]) targets[newX] = {}
                if (!targets[newX][newY]) targets[newX][newY] = []
                targets[newX][newY].push(i)
                break
            }
        }
    })

    Object.entries(targets).forEach(([x, v]) => {
        Object.entries(v).forEach(([y, candidates]) => {
            if (candidates.length === 1) {
                const [originX, originY] = elves[candidates[0]]
                delete map[originX][originY]
                elves[candidates[0]] = [parseInt(x), parseInt(y)]
                if (!map[x]) map[x] = {}
                map[x][y] = '#'
            }
        })
    })
    lookDirs.push(lookDirs.shift())
}
for (let i=0; i<10; i++) {
    run()
}

var sortedX = Object.keys(map).filter(x => Object.keys(map[x]).length).map(Number).sort((a, b) => a-b)
var height = sortedX[sortedX.length-1] - sortedX[0] + 1
var minY = Infinity
var maxY = -Infinity
Object.values(map).filter(row => Object.keys(row).length).forEach(row => {
    const sortedY = Object.keys(row).map(Number).sort((a, b) => a-b)
    minY = Math.min(minY, sortedY[0])
    maxY = Math.max(maxY, sortedY[sortedY.length-1])
    width = Math.max(width, sortedY[sortedY.length-1] - sortedY[0] + 1)
})
var width = maxY - minY + 1
height*width - elves.length

Day 23 - part 2

var run = () => {
    const targets = {}
    if (elves.filter((elf, i) => {
        for (let l=0; l<lookDirs.length; l++) {
            if (Object.values(DIRS).every(dir => map[elf[0]+dir[0]]?.[elf[1]+dir[1]] !== '#')) return false
            if (lookDirs[l].every(dir => map[elf[0]+dir[0]]?.[elf[1]+dir[1]] !== '#')) {
                const [dX, dY] = lookDirs[l][0]
                const newX = elf[0]+dX
                const newY = elf[1]+dY
                if (!targets[newX]) targets[newX] = {}
                if (!targets[newX][newY]) targets[newX][newY] = []
                targets[newX][newY].push(i)
                break
            }
        }
        return true
    }).length === 0) return true

    Object.entries(targets).forEach(([x, v]) => {
        Object.entries(v).forEach(([y, candidates]) => {
            if (candidates.length === 1) {
                const [originX, originY] = elves[candidates[0]]
                delete map[originX][originY]
                elves[candidates[0]] = [parseInt(x), parseInt(y)]
                if (!map[x]) map[x] = {}
                map[x][y] = '#'
            }
        })
    })
    lookDirs.push(lookDirs.shift())
}
for (let i=0;; i++) {
    if (run()) {
        console.log(i)
        break
    }
}

Day 24 - part 1

line.shift()
line.pop()
var originMap = line.map(s => {
    const row = s.split('')
    row.shift()
    row.pop()
    return row
})
var maps = new Array(originMap.length*originMap[0].length)
maps[0] = originMap

for (let i=1; i<maps.length; i++) {
    const nextMap = new Array(originMap.length)
    for (let x=0; x<originMap.length; x++) {
        if (!nextMap[x]) nextMap[x] = []
        for (let y=0; y<originMap[0].length; y++) {
            if (originMap[x][y] === '>') {
                const newY = (y+i) % originMap[0].length
                if (!nextMap[x][newY]) nextMap[x][newY] = ''
                nextMap[x][newY] += originMap[x][y]
            } else if (originMap[x][y] === '<') {
                const newY = (y - (i % originMap[0].length) + originMap[0].length) % originMap[0].length
                if (!nextMap[x][newY]) nextMap[x][newY] = ''
                nextMap[x][newY] += originMap[x][y]
            } else if (originMap[x][y] === 'v') {
                const newX = (x+i) % originMap.length
                if (!nextMap[newX]) nextMap[newX] = []
                if (!nextMap[newX][y]) nextMap[newX][y] = ''
                nextMap[newX][y] += originMap[x][y]
            } else if (originMap[x][y] === '^') {
                const newX = (x - (i % originMap.length) + originMap.length) % originMap.length
                if (!nextMap[newX]) nextMap[newX] = []
                if (!nextMap[newX][y]) nextMap[newX][y] = ''
                nextMap[newX][y] += originMap[x][y]
            }
        }
    }
    maps[i] = nextMap
}
var DIRS = [[0, 1], [1, 0], [0, -1], [-1, 0], [0, 0]]

// Maximum call stack size exceeded
// var memo = {}
// var dfs = ([x, y], depth) => {
//     const nextDepth = depth+1
//     let min = Infinity
//     for (let d=0; d<DIRS.length; d++) {
//         const [dX, dY] = DIRS[d]
//         const newX = x + dX
//         const newY = y + dY
//         if (newX === originMap.length -1 && newY === originMap[0].length-1) return nextDepth+1
//         if (d !== 4 && (newX < 0 || newX === originMap.length || newY < 0 || newY === originMap[0].length)) continue
//         const next = maps[nextDepth%maps.length][newX]?.[newY]
//         if (next && next !== '.') continue

//         const key = `${newX},${newY},${nextDepth%maps.length}`
//         if (memo[key]) continue
//         else memo[key] = true

//         min = Math.min(min, dfs([newX, newY], nextDepth))
//     }
//     return min
// }
// dfs([-1, 0], 0)
var bfs = () => {
    var memo = new Set()
    const queue = [[-1, 0, 0]]
    let min = Infinity
    while (queue.length !== 0) {
        const [x, y, depth] = queue.shift()
        const nextDepth = depth+1
        for (let d=0; d<DIRS.length; d++) {
            const [dX, dY] = DIRS[d]
            const newX = x + dX
            const newY = y + dY
            if (newX === originMap.length && newY === originMap[0].length-1) {
                min = Math.min(min, nextDepth)
                break
            }
            if (d !== 4 && (newX < 0 || newX === originMap.length || newY < 0 || newY === originMap[0].length)) continue
            const next = maps[nextDepth%maps.length][newX]?.[newY]
            if (next && next !== '.') continue
            const key = `${newX},${newY},${nextDepth%maps.length}`
            if (memo.has(key)) continue

            memo.add(key)
            queue.push([newX, newY, nextDepth])
        }
    }
    return min
}
bfs()

Day 24 - part 2

var bfs = (start, end, initDepth) => {
    var memo = new Set()
    const queue = [[...start, initDepth]]
    let min = Infinity
    while (queue.length !== 0) {
        const [x, y, depth] = queue.shift()
        const nextDepth = depth+1
        for (let d=0; d<DIRS.length; d++) {
            const [dX, dY] = DIRS[d]
            const newX = x + dX
            const newY = y + dY
            if (newX === end[0] && newY === end[1]) {
                min = Math.min(min, nextDepth)
                break
            }
            if (d !== 4 && (newX < 0 || newX >= originMap.length || newY < 0 || newY >= originMap[0].length)) continue
            const next = maps[nextDepth%maps.length][newX]?.[newY]
            if (next && next !== '.') continue
            const key = `${newX},${newY},${nextDepth%maps.length}`
            if (memo.has(key)) continue

            memo.add(key)
            queue.push([newX, newY, nextDepth])
        }
    }
    return min
}
bfs([-1, 0], [originMap.length, originMap[0].length-1],
    bfs([originMap.length, originMap[0].length-1], [-1, 0],
       bfs([-1, 0], [originMap.length, originMap[0].length-1], 0)))

Day 25 - part 1

var nums = line.map(n => n.split('').map(d => d === '-'
    ? -1
    : d === '='
        ? -2
        : parseInt(d)
).reverse())
var overflow = 0
var res = []
for (let i=0;; i++) {
    const digitSum = nums.map(n => n[i]).filter(s => s).reduce((s, d) => s+d, 0) + overflow
    if (digitSum === 0) break
    overflow = digitSum / 5
    overflow = overflow > 0 ? Math.floor(overflow) : Math.ceil(overflow)
    let reminder = digitSum % 5
    if (reminder > 2) {
        overflow++
        reminder -= 5
    } else if (reminder < -2) {
        overflow--
        reminder += 5
    }
    res.push(reminder) 
}
res.reverse().reduce((r, d) => r += d === -1 
    ? '-' 
    : d === -2
        ? '='
        : d, '')

Day 25 - part 2

There is no such thing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment