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 (2758B)


      1 const fs            = require('fs');
      2 const through       = require('through2');
      3 const line_for_line = require('../common/line-for-line');
      4 
      5 let pwd    = [];
      6 let vfs    = {};
      7 const size = Symbol('size');
      8 const dirs = {'/': 0};
      9 
     10 let totalsize = 70000000;
     11 
     12 function set(sub, path, value) {
     13   // console.log('set', { sub, path, value });
     14   path = path.slice();
     15   const last = path.pop();
     16   while(path.length) {
     17     const token = path.shift();
     18     sub = sub[token] = sub[token] || {};
     19   }
     20   sub[last] = value;
     21 }
     22 function get(sub, path) {
     23   path = path.slice();
     24   while(path.length) sub = sub[path.shift()];
     25   return sub;
     26 }
     27 const sum = (r, a) => r + a;
     28 
     29 fs.createReadStream('input')
     30   .pipe(line_for_line())
     31 
     32   // Build directory structure
     33   .pipe(through(function(line, enc, cb) {
     34     line = line.toString();
     35     process.stdout.write(`${pwd.join('/')}> ${line}\n`);
     36     const [type, ...args] = line.split(' ');
     37 
     38     if (!isNaN(type)) {
     39       // File marker
     40       const p = [...pwd, args[0]].join('/');
     41       vfs[p] = parseInt(type);
     42     } else if (type == 'dir') {
     43       // Dir marker
     44       const p = [...pwd, args[0]].join('/');
     45       dirs[p] = 0;
     46     } else if (type == '$') {
     47       // Command marker
     48       const cmd = args.shift();
     49       switch(cmd) {
     50         case 'cd':
     51           if (args[0] === '..') pwd.pop();
     52           else if (args[0] == '/') pwd = [];
     53           else pwd.push(args[0]);
     54           break;
     55         default:
     56           break;
     57       }
     58     } else {
     59       throw new Error(`Unknown type: ${type}`);
     60     }
     61 
     62     // console.log(JSON.stringify({ type, args, vfs }, null, 2));
     63     cb();
     64   }))
     65 
     66   // Actual tasks
     67   .on('finish', () => {
     68     // done
     69 
     70     // Calculate size independently for each directory
     71     for(let dir in dirs) {
     72       if (!dirs.hasOwnProperty(dir)) continue;
     73       if (dir == '/') {
     74         dirs[dir] = Object.values(vfs).reduce((r,a)=>r+a, 0);
     75         continue;
     76       }
     77       dir = dir + '/'
     78       dirs[dir] = Object.entries(vfs)
     79         .filter(([name, size]) => name.substr(0, dir.length) == dir)
     80         .map(([name, size]) => size)
     81         .reduce((r,a)=>r+a,0);
     82     }
     83 
     84     // Sum + threshold
     85     const threshold   = 100000;
     86     let   sum         = 0;
     87     for(const size of Object.values(dirs)) {
     88       if (size > threshold) continue;
     89       sum += size;
     90     }
     91     console.log({ sum });
     92 
     93     // Find smallest above threshold
     94     let unusedSize = totalsize - dirs['/'];
     95     let neededSize = 30000000;
     96     let deleteSize = neededSize - unusedSize;
     97     let selected   = '/';
     98     for(const [name, size] of Object.entries(dirs)) {
     99       if (size < deleteSize) continue;
    100       if (size >= dirs[selected]) continue;
    101       selected = name;
    102     }
    103 
    104     console.log({unusedSize, selected, 'sz': dirs[selected]});
    105 
    106     // START -- En
    107 
    108   });