advent-of-code

Entries to advent of code, multiple years
git clone git://git.finwo.net/misc/advent-of-code
Log | Files | Refs

index.js (3155B)


      1 const fs            = require('fs');
      2 const through       = require('through2');
      3 const line_for_line = require('../common/line-for-line');
      4 
      5 String.prototype.startsWith = function(subject) {
      6   return this.substr(0, subject.length) === subject;
      7 };
      8 
      9 const monkeys = [];
     10 
     11 fs.createReadStream('input')
     12   .pipe(line_for_line())
     13 
     14   // Turn into paragraphs
     15   .pipe(through(function(line, enc, cb) {
     16     line = line.toString();
     17     this.buffer = this.buffer || [];
     18 
     19     // Emit paragraph on empty line
     20     if (!line.length) {
     21       this.push(this.buffer.join('\n'));
     22       this.buffer = [];
     23       return cb();
     24     }
     25 
     26     // Add line to buffer
     27     this.buffer.push(line);
     28     cb();
     29   }))
     30 
     31   // Prase paragraph
     32   .pipe(through(function(paragraph, enc, cb) {
     33     paragraph = paragraph.toString();
     34 
     35     const lines = paragraph
     36       .split('\n')
     37       .map(str => str.replace(/^\s+|\s+$/g, ''))
     38       .map(str => str.split(':').map(s => s.replace(/^\s+|\s+$/g, '')))
     39       ;
     40 
     41     const monkey = {inspects: 0};
     42 
     43     lines.forEach(line => {
     44       const [name, value] = line;
     45       if (name.startsWith("Monkey")) {
     46         monkey.id = parseInt(name.split(' ').pop());
     47       } else if (name == 'Starting items') {
     48         monkey.items = value.split(', ').map(v => BigInt(v));
     49       } else if (name == 'Test') {
     50         monkey.test = BigInt(value.split(' ').pop());
     51       } else if (name == 'If true') {
     52         monkey.resolve = parseInt(value.split(' ').pop());
     53       } else if (name == 'If false') {
     54         monkey.reject = parseInt(value.split(' ').pop());
     55       } else if (name == 'Operation') {
     56         monkey.operation = Function('old', `return ${value.substr(6).replace(/(\d+)/, '$1n')};`);
     57       }
     58     });
     59 
     60     monkeys.push(monkey);
     61     cb();
     62   }))
     63 
     64   .on('finish', () => {
     65     monkeys.sort((a, b) => a.id - b.id);
     66     console.log({ monkeys });
     67 
     68     const pod = monkeys
     69       .map(m => m.test)
     70       .reduce((r,a) => r*a, 1n);
     71 
     72     for(let i=0; i<10000; i++) {
     73 
     74       for(let j=0; j<monkeys.length; j++) {
     75       // for(const monkey of monkeys) {
     76         // process.stdout.write(`Monkey ${monkey.id}:\n`);
     77         monkeys[j].inspects += monkeys[j].items.length;
     78 
     79         const test = (wl) =>
     80           wl % monkeys[j].test == 0n ? monkeys[j].resolve : monkeys[j].reject;
     81 
     82         while(monkeys[j].items.length) {
     83           const item = monkeys[j].items.shift();
     84           let _new = monkeys[j].operation(item) % pod;
     85           monkeys[test(_new)].items.push(_new);
     86         }
     87         process.stdout.write(`Monkey ${monkeys[j].id} inspected items ${monkeys[j].inspects} times.\n`);
     88       }
     89       process.stdout.write(`Round ${i} finished\n\n`);
     90     }
     91 
     92     // // Find the most active monkeys
     93     // for(const monkey of monkeys) {
     94     //   process.stdout.write(`Monkey ${monkey.id} inspected items ${monkey.inspects} times.\n`);
     95     // }
     96 
     97     monkeys.sort((a, b) => {
     98       const x = b.inspects - a.inspects;
     99       if (x < 0n) return -1;
    100       if (x > 0n) return  1;
    101       return 0;
    102     });
    103 
    104     process.stdout.write(`\nMonkey business: ${monkeys[0].inspects} * ${monkeys[1].inspects} = ${monkeys[0].inspects * monkeys[1].inspects}\n`);
    105 
    106     console.log('finish');
    107   });