aboutsummaryrefslogtreecommitdiff
path: root/2021/day25/day25.cpp
diff options
context:
space:
mode:
authorjacopograndi <jacopo.grandi@outlook.it>2022-02-28 18:55:18 +0100
committerjacopograndi <jacopo.grandi@outlook.it>2022-02-28 18:55:18 +0100
commit6fd47da5cb524f3239ebd99a8204ff5eaaec3ef5 (patch)
treeb137460e86e9008cbd4073f573d357e577d18aca /2021/day25/day25.cpp
parent629a630b2d8a02a6c9aff2e7c8c61a6e55da2b32 (diff)
day25
Diffstat (limited to '2021/day25/day25.cpp')
-rw-r--r--2021/day25/day25.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/2021/day25/day25.cpp b/2021/day25/day25.cpp
new file mode 100644
index 0000000..5797ee2
--- /dev/null
+++ b/2021/day25/day25.cpp
@@ -0,0 +1,195 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "gtest/gtest.h"
+
+
+class Board {
+ private:
+ std::vector<int> tiles;
+
+ int at_uncheck (int i, int j) { return i+j*sx; }
+ int at (int i, int j) const { return (i%sx)+(j%sy)*sx; }
+
+ public:
+ int sx, sy;
+
+ Board(const Board &b): sx(b.sx), sy(b.sy), tiles(b.tiles) { }
+ Board(int sx, int sy): sx(sx), sy(sy) {
+ for (int j=0; j<sy; j++)
+ for (int i=0; i<sx; i++)
+ tiles.push_back(0);
+ }
+ Board(std::string raw) {
+ sy = 0;
+ while (raw.size() > 0) {
+ std::string line = raw;
+ auto token = raw.find("\n");
+ if (token != std::string::npos) {
+ line = raw.substr(0, token);
+ raw = raw.substr(token+1);
+ } else raw = "";
+ for (int i=0; i<line.size(); i++) {
+ if (line[i] == '.') tiles.push_back(0);
+ if (line[i] == '>') tiles.push_back(1);
+ if (line[i] == 'v') tiles.push_back(2);
+ }
+ sx = line.size();
+ sy ++;
+ }
+ }
+
+ int get (int i, int j) const { return tiles[at(i, j)]; }
+ void set (int i, int j, int v) { tiles[at(i, j)] = v; }
+
+ friend std::ostream& operator<< (
+ std::ostream& stream, const Board& board)
+ {
+ stream << "Board ("
+ << board.sx << ", " << board.sy << ")" << std::endl;
+ for (int j=0; j<board.sy; j++) {
+ for (int i=0; i<board.sx; i++) {
+ int tile = board.get(i, j);
+ if (tile == 0) stream << ".";
+ if (tile == 1) stream << ">";
+ if (tile == 2) stream << "v";
+ }
+ stream << std::endl;
+ }
+ return stream;
+ }
+};
+
+TEST (board, exist) {
+ Board b { 4, 4 };
+}
+
+TEST (board, modify) {
+ Board b { 4, 4 };
+ b.set(3, 3, 1);
+ ASSERT_EQ(1, b.get(3, 3));
+}
+
+TEST (board, donut) {
+ Board b { 4, 4 };
+ b.set(4, 4, 1);
+ ASSERT_EQ(1, b.get(0, 0));
+}
+
+TEST (board, parse_ez) {
+ Board b { ".>v" };
+ ASSERT_EQ(0, b.get(0, 0));
+ ASSERT_EQ(1, b.get(1, 0));
+ ASSERT_EQ(2, b.get(2, 0));
+}
+
+TEST (board, parse_test_txt) {
+ std::string raw;
+ std::getline(std::ifstream("test0.txt"), raw, '\0');
+ Board b { raw };
+ ASSERT_EQ(0, b.get(0, 0));
+ ASSERT_EQ(1, b.get(3, 0));
+ ASSERT_EQ(2, b.get(0, 3));
+ ASSERT_EQ(2, b.get(4, 6));
+}
+
+
+class Engine {
+ private:
+ int t;
+
+ public:
+ Engine (Board b): board(b), t(0) { }
+
+ Board board;
+
+ friend std::ostream& operator<< (
+ std::ostream& stream, const Engine& e)
+ {
+ stream << "Engine (step: " << e.t << ")" << std::endl;
+ stream << e.board;
+ return stream;
+ }
+
+ int step_herd(int h, int move) {
+ int changes = 0;
+ Board next { board };
+ for (int j=0; j<board.sy; j++) {
+ for (int i=0; i<board.sx; i++) {
+ if (board.get(i, j) == h) {
+ if (move == 0) {
+ if (board.get(i+1, j) == 0) {
+ next.set(i+1, j, board.get(i, j));
+ next.set(i, j, 0);
+ changes ++;
+ }
+ }
+ if (move == 1) {
+ if (board.get(i, j+1) == 0) {
+ next.set(i, j+1, board.get(i, j));
+ next.set(i, j, 0);
+ changes ++;
+ }
+ }
+ }
+ }
+ }
+ board = next;
+ return changes;
+ }
+
+ int step () {
+ t++;
+ int changes = 0;
+ changes += step_herd(1, 0);
+ changes += step_herd(2, 1);
+ return changes;
+ }
+
+ void run () {
+ int changes = step();
+ if (changes > 0) run();
+ }
+
+ int get_t() { return t; }
+};
+
+TEST (engine, step_ez) {
+ Engine engine { Board { "...>>>>>..." } };
+ engine.step();
+ ASSERT_EQ(1, engine.board.get(8, 0));
+ engine.step();
+ ASSERT_EQ(0, engine.board.get(8, 0));
+}
+
+TEST (engine, step_blocking) {
+ std::string raw;
+ std::getline(std::ifstream("test1.txt"), raw, '\0');
+ Engine engine { Board { raw } };
+ engine.step();
+ ASSERT_EQ(2, engine.board.get(7, 2));
+}
+
+TEST (engine, step_run) {
+ std::string raw;
+ std::getline(std::ifstream("test2.txt"), raw, '\0');
+ Engine engine { Board { raw } };
+ engine.run();
+}
+
+
+int main (int argc, char *argv[]) {
+ if (argc > 1 && std::string { argv[1] } == "-t") {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+ }
+
+ std::string raw;
+ std::getline(std::ifstream("day25_input.txt"), raw, '\0');
+ Engine engine { Board { raw } };
+ engine.run();
+ std::cout << "steps: " << engine.get_t() << std::endl;
+
+ return 0;
+}