aboutsummaryrefslogtreecommitdiff
path: root/src/2020/day9/aoc.cpp
blob: 10ba7893774a2e84d8da1b3bf557d2dc57f77750 (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
#include "aoc.h"
#include <set>

namespace aoc2020 {
static int numbers[1000] = {0};

static int get_number(const char* p) {
  int d{0};
  while (*p >= '0' && *p <= '9') {
    d = d * 10 + *p - '0';
    p++;
  }
  return d;
}

bool check25(int i, int* weak) {
  std::set<int> si;
  for (int x = i - 25; x < i; x++) {
    si.insert(numbers[x]);
  }
  for (int x = i - 25; x < i; x++) {
    int y = numbers[i] - numbers[x];
    if (si.find(y) != si.end()) {
      return true;
    }
  }

  *weak = numbers[i];
  return false;
}

bool check_contiguous(int i, int* end, int target) {
  if (target == 0) {
    *end = i;
    return true;
  }
  if (target < 0) {
    return false;
  }
  return check_contiguous(i + 1, end, target - numbers[i]);
}

static void minmax(int x, int y, int* min, int* max) {
  for(int i = x; i < y; i++) {
    if (*min > numbers[i]) {
        *min = numbers[i];
    }
    if (*max < numbers[i]) {
        *max = numbers[i];
    }
  }
}

std::pair<int, int> day9(line_view file) {
  int i{0};
  per_line(file, [&i](line_view lv){
    numbers[i++] = get_number(lv.line);
    return true;
  });

  int weak{0};
  int pos{0};
  for (int i = 25; i < 1000; i++) {
    if (!check25(i, &weak)) {
      pos = i;
      break;
    }
  }

  int e{0};
  int min{INT32_MAX}, max{INT32_MIN};
  for (int i = 0; i < pos; i++) {
    if (check_contiguous(i, &e, weak)) {
      minmax(i, e, &min, &max);
    }
  }

  return {weak, min + max};
}

}