-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
161 lines (128 loc) · 4.63 KB
/
main.cpp
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Advent of Code: Day 03
// Ali Bozorgzadeh
#include <bitset> // std::bitset
#include <cstdint> // uint32_t
#include <cstdlib> // std::exit()
#include <iostream> // std::cerr, std::cout
#include <stdexcept> // std::runtime_error
#include <string> // std::string
#include <vector> // std::vector
#include "utils/parser.h"
#include "utils/timer.h"
template <size_t N>
static uint32_t problem1(const std::string &input);
template <size_t N>
static uint64_t problem2(const std::string &input);
// If you want most common pass true as second argument, otherwise false
template <size_t N>
bool computeCommonBitAtPos(std::vector<std::bitset<N>> &vec, size_t pos,
bool is_most);
#define BITWIDTH 12
int main() {
auto timer = utils::Timer();
std::cout << "Problem 1: answer: " << problem1<BITWIDTH>("input.txt")
<< '\n';
std::cout << "Problem 2: answer: " << problem2<BITWIDTH>("input.txt")
<< '\n';
return 0;
}
// N: width of the bits
// > for std::bitset<N>, N must be known at compile time, otherwise
// std::vector<bool> or boost::dynamic_bitset may be used
template <size_t N>
static uint32_t problem1(const std::string &input) {
// Read the file and buffer it
std::vector<std::bitset<N>> data;
try {
data = utils::parseOnePerLine<std::bitset<N>>(input);
} catch (const std::runtime_error &e) {
std::cerr << e.what() << '\n';
std::exit(1);
}
// Bits are initialized to zero
std::bitset<N> gamma;
// For each bit position
// > Here we counting in the reverse order, from the least significant bit
// to the most
for (size_t bitPos = 0; bitPos < N; ++bitPos) {
uint32_t nOnes = 0;
uint32_t nZeros = 0;
// Look up index bitPos of bits in each line
for (const auto bits : data) bits[bitPos] == 0 ? ++nZeros : ++nOnes;
// Compute the most common bit
nZeros > nOnes ? gamma[bitPos] = 0 : gamma[bitPos] = 1;
}
// epsilon is exactly flipped version of gamma (Note the overloaded ~
// operator)
std::bitset<N> epsilon = ~gamma;
// Answer
uint32_t powerConsumption =
static_cast<uint32_t>(gamma.to_ulong() * epsilon.to_ulong());
return powerConsumption;
}
template <size_t N>
bool computeCommonBitAtPos(std::vector<std::bitset<N>> &vec, size_t pos,
bool is_most) {
size_t nZeros = 0;
size_t nOnes = 0;
for (const auto bits : vec) {
bits[pos] == 0 ? ++nZeros : ++nOnes;
}
if (is_most) return nZeros > nOnes ? false : true;
return nZeros > nOnes ? true : false;
}
template <size_t N>
static uint64_t problem2(const std::string &input) {
(void)input;
std::vector<std::bitset<N>> data =
utils::parseOnePerLine<std::bitset<N>>(input);
// Use these to do the calculation on a reduced set of binary numbers
std::vector<std::bitset<N>> data_curr_pos = data;
std::vector<std::bitset<N>> data_next_pos;
// O2 Generator rating
uint64_t O2_rating = 0;
for (size_t bitPos = N - 1; bitPos >= 0; --bitPos) {
bool mostCommonBit =
computeCommonBitAtPos<N>(data_curr_pos, bitPos, true);
// Clear its content before pushing new binary numbers in it
data_next_pos.clear();
// Create new vector
for (const auto bits : data_curr_pos) {
if (static_cast<bool>(bits[bitPos]) == mostCommonBit) {
data_next_pos.push_back(bits);
}
}
// Check if we left with one binary number
if (data_next_pos.size() == 1) {
O2_rating = data_next_pos[0].to_ulong();
break;
}
// Swap them, so no copy
data_curr_pos.swap(data_next_pos);
}
// CO2 Scrubber Rating
uint64_t CO2_rating = 0;
data_curr_pos = data;
data_next_pos.clear();
for (size_t bitPos = N - 1; bitPos >= 0; --bitPos) {
// Calculate the least common bit
bool leastCommonBit =
computeCommonBitAtPos<N>(data_curr_pos, bitPos, false);
// Clear its content before pushing new binary numbers in it
data_next_pos.clear();
// Create new vector
for (const auto bits : data_curr_pos) {
if (static_cast<bool>(bits[bitPos]) == leastCommonBit) {
data_next_pos.push_back(bits);
}
}
// Check if we left with one binary number
if (data_next_pos.size() == 1) {
CO2_rating = data_next_pos[0].to_ulong();
break;
}
// Swap them, so no copy
data_curr_pos.swap(data_next_pos);
}
return O2_rating * CO2_rating;
}