Skip to content

Instantly share code, notes, and snippets.

@kevincharm
Last active December 22, 2017 16:10
Show Gist options
  • Save kevincharm/89fffbf73553bc163461a6ce6b8f135a to your computer and use it in GitHub Desktop.
Save kevincharm/89fffbf73553bc163461a6ce6b8f135a to your computer and use it in GitHub Desktop.
nice quads
// -*- node.jz -*-
/**
* Day 22, Part 1 & 2
*
* Usage:
* input >> stdin >> node day22.js $PART $ITERATIONS
* e.g.
* `cat input.txt | node day22.js 2 10000000`
*/
let input = ''
process.stdin.on('readable', () => input += process.stdin.read() || '')
process.stdin.on('end', () => main())
// Enums
const NS_CLEAN = 0x0
const NS_WEAKENED = 0x1
const NS_INFECTED = 0x2
const NS_FLAGGED = 0x3
// Utils
const hash = (x, y) => `${x},${y}`
const unhash = (str) => str.split(',').map(n => parseInt(n))
const left = dir => dir + 90
const right = dir => dir - 90
const backout = dir => dir + 180
function main() {
const partOne = ~~process.argv[2] === 1
const cluster = inputToCluster(input)
let node = cluster['0,0']
const pos = { x: 0, y: 0 }
let dir = 90
let infections = 0
let iter = ~~process.argv[3] || 10e6
while (iter--) {
switch (node.status) {
case NS_CLEAN:
if (partOne) {
node.status = NS_INFECTED
infections++
} else {
node.status = NS_WEAKENED
}
dir = left(dir)
break
case NS_WEAKENED:
node.status = NS_INFECTED
infections++
break
case NS_INFECTED:
if (partOne) {
node.status = NS_CLEAN
} else {
node.status = NS_FLAGGED
}
dir = right(dir)
break
case NS_FLAGGED:
node.status = NS_CLEAN
dir = backout(dir)
break
}
pos.x += Math.round(Math.cos(dtr(dir)))
pos.y -= Math.round(Math.sin(dtr(dir)))
const key = hash(pos.x, pos.y)
let next = node[english(dir)]
if (!next) {
// unresolved, check if we've seen it:
next = cluster[key]
}
if (!next) {
// haven't seen it before, so record it
next = new Node()
// link back to this node
next[english(backout(dir))] = node
// bob is, indeed, your uncle
cluster[key] = next
}
node = next
}
console.log(`Infections: ${infections}`)
}
/**
* Quadtree node
*/
class Node {
constructor(
status = NS_CLEAN,
up = null,
down = null,
left = null,
right = null
) {
this.up = up
this.down = down
this.left = left
this.right = right
this.status = status
}
}
/**
* Input string -> quadtree
*/
function inputToCluster(str) {
const rows = str
.split('\n')
.map(row =>
row.split('').map(col => {
switch (col) {
case '#': return true
default: return false
}
})
)
const cluster = {}
const n = rows.length
const off = -Math.floor(n/2) // halfway
rows.forEach((row, _y) => {
row.forEach((col, _x) => {
const x = _x+off
const y = _y+off
const node = new Node(col ? NS_INFECTED : NS_CLEAN)
cluster[hash(x, y)] = node
})
})
for (const key in cluster) {
resolve(key, cluster)
}
return cluster
}
function resolve(key, cluster) {
const [x, y] = unhash(key)
const node = cluster[key]
if (!node.up) node.up = cluster[hash(x, y-1)]
if (!node.down) node.down = cluster[hash(x, y+1)]
if (!node.left) node.left = cluster[hash(x-1, y)]
if (!node.right) node.right = cluster[hash(x+1, y)]
}
function english(dir) {
switch (dir % 360) {
case 90: return 'up'
case 180: return 'left'
case 270: return 'down'
case 0: return 'right'
}
}
function dtr(deg) {
return deg*Math.PI/180
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment