Yes - I'm falling behind, but let's just pretend today is still the 8th. Day 8 was a difficult one (I feel like I'm saying that more and more) as it required working with 2D arrays, something I always have trouble with. Specifically - you needed to represent a 2D array of cells on a screen. You then had to take input in the form of:

  • rect AxB - which would turn on lights in a rectangle A wide and B high in the upper left corner of the screen.
  • rotate row y=A by B - which "rotates" lights in row A B steps lower. You have to handle wrapping too as a light that 'falls off' the bottom then returns to the top.
  • rotate column x=A by B - same concept, but in a column.

The answer to this puzzle would simply be the number of lit lights.

The rect part was trivial, but the rotation took me forever. I figured out that given an set of values like so:

ABCDE

and wanting to rotate by, let's say 2, you could create a new set by starting on the third letter and selecting from the original set until you get to the end, and then wrap around, so:

CDEAB

As I've said many times before, using their sample input/output was a huge help. In this case, it helped so much that when I switched from the sample input to the real input, my code returned the right answer immediately!

(I have to admit though, this one was so difficult I contemplated cheating. When you enter a numeric answer in Advent of Code, it usually tells if it is too high or too low. So in theory, I could have gotten the max number of lights and then began guessing by supplying a number half-way through the range and just narrowing it down.)

Here is my solution:


//screen size
let width = 50;
let height = 6;
let screen = seedScreen(width,height);

renderScreen(screen, width, height);
/*
let input = 'rect 3x2';
screen = parseInput(screen, input);
renderScreen(screen, width, height);

console.log('NOW DO COL');
screen = parseInput(screen, 'rotate column x=1 by 1');
renderScreen(screen, width, height);

console.log('NOW DO RECT');

screen = parseInput(screen, 'rotate row y=0 by 4');
renderScreen(screen, width, height);

console.log('NOW DO COL');
screen = parseInput(screen, 'rotate column x=1 by 1');
renderScreen(screen, width, height);
*/

const fs = require('fs');
const input = fs.readFileSync('./input.txt','utf8');

let good = 0;
let lines = input.split('\n');
lines.forEach(function(line) {
	screen = parseInput(screen, line);
	renderScreen(screen, width, height);
});

let total = getTotal(screen);
console.log(total);

function getTotal(s) {
	let total = 0;
	for(let x=0;x<s.length;x++) {
		for(let y=0;y<s[x].length;y++) {
			if(s[x][y] === "#") total++;
		}
	}
	return total;
}

function parseInput(screen, i) {
	if(i.indexOf('rect') === 0) {
		let dim = i.split(' ')[1];
		let width = dim.split('x')[0];
		let height = dim.split('x')[1];
		return drawRect(screen, width, height);
	}

	//	rotate row y=A by B
	if(i.indexOf('rotate row') === 0) {
		let dim = i.split(' row y=')[1];
		let row = Number(dim.split(' by ')[0]);
		let offset = Number(dim.split(' by ')[1]);
		return rotateRow(screen, width, height, row, offset);
	}

	//	otate column x=1 by 1
	if(i.indexOf('rotate column') === 0) {
		let dim = i.split(' column x=')[1];
		let col = Number(dim.split(' by ')[0]);
		let offset = Number(dim.split(' by ')[1]);
		return rotateColumn(screen, width, height, col, offset);
	}

	throw('Unknown command: '+i);
}

function rotateColumn(s, w, h, c, o) {
	//##.  => .## (1)
	//##. => #.# (2)
	let originalCol = s[c];
//	console.log('offset is '+o);
//	console.log('origCol='+originalCol.join(''));
	let newCol = [];
	for(let x=0;x<originalCol.length;x++) {
		let thisVal = originalCol[x];
		let newPos = x + o;
//		console.log('thisVal='+thisVal+' newPos='+newPos);
		if(newPos >= originalCol.length) newPos =  newPos - originalCol.length;
//		console.log(' newPos='+newPos);
		newCol[newPos] = thisVal;
	}
//	console.log('newCol='+newCol);
	s[c] = newCol;
	return s;
}

function rotateRow(s, w, h, r, o) {
	/*
	so given ##00# and offset of 2, 
	we make a new list starting at 2. 
	#00##
	*/
	let originalRow = [];
    for(let x=0;x<w;x++) {
        for(let i=0;i<h;i++) {
			if(i === r) {
				originalRow.push(s[x][i]);
			}
        }
    }
//	console.log('or: '+originalRow.join('')+'-');
	let newRow = [];
	let done = 0;
	//because:
	o++;
	for(let x = o; x < o+originalRow.length; x++) {
		let pos = x;
//		console.log('trying to set '+pos);
		if(pos > w) pos = pos-w;
//		console.log('really '+pos);
//		newRow.push(originalRow[x]);
//console.log('val to set is '+originalRow[done]);
		newRow[pos-1] = originalRow[done];
		done++;
//		console.log('new Row len is now '+newRow.length);
	}
//	console.log('newRow: '+newRow.join(''));
    for(let x=0;x<w;x++) {
        for(let i=0;i<h;i++) {
			if(i === r) {
				s[x][i] = newRow[x];
			}
        }
    }

	return s;
	
}

function drawRect(s,w,h) {
	console.log('going to draw '+w+','+h);
	for(let i=0;i<w;i++) {
		for(let x=0;x<h;x++) {
			s[i][x] = "#";
		} 
	}
	return s;
}

function seedScreen(w,h) {
    let screen = [];
    for(let i=0;i<w;i++) {
        for(let x=0;x<h;x++) {
            //console.log('setting s['+i+']['+x+']');
            if(!screen[i]) screen[i] = [];
            screen[i][x] = ".";
        }
    }
    return screen;
}

function renderScreen(s,width,height) {
    var result = '';
    for(let x=0;x<height;x++) {
        for(let i=0;i<width;i++) {
            result += s[i][x];
        }
        result += '\n';
    }
    console.log(result);
}

Notice the renderScreen function. I built this to help me debug and it was a fortuitous decision. I noticed when I rendered the 'real' input, the output was a set of letters. Part two to the puzzle was to simply input those letters. Here is what my output looked like:

Text output

You can find my repo of solutions here: https://github.com/cfjedimaster/adventofcode