aboutsummaryrefslogtreecommitdiff
path: root/src/2022/day7/aoc.cpp
blob: 940d9be8bcf6a7ce0af4c974a0d765c62339dc14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "aoc.h"
#include <iostream>
#include <algorithm>

namespace aoc2022 {
static dir root{"/"};

// ls
void load(dir* d, line_view lv) {
  per_line(lv, [&d](line_view l) {
      dir* n = new dir(l);
      n->parent = d;
      d->dirs.push_back(n);
      return true;
  });
}

// cd /
void get_root(dir** current) {
  *current = &root;
}

// cd ..
void get_parent(dir** current) {
  dir* parent = (*current)->parent;
  *current = parent;
}

// cd xxxx
void get_dir(dir** current, line_view n) {
  dir* d = *current; 
  for(auto& s : d->dirs) {
    if (s->name == n) {
      *current = s;
      break;
    }
  }
}

struct dst {
  dir* d;
  int s;
};

void get_size(dir* d, std::vector<dir*> & dirs, std::vector<dst>& ds, int target) {
  int s = d->get_size();
  if (d->size == 0) {
    ds.push_back({d, s});
  }
  if (s <= target && d->size == 0) {
    // std::cout << d->name << " size is " << s << std::endl;
    dirs.push_back(d);
  }
  for (auto& x: d->dirs) {
    get_size(x, dirs, ds, target);
  }
}

std::pair<int,int> day7(line_view file) {
  dir* current = nullptr;
  const char* p = file.line;
  while(p < file.line + file.length) {
    if (p[0] == '$') {
      if (p[2] == 'c' && p[3] == 'd') {
        if (p[5] == '/') get_root(&current);
        else if (p[5] == '.') get_parent(&current);
        else {
          const char *p0 = p + 5;
          while(*p0 != '\n') p0++;
          get_dir(&current, line_view{p + 5, p0});
        }
        while(*p != '\n') p++;
      } 
      if (p[2] == 'l' && p[3] == 's') {
        const char* p0 = p + 5;
        while (*p0 != '$') p0++;
        load(current, line_view{p + 5, p0});
        p = p0 - 1;
      }
    }
    p++;
  }

  int rootsize = root.get_size();
  // printf("root size is %d\n", rootsize);
  std::vector<dir*> dirs;
  std::vector<dst> ds;
  get_size(&root, dirs, ds, 100000);
  int total{0};
  for(auto& d : dirs) {
     total += d->get_size();
  }
  std::sort(ds.begin(), ds.end(), [](const dst&d1, const dst&d2) {
      return d1.s < d2.s;
  });
  int smallest{0};
  for (auto& d: ds) {
    int x = 70000000 - rootsize + d.s;
    // std::cout << d.d->name << ": " << d.s << " avail: " << x << std::endl;
    if ( x >= 30000000) {
      smallest = d.s;
      break;
    }
  }
  return {total, smallest};
}

}