DEV Community

Discussion on: AoC Day 16: Chronal Classification

Collapse
themindfuldev profile image
Tiago Romero Garcia

JavaScript solution

I'm gonna omit reader.js which is the same as the other solutions and jump to the point:

16-common.js

const beforeRegex = /^Before: \[(?<b0>\d), (?<b1>\d), (?<b2>\d), (?<b3>\d)\]$/;
const instructionRegex = /^(?<op>\d+) (?<a>\d) (?<b>\d) (?<c>\d)$/;
const afterRegex = /^After:  \[(?<a0>\d), (?<a1>\d), (?<a2>\d), (?<a3>\d)\]$/;

const readInput = lines => {
    const samples = [];
    const program = [];
    const n = lines.length;
    for (let i = 0; i < n; i++) {
        const line = lines[i];
        const sampleMatch = line.match(beforeRegex);
        if (sampleMatch) {
            const { b0, b1, b2, b3 } = sampleMatch.groups;
            const { op, a, b, c } = lines[i+1].match(instructionRegex).groups;
            const { a0, a1, a2, a3 } = lines[i+2].match(afterRegex).groups;
            samples.push({
                before: [+b0, +b1, +b2, +b3],
                instructions: [+op, +a, +b, +c],
                after: [+a0, +a1, +a2, +a3]
            });
            i += 2;
        }
        else {
            const programMatch = line.match(instructionRegex);
            if (programMatch) {
                const { op, a, b, c } = programMatch.groups;
                program.push([+op, +a, +b, +c]);
            }
        }

    }
    return { samples, program };
};

const operations = {
    'addr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] + registers[b]; 
        return result; 
    },
    'addi': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] + b; 
        return result; 
    },
    'mulr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] * registers[b]; 
        return result; 
    },
    'muli': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] * b; 
        return result; 
    },
    'banr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] & registers[b]; 
        return result; 
    },
    'bani': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] & b; 
        return result; 
    },
    'borr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] | registers[b]; 
        return result; 
    },
    'bori': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] | b; 
        return result; 
    },
    'setr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a]; 
        return result; 
    },
    'seti': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = a; 
        return result; 
    },
    'gtir': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = a > registers[b] ? 1 : 0; 
        return result; 
    },
    'gtri': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] > b ? 1 : 0; 
        return result; 
    },
    'gtrr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] > registers[b] ? 1 : 0; 
        return result; 
    },
    'eqir': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = a === registers[b] ? 1 : 0; 
        return result; 
    },
    'eqri': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] === b ? 1 : 0; 
        return result; 
    },
    'eqrr': ([op, a, b, c]) => registers => { 
        const result = [...registers];
        result[c] = registers[a] === registers[b] ? 1 : 0;
        return result;
     }
};

module.exports = {
    readInput,
    operations
};

16a.js

const { readFile } = require('./reader');
const {
    readInput,
    operations
} = require('./16-common');

const evaluateSamples = samples => {
    let numberOfSamples = 0;

    for (let sample of samples) {
        const { before, instructions, after } = sample;

        const opcodes = Object.values(operations)
            .map(op => op(instructions)(before))
            .filter(result => result.toString() === after.toString()).length;

        if (opcodes >= 3) numberOfSamples += 1;
    }
    return numberOfSamples;
};

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

    const { samples } = readInput(lines);
    const numberOfSamples = evaluateSamples(samples);

    console.log(`The number of samples with three or more opcodes is ${numberOfSamples}`);    
})();

16b.js

const { readFile } = require('./reader');
const {
    readInput,
    operations
} = require('./16-common');

const determineOpcodes = samples => {   
    const opcodes = [];

    const remainingOperations = new Map(Object.entries(operations));

    let i = 0;
    while (remainingOperations.size > 0) {
        const { before, instructions, after } = samples[i];

        const candidates = [...remainingOperations]
            .map(([name, op]) => ({
                name,
                op,
                result: op(instructions)(before)
            }))
            .filter(({ result }) => result.toString() === after.toString());

        if (candidates.length === 1) {
            const { name, op } = candidates[0];

            const opcode = instructions[0];
            opcodes[opcode] = op;
            remainingOperations.delete(name);

            samples = samples.filter(({ instructions }) => instructions[0] !== opcode);
            i = 0;
        }

        i = (i + 1) % samples.length;
    }
    return opcodes;
};

const runProgram = (opcodes, program) => {
    let result = [0, 0, 0, 0];
    for (const instruction of program) {
        const op = opcodes[instruction[0]];
        result = op(instruction)(result);
    }
    return result;
};

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

    const { samples, program } = readInput(lines);
    const opcodes = determineOpcodes(samples);
    const result = runProgram(opcodes, program);

    console.log(`The state of the registers after executing the test program is ${result}`);
})();