-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday03.cpp
More file actions
180 lines (150 loc) · 5.76 KB
/
day03.cpp
File metadata and controls
180 lines (150 loc) · 5.76 KB
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include "day03.h"
#include <cctype>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
namespace day03
{
int solvePart1(std::ifstream& file);
int solvePart2(std::ifstream& file);
void run_day(bool example)
{
std::cout << "Running day 03 \n";
const std::string fileName{ example ? "inputs/day03_example.txt" : "inputs/day03_real.txt" };
std::ifstream file{ fileName };
int sum{ solvePart1(file) };
std::cout << "Part 1 answer: " << sum << '\n';
file.close();
file.open(fileName);
sum = solvePart2(file);
std::cout << "Part 2 answer: " << sum << '\n';
}
std::vector<std::vector<char>> parseInput(std::ifstream& file)
{
// For height loop over lines and count:
size_t height{};
std::string line;
while (std::getline(file, line))
{
height++;
}
// Create outer vector
std::vector<std::vector<char>> field(height);
// Reset file stream
file.clear();
file.seekg(0);
// Read in each line of file
size_t currentLineIndex{};
while (std::getline(file, line))
{
const std::vector<char> fieldLine(line.begin(), line.end());
field[currentLineIndex] = fieldLine;
currentLineIndex++;
}
return field;
}
int solvePart1(std::ifstream& file)
{
const std::vector<std::vector<char>> field{ parseInput(file) };
const int height{ static_cast<int>(field.size()) };
const int width{ static_cast<int>(field[0].size()) };
int partsSum{};
// Loop over the lines detecting numbers:
for (size_t y = 0; y < height; y ++)
{
size_t x{};
// Keep going on line until we pass right-hand of field.
while (x < width)
{
// Skip over non-digits
while (x < width && !std::isdigit(field[y][x]))
x++;
int partNumber{};
// Collect full partNumber
char digit;
const size_t startOfNumber{ x };
while (x < width && std::isdigit(digit = field[y][x]))
{
partNumber *= 10;
partNumber += digit - '0';
x++;
}
const size_t endOfNumber{ x - 1 };
// Now need to determine if number is partConnected
bool partAdjacent{};
for (size_t compareY = y - 1; compareY <= y + 1; compareY++)
{
for (size_t compareX = startOfNumber - 1; compareX <= endOfNumber + 1; compareX++)
{
if (compareY > 0 && compareY < height && compareX > 0 && compareX < width
&& !std::isdigit(field[compareY][compareX]) && field[compareY][compareX] != '.')
// Found an adjacent square in field with non-digit, non-. character
partAdjacent = true;
}
}
if (partAdjacent)
partsSum += partNumber;
}
}
return partsSum;
}
int solvePart2(std::ifstream& file)
{
const std::vector<std::vector<char>> field{ parseInput(file) };
const size_t height{ (field.size()) };
const size_t width{ (field[0].size()) };
// We create two new fields where we keep track of the nr of adjacent numbers if *
// and the product of adjacent numbers.
std::vector<std::vector<int>> adjCountField(height, std::vector<int>(width, 0));
std::vector<std::vector<int>> adjProductField(height, std::vector<int>(width, 1));
// Loop over the lines detecting numbers to fill out our adj fields:
for (size_t y = 0; y < height; y++)
{
size_t x{};
// Keep going on line until we pass right-hand of field.
while (x < width)
{
// Skip over non-digits
while (x < width && !std::isdigit(field[y][x]))
x++;
int partNumber{};
// Collect full partNumber
char digit;
const size_t startOfNumber{ x };
while (x < width && std::isdigit(digit = field[y][x]))
{
partNumber *= 10;
partNumber += digit - '0';
x++;
}
const size_t endOfNumber{ x - 1 };
// Now check for adjacent gears to up our count/product field for
for (size_t compareY = y - 1; compareY <= y + 1; compareY++)
{
for (size_t compareX = startOfNumber - 1; compareX <= endOfNumber + 1; compareX++)
{
if (compareY > 0 && compareY < height && compareX > 0 && compareX < width
&& field[compareY][compareX] == '*')
{
// Found an adjacent square in field with gear in it, up count & product.
adjCountField[compareY][compareX] += 1;
adjProductField[compareY][compareX] *= partNumber;
}
}
}
}
}
// Loop over the adj fields to determine the sum of faulty gears
int faultySum{};
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
{
if (adjCountField[y][x] == 2)
faultySum += adjProductField[y][x];
}
}
return faultySum;
}
}