DEV Community

Discussion on: AoC Day 10: The Stars Align

Collapse
 
themindfuldev profile image
Tiago Romero Garcia

Javascript solution

I had a really hard time with Stack Overflows (I even tried my company's computer to see if it would be better). I even looked at pixel plotting libraries for Node.js.

It took me 1 hour to realize that I would not need to print the whole matrix - but I could just keep processing it until I got it to the smallest height, and then I print it.

However I would only know I got to the smallest height after I'm no longer on the smallest height and then I need to tick the clock just once backwards to get back to the smallest height and print it.

reader.js

const fs = require('fs');
const readline = require('readline');

const readLines = (file, onLine) => {
    const reader = readline.createInterface({
        input: fs.createReadStream(file),
        crlfDelay: Infinity
    });

    reader.on('line', onLine);

    return new Promise(resolve => reader.on('close', resolve));
};

const readFile = async file => {
    const lines = [];
    await readLines(file, line => lines.push(line));  
    return lines;
}

module.exports = {
    readLines,
    readFile
};

10.js

const { readFile } = require('./reader');
const fs = require('fs');

const regex = /^position=<\s?(?<posX>-?\d+), \s?(?<posY>-?\d+)> velocity=<\s?(?<velX>-?\d+), \s?(?<velY>-?\d+)>$/;

const parseInput = lines => {
    return lines.map(line => {
        const { posX, posY, velX, velY } = line.match(regex).groups;
        return {
            posX: +posX,
            posY: +posY,
            velX: +velX,
            velY: +velY
        };
    });
};

const printPointsUntilMinimum = points => {
    const viewSize = 100;

    let minimumY = getEdges(points).lengthY;
    let hasReachedMinimum = false;
    let secondsForMessage = 0;

    while (!hasReachedMinimum) {
        tick(points);   
        secondsForMessage++;     

        const { lengthY } = getEdges(points);
        if (lengthY < minimumY) {
            minimumY = lengthY;            
        }
        else {
            tick(points, false);
            console.log(`${lengthY} lines`);
            printPoints(points);

            hasReachedMinimum = true;            
        }
    }

    console.log(`The elves had to wait ${secondsForMessage-1} seconds`);
}

const tick = (points, forward = true) => {
    const sign = forward ? 1 : -1;
    for (let point of points) {
        point.posX += point.velX * sign;
        point.posY += point.velY * sign;
    }
};

const getEdges = points => {
    const posX = points.map(p => p.posX);
    const posY = points.map(p => p.posY);

    const minX = Math.min(...posX);
    const maxX = Math.max(...posX);
    const minY = Math.min(...posY);
    const maxY = Math.max(...posY);

    return {
        minX,
        minY,
        lengthX: maxX - minX + 1,
        lengthY: maxY - minY + 1
    };
};

const printPoints = points => {
    const { minX, minY, lengthX, lengthY } = getEdges(points);

    const grid = Array.from({length: lengthY}, row => Array.from({length: lengthX}, col => '.'));

    for (let point of points) {
        const x = point.posX - minX;
        const y = point.posY - minY;
        grid[y][x] = '#';
    }

    for (let row of grid) {
        console.log(row.join(''));
    }
};

(async () => {
    const lines = await readFile('10-input.txt');

    const points = parseInput(lines);

    printPointsUntilMinimum(points);    
})();