Skip to content

Commit 794f057

Browse files
committed
feat: day09 in c++
1 parent 871b938 commit 794f057

File tree

9 files changed

+200
-63
lines changed

9 files changed

+200
-63
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ Ideally, the solution does not use external crates/dependencies.
1919
| 6 |||||||
2020
| 7 |||||||
2121
| 8 |||||||
22-
| 9 ||| | |||
22+
| 9 ||| | |||

cpp/day03.cc

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "helpers.h"
12
#include <cctype>
23
#include <fstream>
34
#include <iostream>
@@ -142,17 +143,6 @@ int parseWithRules(const std::string &message) {
142143
return count;
143144
}
144145

145-
std::string readFile(const std::string &filePath) {
146-
std::ifstream file(filePath);
147-
if (!file.is_open()) {
148-
throw std::runtime_error("Unable to open file: " + filePath);
149-
}
150-
151-
std::ostringstream content;
152-
content << file.rdbuf();
153-
return content.str();
154-
}
155-
156146
int main() {
157147
try {
158148
std::string message = readFile("crates/day03/input.txt");

cpp/day05.cc

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "helpers.h"
12
#include <algorithm>
23
#include <fstream>
34
#include <iostream>
@@ -114,16 +115,6 @@ class PrintQueueChecker {
114115
}
115116
};
116117

117-
std::string readFile(const std::string &filename) {
118-
std::ifstream file(filename);
119-
if (!file)
120-
throw std::runtime_error("Unable to open file");
121-
122-
std::ostringstream ss;
123-
ss << file.rdbuf();
124-
return ss.str();
125-
}
126-
127118
int main() {
128119
try {
129120
std::string message = readFile("crates/day05/input.txt");

cpp/day06.cc

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "helpers.h"
12
#include <fstream>
23
#include <iostream>
34
#include <optional>
@@ -206,16 +207,6 @@ class Lab {
206207
}
207208
};
208209

209-
string readFile(const string &filename) {
210-
ifstream file(filename);
211-
if (!file.is_open()) {
212-
throw runtime_error("Could not open file");
213-
}
214-
stringstream buffer;
215-
buffer << file.rdbuf();
216-
return buffer.str();
217-
}
218-
219210
int main() {
220211
try {
221212
string message = readFile("crates/day06/input.txt");

cpp/day07.cc

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "helpers.h"
12
#include <algorithm>
23
#include <cassert>
34
#include <cmath>
@@ -91,20 +92,9 @@ struct Calibration {
9192
}
9293
};
9394

94-
std::string read_file(const std::string &file_path) {
95-
std::ifstream file(file_path);
96-
if (!file) {
97-
throw std::runtime_error("Could not open file: " + file_path);
98-
}
99-
100-
std::ostringstream buffer;
101-
buffer << file.rdbuf();
102-
return buffer.str();
103-
}
104-
10595
int main() {
10696
try {
107-
std::string message = read_file("crates/day07/input.txt");
97+
std::string message = readFile("crates/day07/input.txt");
10898

10999
// --- Part One ---
110100
Calibration checker(message);

cpp/day08.cc

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "helpers.h"
12
#include <algorithm>
23
#include <cmath>
34
#include <fstream>
@@ -140,19 +141,9 @@ class Antenna {
140141
GridSize grid;
141142
};
142143

143-
std::string read_file(const std::string &filename) {
144-
std::ifstream file(filename);
145-
if (!file) {
146-
throw std::runtime_error("Could not open the file");
147-
}
148-
std::stringstream buffer;
149-
buffer << file.rdbuf();
150-
return buffer.str();
151-
}
152-
153144
int main() {
154145
try {
155-
std::string message = read_file("crates/day08/input.txt");
146+
std::string message = readFile("crates/day08/input.txt");
156147

157148
// --- Part One ---
158149
Antenna checker(message);

cpp/day09.cc

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#include "helpers.h"
2+
#include <algorithm>
3+
#include <cstdint>
4+
#include <fstream>
5+
#include <iostream>
6+
#include <optional>
7+
#include <string>
8+
#include <vector>
9+
10+
enum class File { Free, Taken };
11+
12+
struct TakenFile {
13+
uint32_t id;
14+
};
15+
16+
class FileSystem {
17+
private:
18+
std::vector<std::optional<TakenFile>> files;
19+
std::vector<std::optional<TakenFile>> defragmentedFiles;
20+
21+
public:
22+
FileSystem(const std::string &content) {
23+
uint32_t id = 0;
24+
for (const auto &line : split(content, '\n')) {
25+
for (size_t i = 0; i < line.size(); ++i) {
26+
char c = line[i];
27+
if (std::isdigit(c)) {
28+
uint32_t digit = c - '0';
29+
if (i % 2 == 0) {
30+
for (uint32_t j = 0; j < digit; ++j) {
31+
files.emplace_back(TakenFile{id});
32+
}
33+
id++;
34+
} else {
35+
for (uint32_t j = 0; j < digit; ++j) {
36+
files.emplace_back(std::nullopt);
37+
}
38+
}
39+
}
40+
}
41+
}
42+
defragmentedFiles = files;
43+
}
44+
45+
static size_t
46+
countFreeFiles(const std::vector<std::optional<TakenFile>> &files,
47+
size_t index) {
48+
size_t count = 0;
49+
for (size_t i = index; i < files.size(); ++i) {
50+
if (files[i].has_value()) {
51+
break;
52+
}
53+
count++;
54+
}
55+
return count;
56+
}
57+
58+
static std::optional<std::pair<size_t, size_t>>
59+
detectBlock(const std::vector<std::optional<TakenFile>> &files,
60+
size_t indexEnd) {
61+
std::optional<std::pair<uint32_t, size_t>> currentBlock;
62+
63+
for (size_t i = indexEnd; i-- > 0;) {
64+
if (!files[i].has_value()) {
65+
if (currentBlock.has_value()) {
66+
return std::make_pair(i + 1, currentBlock->second);
67+
}
68+
currentBlock.reset();
69+
} else if (files[i]->id) {
70+
if (!currentBlock.has_value()) {
71+
currentBlock = std::make_pair(files[i]->id, 1);
72+
} else if (files[i]->id != currentBlock->first) {
73+
return std::make_pair(i + 1, currentBlock->second);
74+
} else {
75+
currentBlock->second++;
76+
}
77+
}
78+
}
79+
80+
return std::nullopt;
81+
}
82+
83+
void fragmentFiles() {
84+
for (size_t i = 0; i < defragmentedFiles.size(); ++i) {
85+
if (!defragmentedFiles[i].has_value()) {
86+
auto it = std::find_if(
87+
defragmentedFiles.rbegin(), defragmentedFiles.rend() - i,
88+
[](const auto &file) { return file.has_value(); });
89+
if (it != defragmentedFiles.rend() - i) {
90+
std::iter_swap(defragmentedFiles.begin() + i, it.base() - 1);
91+
}
92+
}
93+
}
94+
}
95+
96+
void fragmentFilesBlock() {
97+
size_t endVec = files.size();
98+
while (auto block = detectBlock(files, endVec)) {
99+
size_t startIndex = block->first;
100+
size_t size = block->second;
101+
bool followingFreeFile = false;
102+
for (size_t i = 0; i < files.size(); ++i) {
103+
if (!files[i].has_value()) {
104+
if (!followingFreeFile) {
105+
followingFreeFile = true;
106+
size_t numberFreeFiles = countFreeFiles(files, i);
107+
if (numberFreeFiles >= size && i < startIndex) {
108+
for (size_t j = 0; j < size; ++j) {
109+
std::swap(files[i + j], files[startIndex + j]);
110+
}
111+
break;
112+
}
113+
}
114+
} else {
115+
followingFreeFile = false;
116+
}
117+
}
118+
endVec = startIndex;
119+
}
120+
}
121+
122+
static uint64_t
123+
calculateChecksum(const std::vector<std::optional<TakenFile>> &files) {
124+
uint64_t checksum = 0;
125+
for (size_t i = 0; i < files.size(); ++i) {
126+
if (files[i].has_value()) {
127+
checksum += i * files[i]->id;
128+
}
129+
}
130+
return checksum;
131+
}
132+
133+
const std::vector<std::optional<TakenFile>> &getDefragmentedFiles() const {
134+
return defragmentedFiles;
135+
}
136+
137+
const std::vector<std::optional<TakenFile>> &getFiles() const {
138+
return files;
139+
}
140+
141+
private:
142+
static std::vector<std::string> split(const std::string &str,
143+
char delimiter) {
144+
std::vector<std::string> tokens;
145+
size_t start = 0, end = 0;
146+
while ((end = str.find(delimiter, start)) != std::string::npos) {
147+
tokens.push_back(str.substr(start, end - start));
148+
start = end + 1;
149+
}
150+
tokens.push_back(str.substr(start));
151+
return tokens;
152+
}
153+
};
154+
155+
int main() {
156+
try {
157+
std::string message = readFile("crates/day09/input.txt");
158+
159+
// --- Part One ---
160+
FileSystem checker(message);
161+
checker.fragmentFiles();
162+
std::cout << "Part One solution: "
163+
<< FileSystem::calculateChecksum(checker.getDefragmentedFiles())
164+
<< "\n";
165+
166+
// --- Part Two ---
167+
checker.fragmentFilesBlock();
168+
std::cout << "Part Two solution: "
169+
<< FileSystem::calculateChecksum(checker.getFiles()) << "\n";
170+
171+
} catch (const std::exception &ex) {
172+
std::cerr << "Error: " << ex.what() << "\n";
173+
return 1;
174+
}
175+
return 0;
176+
}

cpp/helpers.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <fstream>
2+
#include <sstream>
3+
#include <string>
4+
5+
std::string readFile(const std::string &filePath) {
6+
std::ifstream file(filePath);
7+
if (!file) {
8+
throw std::runtime_error("Could not open file");
9+
}
10+
return std::string((std::istreambuf_iterator<char>(file)),
11+
std::istreambuf_iterator<char>());
12+
}

crates/day09/src/main.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,10 @@ impl FileSystem {
128128
fn calculate_checksum(files: &[File]) -> u64 {
129129
files
130130
.iter()
131-
.enumerate() // Get position (index) along with each file
132-
.filter_map(|(pos, file)| {
133-
if let File::Taken(id) = file {
134-
// println!("{pos} * {id} [{file:?}]");
135-
Some(pos as u64 * u64::from(*id))
136-
} else {
137-
None
138-
}
131+
.enumerate()
132+
.filter_map(|(pos, file)| match file {
133+
File::Taken(id) => Some(pos as u64 * u64::from(*id)),
134+
File::Free => None,
139135
})
140136
.sum()
141137
}

0 commit comments

Comments
 (0)