Skip to content

Instantly share code, notes, and snippets.

@kevincharm
Last active December 21, 2017 16:01
Show Gist options
  • Save kevincharm/b822a7f649b61c865b66a536af3d3739 to your computer and use it in GitHub Desktop.
Save kevincharm/b822a7f649b61c865b66a536af3d3739 to your computer and use it in GitHub Desktop.
// -*- node.jz -*-
const { compose, encode, decode,
rotr, rotl, flipX, flipY, print } = require('./util')
let input = ''
process.stdin.on('readable', () => input += process.stdin.read() || '')
process.stdin.on('end', () => main())
function main() {
let matrix = decode('.#./..#/###')
const rules = input
.split('\n')
.map(rule => rule.split('=>').map(parts => parts.trim()))
// print(matrix)
let iter = process.argv[2]
while (iter--) {
const n = matrix.length
if (!(n % 2)) {
matrix = div2(matrix, rules)
} else if (!(n % 3)) {
matrix = div3(matrix, rules)
}
// print(matrix)
}
const count = matrix
.map(row => {
return row
.map(col => {
switch (col) {
case '#': return 1
case '.': return 0
}
})
.reduce((p, c) => p + c, 0)
})
.reduce((p, c) => p + c, 0)
console.log(`On: ${count}`)
}
function div2(matrix, rules) {
const n = matrix.length
const submatrices = []
for (let y=0; y<n; y+=2) {
const rows = matrix.slice(y, y+2)
for (let x=0; x<n; x+=2) {
const submatrix = rows
.map(row => row.slice(x, x+2))
const enhanced = lookup(submatrix, rules)
submatrices.push(enhanced)
}
}
return combine(submatrices)
}
function div3(matrix, rules) {
const n = matrix.length
const submatrices = []
for (let y=0; y<n; y+=3) {
const rows = matrix.slice(y, y+3)
for (let x=0; x<n; x+=3) {
const submatrix = rows
.map(row => row.slice(x, x+3))
const enhanced = lookup(submatrix, rules)
submatrices.push(enhanced)
}
}
return combine(submatrices)
}
function combine(matrices = []) {
const n = Math.sqrt(matrices.length)
const result = []
for (let i=0; i<matrices.length; i+=n) {
const subset = matrices.slice(i, i+n)
for (let y=0; y<matrices[0].length; y++) {
const row = []
for (let x=0; x<n; x++) {
row.push(...subset[x][y])
}
result.push(row)
}
}
return result
}
function lookup(matrix, rules) {
let m = matrix.slice()
for (let i=0; i<4; i++) {
const mm = find(m, rules)
if (mm) return mm
const mx = find(flipX(m), rules)
if (mx) return mx
const my = find(flipY(m), rules)
if (my) return my
m = rotr(m)
}
return null
}
function find(matrix, rules) {
const m = encode(matrix)
const r = rules
.find(([rule, out]) => m === rule)
if (r) {
const [_, out] = r
return decode(out)
}
return null
}
const compose = (...fns) =>
fns.reverse().reduce((f, g) =>
x => g(f(x)),
x => x)
function encode(matrix) {
if (!matrix) {
console.warn('Encode failed!')
return null
}
return matrix
.map(row => row.join(''))
.join('/')
}
function decode(image) {
if (!image) {
console.warn('Decode failed!')
return null
}
return image
.split('/')
.map(row => row.split(''))
}
function rotr(matrix) {
const n = matrix.length
const rotated = []
for (let i=0; i<n; i++) rotated.push([])
for (let x=0; x<n; x++) {
for (let y=0; y<n; y++) {
rotated[x][y] = matrix[n-y-1][x]
}
}
return rotated
}
function flipX(matrix) {
const n = matrix.length
const flipped = []
for (let y=0; y<n; y++) {
flipped.push(matrix[n-y-1])
}
return flipped
}
function rotl(matrix) {
return compose(rotr, rotr, rotr)(matrix)
}
function flipY(matrix) {
return compose(rotr, flipX, rotl)(matrix)
}
function print(matrix) {
const m = matrix.slice()
if (!m) {
console.warn('Empty matrix!')
return
}
console.log('')
if (typeof m === 'string') {
m = decode(m)
}
m.forEach(row => {
console.log(row.join(''))
})
console.log('')
}
module.exports = {
compose,
encode,
decode,
rotr,
rotl,
flipX,
flipY,
print
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment