class Bot { constructor(id) { this.id = id; this.chips = []; } receive(chip) { if (this.chips.length === 2) throw new Error('There are two chips already!'); this.chips.push(chip); this.chips.sort(); } outputLow(output, index) { output[index] = this.chips[0]; } outputHigh(output, index) { output[index] = this.chips[1]; } giveBotLow(bot) { bot.receive(this.chips[0]); } giveBotHigh(bot) { bot.receive(this.chips[1]); } } const valueRegexp = /value (\d+) goes to bot (\d+)/; const giveRegexp = /bot (\d+) gives low to (bot|output) (\d+) and high to (bot|output) (\d+)/; class Factory { constructor() { this.bots = []; this.output = []; } getBot(id) { if (!this.bots[id]) { this.bots[id] = new Bot(id); } return this.bots[id]; } exec(input) { let unresolved = input.split('\n'); while (unresolved.length > 0) { unresolved = unresolved.filter(inst => { let valueInst, giveInst; if (valueInst = valueRegexp.exec(inst)) { let bot = this.getBot(parseInt(valueInst[2], 10)); bot.receive(parseInt(valueInst[1], 10)); return false; // resolved } else if (giveInst = giveRegexp.exec(inst)) { let fromBot = this.getBot(parseInt(giveInst[1], 10)); if (fromBot.chips.length === 2) { let lowTarget = giveInst[2]; let lowId = parseInt(giveInst[3], 10); if (lowTarget === 'bot') { fromBot.giveBotLow(this.getBot(lowId)); } else if (lowTarget === 'output') { fromBot.outputLow(this.output, lowId); } let highTarget = giveInst[4]; let highId = parseInt(giveInst[5], 10); if (highTarget === 'bot') { fromBot.giveBotHigh(this.getBot(highId)); } else if (highTarget === 'output') { fromBot.outputHigh(this.output, highId); } return false; // resolved } else { return true; } } else { throw new Error('Unknown instruction: ' + inst); } }); } return this; } findBot(low, high) { return this.bots.find(bot => bot.chips[0] === low && bot.chips[1] === high); } listBots() { this.bots.forEach(bot => console.log(bot)); } } let f = new Factory(); const input = require('fs').readFileSync('d10.txt', 'utf8'); // f.exec(input).listBots(); console.log(`bot: ${f.exec(input).findBot(17, 61).id}`);