Skip to content

Instantly share code, notes, and snippets.

@carpusherw
Last active December 29, 2021 18:38
Show Gist options
  • Save carpusherw/96e394180194a17d57a47562ca90251b to your computer and use it in GitHub Desktop.
Save carpusherw/96e394180194a17d57a47562ca90251b to your computer and use it in GitHub Desktop.

Advent of Code 2021

https://adventofcode.com/2021

Coding in browser developer tools.

Get input

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

or

var arr
fetch('https://adventofcode.com/2021/day/XX/input')
  .then(response => response.text())
  .then(data => { arr = data.split('\n') })

Day 1 - part 1

arr.filter((n, i) => i != 0 && n > arr[i-1]).length

Day 1 - part 2

arr.filter((n, i) => i >= 3 && n > arr[i-3]).length

Day 2 - part 1

var x = y = 0
arr.map(item => item.split(' ')).forEach(([direction, valueString]) => {
  const value = parseInt(valueString)
  direction === 'forward' && (x += value)
  direction === 'down' && (y += value)
  direction === 'up' && (y -= value)
})
x*y

Day 2 - part 2

var y2 = aim = 0
arr.map(item => item.split(' ')).forEach(([direction, valueString]) => {
  const value = parseInt(valueString)
  direction === 'forward' && (y2 += value * aim)
  direction === 'down' && (aim += value)
  direction === 'up' && (aim -= value)
})
x*y2

Day 3 - part 1

var a = arr.map(item => item.split('').map(s => parseInt(s)))
  .reduce(
    (result, item) => result.map((r, i) => r + item[i]),
    Array(arr[0].length).fill(0)
  )
  .map(num => num > arr.length/2 ? 1 : 0)

var b = a.map(x => x ? 0 : 1)
var g = parseInt(a.reduce((result, num) => '' + result + num), 2)
var e = parseInt(b.reduce((result, num) => '' + result + num), 2)

Day 3 - part 2

var find = (type, rest=arr, index=0) => {
  const count = rest
    .map(item => parseInt(item[index]))
    .reduce((r, n) => r + n)
  const next = rest.filter(item => item[index] == ((count >= rest.length / 2 ? 1 : 0) ^ type))
  return next.length === 1 ? parseInt(next[0], 2) : find(type, next, index + 1)
}
find(0) * find(1)

Day 4 - part 1

var input = document.querySelector('pre').innerText.split('\n')
var draw = input[0].split(',').map(d => parseInt(d))
var point = 0
var maxCall = draw.length
for (let i=2; i<input.length; i+=6) {
  let board = Array.from(Array(10), () => new Array())
  let mapToBoard = {}
  for (let r=0; r<5; r++) {
    var nums = input[i+r].split(' ').filter(s => s !== '').map(s => parseInt(s))
    for (let c=0; c<5; c++) {
      const num = nums[c]
      board[r].push(num)
      board[c+5].push(num)
      mapToBoard[num] = [board[r], board[c+5]]
    }
  }
  for (let call=0; call < maxCall; call++) {
    let isBingo = false
    const d = draw[call]
    mapToBoard[d]?.forEach(boardEntry => {
      const index = boardEntry.indexOf(d);
      if (index > -1) {
        boardEntry.splice(index, 1);
      }
      if (boardEntry.length === 0) {
        isBingo = true
      }
    })
    if (isBingo) {
      const sum = board.slice(0, 5).flat().reduce((sum, r) => sum + r)
      const point = sum * d
      if (call < maxCall) {
        point = sum * d
        maxCall = call
        console.log('point: ', point)
      }
      break
    }
  }
}

Day 4 - part 2

var point = 0
var maxCall = 0
for (let i=2; i<input.length; i+=6) {
  let board = Array.from(Array(10), () => new Array())
  let mapToBoard = {}
  for (let r=0; r<5; r++) {
    var nums = input[i+r].split(' ').filter(s => s !== '').map(s => parseInt(s))
    for (let c=0; c<5; c++) {
      const num = nums[c]
      board[r].push(num)
      board[c+5].push(num)
      mapToBoard[num] = [board[r], board[c+5]]
    }
  }
  for (let call=0; call < draw.length; call++) {
    let isBingo = false
    const d = draw[call]
    mapToBoard[d]?.forEach(boardEntry => {
      const index = boardEntry.indexOf(d);
      if (index > -1) {
        boardEntry.splice(index, 1);
      }
      if (boardEntry.length === 0) {
        isBingo = true
      }
    })
    if (isBingo) {
      const sum = board.slice(0, 5).flat().reduce((sum, r) => sum + r)
      const point = sum * d
      if (call > maxCall) {
        lastPoint = sum * d
        maxCall = call
        console.log('point: ', point)
      }
      break
    }
  }
}

Day 5 - part 1

var map = {}
var count = 0
arr.forEach(l => {
  let [a, b] = l.split(' -> ')
    .map(s => s.split(',').map(s => parseInt(s)))
    .map(([x, y]) => ({x, y}))
  if (a.x === b.x) {
    const start = a.y < b.y ? a.y : b.y
    const end = a.y < b.y ? b.y : a.y
    for (let i=start; i<=end; i++) {
      if (map[`${a.x},${i}`]++ === 1) {
        count++
      } else {
        map[`${a.x},${i}`] = 1
      }
    }
  } else if (a.y === b.y) {
    const start = a.x < b.x ? a.x : b.x
    const end = a.x < b.x ? b.x : a.x
    for (let i=start; i<=end; i++) {
      if (map[`${i},${a.y}`]++ === 1) {
        count++
      } else {
        map[`${i},${a.y}`] = 1
      }
    }
  }
})

Day 5 - part 2

arr.forEach(l => {
  let [a, b] = l.split(' -> ')
    .map(s => s.split(',').map(s => parseInt(s)))
    .map(([x, y]) => ({x, y}))
  if (a.x === b.x) {
    const start = a.y < b.y ? a.y : b.y
    const end = a.y < b.y ? b.y : a.y
    for (let i=start; i<=end; i++) {
      if (!map[`${a.x},${i}`]) {
        map[`${a.x},${i}`] = 1
      } else if (map[`${a.x},${i}`]++ === 1) {
        count++
      }
    }
  } else if (a.y === b.y) {
    const start = a.x < b.x ? a.x : b.x
    const end = a.x < b.x ? b.x : a.x
    for (let i=start; i<=end; i++) {
      if (!map[`${i},${a.y}`]) {
        map[`${i},${a.y}`] = 1
      } else if (map[`${i},${a.y}`]++ === 1) {
        count++
      }
    }
  } else {
    const xStep = a.x < b.x ? 1 : -1
    const yStep = a.y < b.y ? 1 : -1
    console.log(a.x, a.y, b.x, b.y, '>>>>')
    for (let i=a.x; (a.x < b.x) ? (i<=b.x) : (i>=b.x); i+=xStep) {
      const x = a.x + xStep * Math.abs(a.x-i)
      const y = a.y + yStep * Math.abs(a.x-i)
      if (!map[`${x},${y}`]) {
        map[`${x},${y}`] = 1
      } else if (map[`${x},${y}`]++ === 1) {
        count++
      }
    }
  }
})

Day 6 - part 1

var result = arr[0].split(',').map(s => parseInt(s))
for (let i=0; i<80; i++) {
  const current = result
  result = []
  for (let j=0; j<current.length; j++) {
    const value = current[j]-1
    if (value < 0) {
      result.push(6)
      result.push(8)
    } else {
      result.push(value)
    }
  }
}

Day 6 - part 2

Didn't write code, but divded to 128 and conquered.

When starting array is [1], with part 1 after 128 days, it becomes a 90763 long array. Calcualte all single number arrays for 128 days.

After that, check how many 0s, 1s, ..., or 8s in the result arrays and multiply the result length. Finally check how many 0s, 1s, ..., or 8s in the input array and multiploy the 256 result length.

[1] / 128 => 90763 / 256 => 6206821033
[2] / 79321 / 5617089148
[3] / 75638 / 5217223242
[4] / 67616 / 4726100874
[5] / 62475 / 4368232009
[6] / 58016
[7] / 51564
[8] / 49380
[0] / 94508
6206821033 * 191 + 5617089148 * 30 + 5217223242 * 20 + 4726100874 * 35 + 4368232009 * 24

It could be divided and conquered from 1, 2, 4, ... to replace part 1 and become a O(m*logn) algorithm where m is number of possible numbers and n is days.

Most peoople use a O(m*n) that shifts numbers of numbers to number-1 buckets.

Day 7 - part 1

var input = arr[0].split(',').map(s => parseInt(s))
input.sort((a, b) => a-b)
var min = Infinity
for (let i=0; i<=input[input.length-1]; i++) {
  var fuel = arr.map(n => Math.abs(n-i)).reduce((r, n) => r+n)
  if (fuel < min) {
    min = fuel
    console.log(i, min)
  }
}

Day 7 - part 2

var accuMap = {0: 0}
var sum = 0
for (let i=1; input[input.length-1]; i++) {
  sum += i
  accuMap[i] = sum
}
var min = Infinity
for (let i=0; i<=input[input.length-1]; i++) {
  var fuel = input
    .map(n => Math.abs(n-i))
    .map(n => accuMap[n])
    .reduce((r, n) => r+n)
  if (fuel < min) {
    min = fuel
    console.log(i, min)
  }
}

Day 8 - part 1

var input = arr.map(l => l.split(' | ').map(s => s.split(' ').map(s => s.split('').sort().reduce((r, s) => r+s))))
input.map(([signal, match]) => 
  match.filter(m => m.length === 2 || m.length === 3 || m.length === 4 || m.length === 7)
    .filter(m => signal.indexOf(m) !== -1).length
).reduce((r, n) => r+n)

Day 8 - part 2

var fn = signal => {
  const map = {
    [signal.filter(s => s.length === 2)[0]]: '1',
    [signal.filter(s => s.length === 4)[0]]: '4',
    [signal.filter(s => s.length === 3)[0]]: '7',
    [signal.filter(s => s.length === 7)[0]]: '8',
    1: signal.filter(s => s.length === 2)[0],
    4: signal.filter(s => s.length === 4)[0],
    7: signal.filter(s => s.length === 3)[0],
  }
  signal.forEach(s => {
    if ([2, 3, 4, 7].indexOf(s.length) !== -1) { return }
    if (s.length === 5) {
      if (map[7].split('').every(a => s.indexOf(a) !== -1)) {
        map[s] = '3'
      } else if (map[4].split('').filter(a => s.indexOf(a) !== -1).length === 3) {
        map[s] = '5'
      } else {
        map[s] = '2'
      }
    } else { // 6
      if (map[4].split('').every(a => s.indexOf(a) !== -1)) {
        map[s] = '9'
      } else if (map[1].split('').every(a => s.indexOf(a) !== -1)) {
        map[s] = '0'
      } else {
        map[s] = '6'
      }
    }
  })
  return map
}

input.map(([signal, digits]) => 
  digits.map(d => fn(signal)[d]).reduce((r, s) => r+s)
).map(s => parseInt(s)).reduce((r, n) => r+n)

Day 9 - part 1

var input = arr.map(l => l.split('').map(s => parseInt(s)))
var map = {}
input.forEach((l, i, o) => {
  l.forEach((n, j) => {
    if ((j === 0 && n < l[j+1])
      || (j === l.length-1 && n < l[j-1])
      || (n < l[j+1] && n < l[j-1])
    ) {
      map[`${i},${j}`] = 1
    }
    if (i !== 0 && l[j] > o[i-1][j] && map[`${i-1},${j}`] === 1) {
      map[`${i-1},${j}`] = 2
    }
    if (i !== 0 && l[j] >= o[i-1][j] && map[`${i},${j}`] === 1) {
      map[`${i},${j}`] = 0
    }
    if (i === o.length-1 && map[`${i},${j}`] === 1) {
      map[`${i},${j}`] = 2
    }
  })
})
var sum = 0
for (let i in map) {
  if (map[i] === 2) {
    const [x, y] = i.split(',')
    sum += input[x][y] + 1
  }
}

Day 9 - part 2

for (let i in map) {
  if (map[i] === 2) {
    map[i] = 0
  } else {
    delete map[i]
  }
}
var findBasin = (input, arr, checked={}) => {
  arr.forEach(({x, y}) => {
    checked[`${x},${y}`] = 1
    const nextArr = []
    if (x-1 >= 0 && input[x-1][y] !== 9 && !checked[`${x-1},${y}`]) {
      nextArr.push({x: x-1, y})
    }
    if (x+1 < input.length && input[x+1][y] !== 9 && !checked[`${x+1},${y}`]) {
      nextArr.push({x: x+1, y})
    }
    if (y-1 >= 0 && input[x][y-1] !== 9 && !checked[`${x},${y-1}`]) {
      nextArr.push({x, y: y-1})
    }
    if (y+1 < input[0].length && input[x][y+1] !== 9 && !checked[`${x},${y+1}`]) {
      nextArr.push({x, y: y+1})
    }
    findBasin(input, nextArr, checked)
  })
  return checked
}
var basinSizes = Object.entries(map).map(([key, value]) => {
  const [x, y] = key.split(',').map(s => parseInt(s))
  return { x, y }
}).map(i => Object.entries(findBasin(input, [i])).length)
  .sort((a, b) => b-a)
basinSizes[0] * basinSizes[1] * basinSizes[2]

Day 10 - part 1

var input = arr.map(s => s.split(''))
var map = {
  [')']: 0,
  [']']: 0,
  ['}']: 0,
  ['>']: 0,
}
var fn = line => {
  const stack = []
  for (let i=0; i<line.length; i++) {
    const last = stack.pop()
    const x = line[i]
    if (x === '(' || x === '[' || x === '{' || x === '<') {
      stack.push(last, x)
    } else if ((x === ')' && last !== '(')
        || (x === ']' && last !== '[')
        || (x === '}' && last !== '{')
        || (x === '>' && last !== '<')
      ) {
      map[x] += 1
      console.log(line, i, x, last)
      break
    }
  }
}
input.forEach(line => fn(line))
map[')']*3 + map[']']*57 + map['}']*1197 + map['>']*25137

Day 10 - part 2

var fn = line => {
  const stack = []
  for (let i=0; i<line.length; i++) {
    const last = stack.pop()
    const x = line[i]
    if (x === '(' || x === '[' || x === '{' || x === '<') {
      stack.push(last, x)
    } else if ((x === ')' && last !== '(')
        || (x === ']' && last !== '[')
        || (x === '}' && last !== '{')
        || (x === '>' && last !== '<')
      ) {
      return -1
    }
  }
  return stack.filter(s => s).reverse().map(x => x === '('
    ? 1
    : x === '['
      ? 2
      : x === '{'
        ? 3
        : 4
  )
}
var scores = input.map(line => fn(line)).filter(x => x !== -1).map(line => line.reduce((r, n) => r*5 + n, 0))
scores.sort((a, b) => a-b)
scores[Math.floor(scores.length/2)]

Day 11 - part 1

var input = arr.map(s => s.split('').map(s => parseInt(s)))
var flashes = 0
var add = (input, [x, y]) => {
  if (++input[x][y] === 10) {
    flash(input, x, y)
  }
}
var flash = (input, i, j) => {
  flashes++
  [
    [i-1, j-1],
    [i, j-1],
    [i+1, j-1],
    [i-1, j],
    [i+1, j],
    [i-1, j+1],
    [i, j+1],
    [i+1, j+1],
  ].filter(([x, y]) => input[x]?.[y] != null).forEach(coor => add(input, coor))
}
var step = input => {
  for (let i=0; i<input.length; i++) {
    for (let j=0; j<input[0].length; j++) {
      add(input, [i, j])
    }
  }
  for (let i=0; i<input.length; i++) {
    for (let j=0; j<input[0].length; j++) {
      input[i][j] = input[i][j] >= 10 ? 0 : input[i][j]
    }
  }
}
for (let i=0; i<100; i++) { step(input) }

Day 11 - part 2

for (let i=1; i<1000; i++) {
  step(input)
  if (input.every(l => l.every(n => n === 0))) {
    console.log(i)
    break
  }
}

Day 12 - part 1

var map = arr.map(s => s.split('-')).reduce((r, [a, b]) => ({
  ...r,
  [a]: r[a] ? r[a].concat(b) : [b],
  [b]: r[b] ? r[b].concat(a) : [a],
}), {})
var countPath = (map, start) => {
  if (start === 'end') { return 1 }
  const { [start]: directions, ...rest } = map
  return directions.filter(d => map[d]).reduce((r, d) => r + countPath(start === start.toUpperCase() ? map : rest, d), 0)
}
countPath(map, 'start')

Day 12 - part 2

var countPath = (map, start, small={}) => {
  if (start === 'end') { return 1 }
  const { [start]: directions, ...rest } = map
  let nextMap
  if (start === start.toUpperCase()) {
    nextMap = map
  } else if (start !== 'start') {
    small[start] = small[start] ? small[start]+1 : 1
    if (Object.entries(small).some(([_, value]) => value >= 2)) {
      nextMap = { ...rest }
      for (const [key] of Object.entries(small)) {
        delete nextMap[key]
      }
    } else {
      nextMap = map
    }
  } else {
    nextMap = rest
  }
  return directions.filter(d => nextMap[d]).reduce((r, d) => r + countPath(nextMap, d, { ...small }), 0)
}

Day 13 - part 1

var coors = arr.filter(s => !s.startsWith('fold')).map(s => s.split(',').map(s => parseInt(s)))
var foldX = (coors, x) => {
  const remain = coors.filter(coor => coor[0] <= x)
  const folded = coors.filter(coor => coor[0] > x)
  return remain.concat(folded.map(coor => [x * 2 - coor[0], coor[1]]).filter(coor => remain.findIndex(i => coor[0] === i[0] && coor[1] === i[1]) === -1))
}
var foldY = (coors, y) => {
  const remain = coors.filter(coor => coor[1] <= y)
  const folded = coors.filter(coor => coor[1] > y)
  return remain.concat(folded.map(coor => [coor[0], y * 2 - coor[1]]).filter(coor => remain.findIndex(i => coor[0] === i[0] && coor[1] === i[1]) === -1))
}

Day 13 - part 2

var fold = arr.filter(s => s.startsWith('fold')).map(s => s.split('fold along ')[1].split('='))
fold.forEach(f => {
  if (f[0] === 'x') {
    coors = foldX(coors, parseInt(f[1]))
  } else {
    coors  = foldY(coors, parseInt(f[1]))
  }
})

var graph = Array.from(Array(50), () => new Array(15).fill(0))
coors.forEach(c => graph[c[0]][c[1]] = 1)

Day 14 - part 1

var template = arr[0]
var map = arr.slice(1).reduce((r, i) => ({ ...r, [i.split(' -> ')[0]]: i.split(' -> ')[1] }), {})
var step = (current, _map=map) => {
  let result = current[0]
  for (let i=1; i<current.length; i++) {
    const insertion = _map[`${current[i-1]}${current[i]}`]
    if (insertion) {
      result += insertion
    }
    result += current[i]
  }
  return result
}
var tenSteps = step(step(step(step(step(step(step(step(step(step(template))))))))))
tenSteps.split('').reduce((r, s) => ({ ...r, [s]: r[s] ? r[s]+1 : 1 }), {})

Day 14 - part 2

var countMap = {}
for (let i=1; i<template.length; i++) {
  countMap[template[i-1]+template[i]] = 1
}
var nStep = (n, countMap) => {
  if (n === 0) { return countMap }
  const result = {  }
  Object.keys(countMap).filter(k => countMap[k]).forEach(s => {
    result[s[0]+map[s]] = result[s[0]+map[s]] ? result[s[0]+map[s]] + countMap[s] : countMap[s]
    result[map[s]+s[1]] = result[map[s]+s[1]] ? result[map[s]+s[1]] + countMap[s] : countMap[s]
  })
  return nStep(n-1, result)
}
var countMap40 = nStep(40, countMap)
Object.keys(countMap40).reduce((r, k) => ({ ...r, [k[0]]: r[k[0]] ? r[k[0]] + countMap40[k] : countMap40[k] }), {})

Day 15 - part 1

var map = arr.map(r => r.split('').map(s => parseInt(s)))
var allDirections = () => {
  const _riskMap = {}
  let changed
  do {
    changed = false
    for (let i=0; i<map.length; i++) {
      for (let j=0; j<map[0].length; j++) {
        if (i === 0 && j === 0) {
          _riskMap[`${i},${j}`] = 0
          continue
        }
        var from = [
          _riskMap[`${i-1},${j}`] != null ? _riskMap[`${i-1},${j}`] : Infinity,
          _riskMap[`${i},${j-1}`] != null ? _riskMap[`${i},${j-1}`] : Infinity,
          _riskMap[`${i},${j+1}`] != null ? _riskMap[`${i},${j+1}`] : Infinity,
          _riskMap[`${i+1},${j}`] != null ? _riskMap[`${i+1},${j}`] : Infinity,
        ].map(n => n + map[i][j])
        const current = _riskMap[`${i},${j}`] != null ? _riskMap[`${i},${j}`] : Infinity
        const updated = Math.min(...from, current) 
        if (updated !== current) {
          _riskMap[`${i},${j}`] = updated
          changed = true
        }
      }
    }
  } while(changed)
  return _riskMap
}
allDirections()['99,99']

Day 15 - part 2

var map1 = arr.map(r => r.split('').map(s => parseInt(s)))
var add = n => o => (o+n)%9 === 0 ? 9 : (o+n)%9
var _map = map1.map(a => [
  ...a,
  ...a.map(add(1)),
  ...a.map(add(2)),
  ...a.map(add(3)),
  ...a.map(add(4)),
])
var map = _map.concat(
  _map.map(a => a.map(add(1))),
  _map.map(a => a.map(add(2))),
  _map.map(a => a.map(add(3))),
  _map.map(a => a.map(add(4))),
)
allDirections()['499,499']

Day 16 - part 1

var hex2bin = hex => (parseInt(hex, 16).toString(2)).padStart(4, '0')
const binary = arr[0].split('').map(hex2bin).reduce((r, s) => r+s)
var sum = 0
var parse = binary => {
  const version = parseInt(binary.substr(0, 3), 2)
  sum += version
  const type = parseInt(binary.substr(3, 3), 2)
  if (type === 4) {
    let valueBinary = ''
    let i=6
    for (;; i+=5) {
      valueBinary += binary.substr(i+1, 4)
      if (binary[i] === '0') { break }
    }
    return {
      version,
      type,
      value: parseInt(valueBinary, 2),
      length: i+5,
    }
  } else if (binary[6] === '0') {
    const len = parseInt(binary.substr(7, 15), 2)
    let remain = len
    while (remain !== 0) {
      const p = parse(binary.substr(22+len-remain, remain))
      console.log(p)
      remain -= p.length
    }
    return {
      version,
      type,
      I: '0',
      length: len+7+15,
    }
  } else if (binary[6] === '1') {
    const nums = parseInt(binary.substr(7, 11), 2)
    let index = 7+11
    for (let i=0; i<nums; i++) {
      const p = parse(binary.substring(index, binary.length))
      console.log(p)
      index += p.length
    }
    return {
      version,
      type,
      I: '1',
      length: index,
    }
  }
}
parse(binary)

Day 16 - part 2

var parse = binary => {
  const type = parseInt(binary.substr(3, 3), 2)
  if (type === 4) {
    let valueBinary = ''
    let i=6
    for (;; i+=5) {
      valueBinary += binary.substr(i+1, 4)
      if (binary[i] === '0') { break }
    }
    return {
      value: parseInt(valueBinary, 2),
      length: i+5,
    }
  } else if (binary[6] === '0') {
    const len = parseInt(binary.substr(7, 15), 2)
    let remain = len
    const packets = []
    while (remain !== 0) {
      const p = parse(binary.substr(22+len-remain, remain))
      packets.push(p)
      remain -= p.length
    }
    return {
      value: packets.map(p => p.value).reduce(
        type === 0 ? (r, n) => r+n
          : type === 1 ? (r, n) => r*n
            : type === 2 ? (r, n) => n < r ? n : r
              : type === 3 ? (r, n) => n > r ? n : r
                : type === 5 ? (r, n) => r > n ? 1 : 0
                  : type === 6 ? (r, n) => r < n ? 1 : 0
                    : (r, n) => r === n ? 1 : 0 // 7
      ),
      length: len+7+15,
    }
  } else if (binary[6] === '1') {
    const nums = parseInt(binary.substr(7, 11), 2)
    let index = 7+11
    const packets = []
    for (let i=0; i<nums; i++) {
      const p = parse(binary.substring(index, binary.length))
      packets.push(p)
      index += p.length
    }
    return {
      value: packets.map(p => p.value).reduce(
        type === 0 ? (r, n) => r+n
          : type === 1 ? (r, n) => r*n
            : type === 2 ? (r, n) => n < r ? n : r
              : type === 3 ? (r, n) => n > r ? n : r
                : type === 5 ? (r, n) => r > n ? 1 : 0
                  : type === 6 ? (r, n) => r < n ? 1 : 0
                    : (r, n) => r === n ? 1 : 0 // 7
      ),
      length: index,
    }
  }
}
parse(binary)

Day 17 - part 1

var step = (v, pos={x:0, y:0}, highest=0) => {
  const newPos = { x: pos.x + v.x, y: pos.y + v.y }
  const newV = {
    x: v.x > 0 ? v.x-1 : v.x < 0 ? v.x+1 : 0,
    y: v.y-1,
  }
  if (newPos.x >= 135 && newPos.x <= 155
    && newPos.y >= -102 && newPos.y <= -78) {
    return highest
  } else if (newPos.x > 155 || newPos.y < -102) {
    return false
  } else {
    highest = newPos.y > highest ? newPos.y : highest
    return step(newV, newPos, highest)
  }
}
var highest
for (let x=1; x<=155; x++) {
  for (let y=1; y<500; y++) {
    const candidate = step({x, y})
    if (candidate && candidate > highest) {
      highest = candidate
    }
  }
}

Day 17 - part 2

var step = (v, pos={x:0, y:0}) => {
  const newPos = { x: pos.x + v.x, y: pos.y + v.y }
  const newV = {
    x: v.x > 0 ? v.x-1 : v.x < 0 ? v.x+1 : 0,
    y: v.y-1,
  }
  if (newPos.x >= 135 && newPos.x <= 155
    && newPos.y >= -102 && newPos.y <= -78) {
    return v
  } else if (newPos.x > 155 || newPos.y < -102) {
    return false
  } else {
    return step(newV, newPos) ? v : false
  }
}
var count = 0
for (let x=1; x<=155; x++) {
  for (let y=1000; y>=-102; y--) {
    const candidate = step({x, y})
    if (candidate) {
      count+=1
    }
  }
}

Day 18 - part 1

var addLeftMost = (a, n) => Array.isArray(a) ? [
  !Array.isArray(a[0]) ? a[0]+n : addLeftMost(a[0], n),
  a[1]
] : a+n
var addRightMost = (a, n) => Array.isArray(a) ? [
  a[0],
  !Array.isArray(a[1]) ? a[1]+n : addRightMost(a[1], n)
]: a+n
var explode = (a, depth=1) => {
  if (!Array.isArray(a)) return { value: a }
  if (Array.isArray(a[0]) && depth === 4) {
    return {
      addToLeft: a[0][0],
      exploded: true,
      value: [0, addLeftMost(a[1], a[0][1])],
    }
  } else if (Array.isArray(a[1]) && depth === 4) {
    return {
      addToRight: a[1][1],
      exploded: true,
      value: [a[1][0] + a[0], 0],
    }
  } else {
    const left = explode(a[0], depth+1)
    if (left.addToLeft) {
      return {
        addToLeft: left.addToLeft,
        exploded: true,
        value: [left.value, a[1]],
      }
    } else if (left.addToRight) {
      return {
        exploded: true,
        value: [left.value, addLeftMost(a[1], left.addToRight)]
      }
    } else if (left.exploded) {
      return {
        exploded: true,
        value: [left.value, a[1]],
      }
    }
    const right = explode(a[1], depth+1)
    if (right.addToRight) {
      return {
        addToRight: right.addToRight,
        exploded: true,
        value: [left.value, right.value],
      }
    } else if (right.addToLeft) {
      return {
        exploded: true,
        value: [addRightMost(left.value, right.addToLeft), right.value]
      }
    }
    return {
      exploded: left.exploded || right.exploded,
      value: [left.value, right.value]
    }
  }
}
var splits = a => {
  if (!Array.isArray(a)) {
    return {
      value: a >= 10 ? [Math.floor(a/2), Math.ceil(a/2)] : a,
      splited: a >= 10
    }
  }
  let left = splits(a[0])
  if (left.splited) {
    return {
      value: [left.value, a[1]],
      splited: true,
    }
  }
  const right = splits(a[1])
  return {
    value: [a[0], right.value],
    splited: right.splited,
  }
}
var reduce = a => {
  let result = explode(a).value
  if (result.toString() !== a.toString()) {
    console.log('explode')
    console.log(a.toString(), result.toString())
    return reduce(result)
  }
  result = splits(a).value
  if (result.toString() !== a.toString()) {
    console.log('splits')
    console.log(a.toString(), result.toString())
    return reduce(result)
  }
  return a
}
var add = (a, b) => reduce([a, b])
var magnitude = a => {
  const [l, r] = a.map(i => Array.isArray(i) ? magnitude(i) : i)
  return l*3 + r*2
}
magnitude(arr.map(s => eval(s)).reduce((r, i) => add(r, i)))

Day 18 - part 2

var input = arr.map(s => eval(s))
for (let i=0; i<input.length-1; i++) {
  for (let j=2; j<input.length; j++) {
    const r1 = magnitude(add(input[i], input[j]))
    const r2 = magnitude(add(input[j], input[i]))
    max = Math.max(r1, r2, max)
  }
}

Day 19 - part 1

var parse = input => {
 const scanners = []
 let scannerIndex = -1
  input.forEach(s => {
    if (s.startsWith('---')) {
      scannerIndex++
      scanners.push([])
      return
    }
    scanners[scannerIndex].push(s.split(',').map(s => parseInt(s)))
  })
  return scanners
}
var evenNotExistedOrientations = beacons => {
  const byBeacon = beacons.map(b => [
    [b[0], b[1], b[2]],
    [b[0], b[2], b[1]],
    [b[1], b[0], b[2]],
    [b[1], b[2], b[0]],
    [b[2], b[0], b[1]],
    [b[2], b[1], b[0]],

    [-b[0], b[1], b[2]],
    [-b[0], b[2], b[1]],
    [-b[1], b[0], b[2]],
    [-b[1], b[2], b[0]],
    [-b[2], b[0], b[1]],
    [-b[2], b[1], b[0]],
    
    [b[0], -b[1], b[2]],
    [b[0], -b[2], b[1]],
    [b[1], -b[0], b[2]],
    [b[1], -b[2], b[0]],
    [b[2], -b[0], b[1]],
    [b[2], -b[1], b[0]],
    
    [-b[0], -b[1], b[2]],
    [-b[0], -b[2], b[1]],
    [-b[1], -b[0], b[2]],
    [-b[1], -b[2], b[0]],
    [-b[2], -b[0], b[1]],
    [-b[2], -b[1], b[0]],
    
    [b[0], b[1], -b[2]],
    [b[0], b[2], -b[1]],
    [b[1], b[0], -b[2]],
    [b[1], b[2], -b[0]],
    [b[2], b[0], -b[1]],
    [b[2], b[1], -b[0]],
    
    [-b[0], b[1], -b[2]],
    [-b[0], b[2], -b[1]],
    [-b[1], b[0], -b[2]],
    [-b[1], b[2], -b[0]],
    [-b[2], b[0], -b[1]],
    [-b[2], b[1], -b[0]],
    
    [b[0], -b[1], -b[2]],
    [b[0], -b[2], -b[1]],
    [b[1], -b[0], -b[2]],
    [b[1], -b[2], -b[0]],
    [b[2], -b[0], -b[1]],
    [b[2], -b[1], -b[0]],
    
    [-b[0], -b[1], -b[2]],
    [-b[0], -b[2], -b[1]],
    [-b[1], -b[0], -b[2]],
    [-b[1], -b[2], -b[0]],
    [-b[2], -b[0], -b[1]],
    [-b[2], -b[1], -b[0]],
  ])
  const byOrientation = []
  for (let i=0; i<byBeacon[0].length; i++) {
    const o = []
    for (let j=0; j<beacons.length; j++) {
      o.push(byBeacon[j][i])
    }
    byOrientation.push(o)
  }
  return byOrientation
}
var correlate = (s1, s2, threshold=12) => {
  const s2o = evenNotExistedOrientations(s2)
  for (let o=0; o<s2o.length; o++) {
    const diffMap = {}
    for (let i=0; i<s1.length; i++) {
      for (let j=0; j<s2o[o].length; j++) {
        const diff = s1[i].map((axis, index) => axis - s2o[o][j][index])
        const diffKey = diff.join(',')
        diffMap[diffKey] = diffMap[diffKey] ? diffMap[diffKey]+1 : 1
        if (diffMap[diffKey] >= threshold) {
          return {
            diff,
            orientation: s2o[o],
          }
        }
      }
    }
  }
}
var fn = (
  scanners=parse(arr),
  solved=[0],
  unsolved=scanners.map((_, i) => i).slice(1, scanners.length),
  scannerMap={ 0: [0,0,0] }
) => {
  const stillUnsolved = []
  const newSolved = []
  unsolved.forEach(u => {
    for (let i=0; i<solved.length; i++) {
      const s = solved[i]
      const result = correlate(scanners[s], scanners[u])
      if (result) {
        scannerMap[u] = result.diff.map((n, axis) => n+scannerMap[s][axis])
        newSolved.push(u)
        scanners[u] = result.orientation
        return
      }
    }
    stillUnsolved.push(u)
  })
  if (stillUnsolved.length > 0) {
    fn(scanners, newSolved, stillUnsolved, scannerMap)
  }
  return [scanners, scannerMap]
}
var [orientedScanners, scannerMap] = fn()
new Set(orientedScanners.map((s, i) => s.map(b => b.map((n, axis) => n+scannerMap[i][axis]))).flat().map(a => a.toString()))

Day 19 - part 2

var max = 0
for (let i=0; i<orientedScanners.length-1; i++) {
  for (let j=0; j<orientedScanners.length; j++) {
    const distance = scannerMap[i].map((n, axis) => Math.abs(n-scannerMap[j][axis])).reduce((r, n) => r+n)
    max = distance > max ? distance : max
  }
}

Day 20 - part 1

var enhancement = square => arr[0][parseInt(square, 2)] === '#' ? '1' : '0'
var input = arr.slice(1, arr.length).map(s => s.split('').map(s => s === '#' ? '1' : '0'))
var getSquare = (image, i, j) => (image[i-1]?.[j-1] ? image[i-1][j-1] : (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i-1]?.[j] ? image[i-1][j] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i-1]?.[j+1] ? image[i-1][j+1] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i]?.[j-1] ? image[i][j-1] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i]?.[j] ? image[i]?.[j] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i]?.[j+1] ? image[i][j+1] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i+1]?.[j-1] ? image[i+1][j-1] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i+1]?.[j] ? image[i+1][j] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
  + (image[i+1]?.[j+1] ? image[i+1][j+1] :  (image.length-input.length)/2%2 === 0 ? '0' : '1')
var enhance = (times=1, image=input) => {
  if (times === 0 ) return image
  const output = []
  const newFirstRow = []
  const newLastRow = []
  for (let j=-1; j<image[0].length+1; j++) {
    newFirstRow.push(enhancement(getSquare(image, -1, j)))
  }
  output.push(newFirstRow)
  image.forEach((row, i) => {
    const newRow = [enhancement(getSquare(image, i, -1))]
    row.forEach((pixel, j) => {
      newRow.push(enhancement(getSquare(image, i, j)))
    })
    newRow.push(enhancement(getSquare(image, i, row.length)))
    output.push(newRow)
  })
  for (let j=-1; j<image[0].length+1; j++) {
    newLastRow.push(enhancement(getSquare(image, image.length, j)))
  }
  output.push(newLastRow)
  return enhance(times-1, output)
}
enhance(2).flat(2).filter(n => n == 1).length

Day 20 - part 2

enhance(50).flat(2).filter(n => n == 1).length

Day 21 - part 1

var deterministicNext = 1; var rolls = 0
var deterministic = (count=3) => {
  let sum = 0
  for (let i=0; i<count; i++) {
    sum += deterministicNext++
    if (deterministicNext > 100) {
      deterministicNext = 1
    }
  }
  rolls+=count
  return sum
}
var players = [{p:4, s:0}, {p:8, s:0}]
do {
  players = players.map(p => {
    const moves = deterministic()
    let newPos = (p.p + moves)%10
    newPos = newPos === 0 ? 10 : newPos
    return {
      p: newPos,
      s: p.s + newPos
    }
  })
} while (players.filter(p => p.s >= 1000).length === 0)
rolls * players[0].s

Day 21 - part 2

var allPossibleDiceSum = (() => {
  const sides = [1, 2, 3]
  const sums = [3, 4, 5, 6, 7, 8, 9].reduce((r, n) => ({...r, [n]: 0}), {})
  for (let i=0; i<3; i++) {
    for (let j=0; j<3; j++) {
      for (let k=0; k<3; k++) {
        sums[sides[i]+sides[j]+sides[k]] += 1
      }
    }
  }
  return sums
})()
var onBoard = n => n%10 === 0 ? 10 : n%10
var split = (universes={ ['5,0;10,0']: 1 }) => {
  let nextUniverses = {}
  const finishedUniverses = {}
  for (const [universe, count] of Object.entries(universes)) {
    const [p1Pos, p1Score, p2Pos, p2Score] = universe.split(';').map(p => p.split(',').map(s => parseInt(s))).flat()
    for (let i=3; i<=9; i++) {
      const newP1Pos = onBoard(p1Pos+i)
      const newP1Score = p1Score+newP1Pos
      if (newP1Score >= 21) {
        const universeName = newP1Pos+','+newP1Score+';'+p2Pos+','+p2Score
        finishedUniverses[universeName] = (finishedUniverses[universeName] || 0) + allPossibleDiceSum[i] * count
        continue
      }
      for (let j=3; j<=9; j++) {
        const newP2Pos = onBoard(p2Pos+j)
        const newP2Score = p2Score+newP2Pos
        const universeName = newP1Pos+','+newP1Score+';'+newP2Pos+','+newP2Score
        const universesToUpdate = newP2Score >= 21 ? finishedUniverses : nextUniverses
        universesToUpdate[universeName] = (universesToUpdate[universeName] || 0 ) + allPossibleDiceSum[i] * allPossibleDiceSum[j] * count
      }
    }
  }
  if (Object.keys(nextUniverses).length !== 0) {
    nextUniverses = split(nextUniverses)
  }
  for (const [universe, count] of Object.entries(nextUniverses)) {
    finishedUniverses[universe] = (finishedUniverses[universe] || 0) + count
  }
  return finishedUniverses
}
var finishedUniverses = split()
Object.keys(finishedUniverses).filter(key => parseInt(key.split(';')[0].split(',')[1]) >= 21).reduce((r, key) => r+finishedUniverses[key], 0)

Day 22 - part 1

var input = arr.map(line => line.split(' ')).map(line => line.map((s, i) => i === 0 ? s : s.split(',').map(axis => {
  const [name, range] = axis.split('=')
  return { [name]: range.split('..').map(s => parseInt(s)) }
}).reduce((r, a) => ({...r, ...a}))))
var intersect = (a, b) => {
  const result = {
    x: [Math.max(a.x[0], b.x[0]), Math.min(a.x[1], b.x[1])],
    y: [Math.max(a.y[0], b.y[0]), Math.min(a.y[1], b.y[1])],
    z: [Math.max(a.z[0], b.z[0]), Math.min(a.z[1], b.z[1])],
  }
  return Object.values(result).some(axis => axis[0] > axis[1]) ? null : result
}
input.reduce((cuboids, next) => {
  if (cuboids.length === 0) return [next]
  const result = []
  cuboids.forEach(cuboid => {
    result.push(cuboid)
    const interCuboid = intersect(cuboid[1], next[1])
    if (interCuboid) {
      result.push([cuboid[0] === 'on' ? 'off' : 'on', interCuboid])
    }
  })
  if (next[0] === 'on') result.push(next)
  return result
}, [])
  .map(cuboid => (cuboid[0] === 'on' ? 1 : -1) * Object.values(cuboid[1]).map(axis => axis[1]-axis[0]+1)
  .reduce((r, n) => r*n))
  .reduce((r, n) => r+n)
Dropped solution: split cuboids

```javascript var add = (a, b) => { if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a contains whole b return [a] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b contains whole a return [b] } else if (a.x[0] <= b.x[0] && a.x[1] < b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a x 由 return [a, {x: [a.x[1], b.x[1]], y: b.y, z: b.z}] } else if (a.x[0] > b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a x 甲 return [a, {x: [b.x[0], a.x[0]], y: b.y, z: b.z}] } else if (a.x[0] >= b.x[0] && a.x[1] > b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b x 由 return [b, {x: [b.x[1], a.x[1]], y: a.y, z: a.z}] } else if (a.x[0] < b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b x 甲 return [b, {x: [a.x[0], b.x[0]], y: a.y, z: a.z}] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] < b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a y 由 return [a, {x: b.x, y: [a.y[1], b.y[1]], z: b.z}] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] > b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a y 甲 return [a, {x: b.x, y: [a.y[0], b.y[0]], z: b.z}] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] > b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b y 由 return [b, {x: a.x, y: [b.y[1], a.y[1]], z: a.z}] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] < b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b y 甲 return [b, {x: a.x, y: [a.y[0], b.y[0]], z: a.z}] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] < b.z[1] ) { // a z 由 return [a, {x: b.x, y: b.y, z: [a.z[1], b.z[1]]}] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] > b.z[0] && a.z[1] >= b.z[1] ) { // a z 甲 return [a, {x: b.x, y: b.y, z: [b.z[0], a.z[0]]}] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] > b.z[1] ) { // b z 由 return [b, {x: a.x, y: a.y, z: [b.z[1], a.z[1]]}] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] < b.z[0] && a.z[1] <= b.z[1] ) { // b z 甲 return [b, {x: a.x, y: a.y, z: [a.z[0], b.z[0]]}] } else if (a.x[0] > b.x[0] && a.x[1] < b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a x 中 return [ a, {x: [a.x[1], b.x[1]], y: b.y, z: b.z}, {x: [b.x[0], a.x[0]], y: b.y, z: b.z}, ] } else if (a.x[0] < b.x[0] && a.x[1] > b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b x 中 return [ b, {x: [b.z[1], a.z[1]], y: a.y, z: a.z}, {x: [a.z[0], b.z[0]], y: a.y, z: a.z}, ] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] > b.y[0] && a.y[1] < b.y[1] && a.z[0] <= b.z[0] && a.z[1] >= b.z[1] ) { // a y 中 return [ a, {x: b.x, y: [a.y[1], b.y[1]], z: b.z}, {x: b.x, y: [b.y[0], a.y[0]], z: b.z}, ] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] < b.y[0] && a.y[1] > b.y[1] && a.z[0] >= b.z[0] && a.z[1] <= b.z[1] ) { // b y 中 return [ b, {x: a.x, y: [b.y[1], a.y[1]], z: a.z}, {x: a.x, y: [a.y[0], b.y[0]], z: a.z}, ] } else if (a.x[0] <= b.x[0] && a.x[1] >= b.x[1] && a.y[0] <= b.y[0] && a.y[1] >= b.y[1] && a.z[0] > b.z[0] && a.z[1] < b.z[1] ) { // a z 中 return [ a, {x: b.x, y: b.y, z: [a.z[1], b.z[1]]}, {x: b.x, y: b.y, z: [b.z[0], a.z[0]]}, ] } else if (a.x[0] >= b.x[0] && a.x[1] <= b.x[1] && a.y[0] >= b.y[0] && a.y[1] <= b.y[1] && a.z[0] < b.z[0] && a.z[1] > b.z[1] ) { // b z 中 return [ b, {x: a.x, y: a.y, z: [b.z[1], a.z[1]]}, {x: a.x, y: a.y, z: [a.z[0], b.z[0]]}, ] } else if (a.x[0] >= b.x[1] || a.x[1] <= b.x[0] || a.y[0] >= b.y[1] || a.y[1] <= b.y[0] || a.z[0] >= b.z[1] || a.z[1] <= b.z[0] ) { // no overlap return [a, b] } else { console.log('else') } } ```

Day 22 - part 2

Same as part 1.

Day 23 - part 1

Walk the amphipods by brain.

Day 23 - part 2

Walk the amphipods by brain, again.

Day 24 - part 1

var n = [12,13,12,-13,11,15,-14,12,-8,14,-9,-11,-6,-5]
var m = [ 1, 9,11,  6, 6,13, 13, 5, 7, 2,10, 14, 7, 1]
var fn = (i, w, lastZ=0) => {
  let x = (lastZ % 26 + n[i]) !== w
  let z = n[i] < 0 ? Math.floor(lastZ/26) : lastZ
  return x ? (26*z+w+m[i]) : z
}
var cache = {}
var monad = s => {
  if (s.length === 1) {
    const result = fn(0, parseInt(s))
    cache[s] = result
    return result
  }

  const s_1 = s.substr(0, s.length-1)
  const result = fn(s.length-1, parseInt(s[s.length-1]), cache[s_1] == null ? monad(s_1) : cache[s_1])
  cache[s] = result
  return result
}

// doesn't work
for (let i=99999999999999; i>=11111111111111; i--) {
  const s = i+''
  if (s.indexOf('0') !== -1) continue
  if (monad(s) === 0) {
    console.log(i)
    break
  }
}

// to prove monad
var alu = {
  x:0, y:0, z:0, w:0, i:0,
  inp: () => {alu.w=parseInt(model[alu.i++])},
  add: (a, b) => {alu[a] += alu[b] != null ? alu[b] : parseInt(b)},
  mul: (a, b) => {alu[a] *= alu[b] != null ? alu[b] : parseInt(b)},
  div: (a, b) => {alu[a] = Math.floor(alu[a]/(alu[b] != null ? alu[b] : parseInt(b)))},
  mod: (a, b) => {alu[a] %= alu[b] != null ? alu[b] : parseInt(b)},
  eql: (a, b) => {alu[a] = alu[a] == (alu[b] != null ? alu[b] : parseInt(b)) ? 1 : 0},
}
arr.map(s => s.split(' ')).forEach(ins => {
  alu[ins[0]](ins[1], ins[2])
})

Day 24 - part 2

Day 25 - part 1

var map = arr.map(s => s.split(''))
var fn = (map=map, count=1) => {
  const newMap = []
  let moved = false
  for (let i=0; i<map.length; i++) {
    const newRow = []
    for (let j=0; j<map[0].length; j++) {
      if (map[i][j] === '>' && j+1 < map[0].length && map[i][j+1] === '.') {
        newRow.push('.', '>')
        j++
        moved = true
      } else if (map[i][j] === '>' && j+1 === map[0].length && map[i][0] === '.') {
        newRow.push('.')
        newRow[0] = '>'
      } else {
        newRow.push(map[i][j])
      }
    }
    newMap.push(newRow)
  }
  const finalMap = newMap.map(row => row.slice())
  for (let i=0; i<finalMap.length; i++) {
    const newRow = []
    for (let j=0; j<finalMap[0].length; j++) {
      if (finalMap[i][j] === 'v' && i+1 < finalMap.length && finalMap[i+1][j] === '.') {
        finalMap[i][j] = '.'
        finalMap[i+1][j] = '^'
        moved = true
      } else if (finalMap[i][j] === '^') {
        finalMap[i][j] = 'v'
      } else if (finalMap[i][j] === 'v' && i+1 === finalMap.length && newMap[0][j] === '.') {
        finalMap[i][j] = '.'
        finalMap[0][j] = 'v'
        moved = true
      }
    }
  }
  return moved ? fn(finalMap, count+1) : count
}
fn(map)

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