From dda4d56f5374fb3b176242182bc6fc1f2ebbfe74 Mon Sep 17 00:00:00 2001 From: Ben Kyd Date: Thu, 4 Dec 2025 15:22:41 +0000 Subject: [PATCH] d4 fast --- 2025/aoc | Bin 100880 -> 99856 bytes 2025/aoc.cpp | 98 ++++++++++++++++++++++--------- 2025/aoc.hpp | 158 +++++++++++++++++++++++++++++--------------------- 2025/day4.hpp | 143 ++++++++++++++++++++++++++++----------------- 4 files changed, 253 insertions(+), 146 deletions(-) diff --git a/2025/aoc b/2025/aoc index 97b0f585b5ed17eded4905a5d58d0c954b031e8b..3f42aa92a9d21f22d78649bbf13b5e3803097a9d 100755 GIT binary patch delta 20554 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 diff --git a/2025/aoc.cpp b/2025/aoc.cpp index 663d537..340dfe7 100644 --- a/2025/aoc.cpp +++ b/2025/aoc.cpp @@ -1,8 +1,11 @@ + #include #include #include #include #include +#include +#include #include "aoc.hpp" #include "day1.hpp" @@ -12,7 +15,7 @@ void GenerateDay(int day, std::filesystem::path base) { - std::cout << "Ganerating template for day " << day << std::endl; + std::cout << "Generating template for day " << day << std::endl; std::ostringstream className; className << "Day" << std::setw(2) << std::setfill('0') << day; // Day01 std::string classStr = className.str(); @@ -71,6 +74,7 @@ int main(int argc, char** argv) // Very shit command-line parsing :tm: int run_day = 0; + int num_runs = 1; std::filesystem::path base = "./"; for (int i = 1; i < argc; ++i) @@ -90,6 +94,20 @@ int main(int argc, char** argv) std::cout << "Selected day to run: " << run_day << "\n"; } + // Runs flag + if (arg == "-r" || arg == "--runs") + { + if (i + 1 >= argc) + { + std::cerr << "Error: -r requires a number of runs\n"; + return 1; + } + ++i; + num_runs = std::atoi(argv[i]); + if (num_runs < 1) num_runs = 1; + std::cout << "Number of runs for averaging: " << num_runs << "\n"; + } + // Path flag if (arg == "-p" || arg == "--path") { @@ -120,23 +138,15 @@ int main(int argc, char** argv) { std::cout << "\nUsage:\n" << " -d [day] Run a specific day\n" + << " -r [runs] Number of runs to average timings (default: 1)\n" << " -p [path] Set a base path for input\n" - << " -g [day] Generate a new day! (Stil need to add to compiler)\n" + << " -g [day] Generate a new day! (Still need to add to compiler)\n" << " help Show this help message\n" << " (no args) Run all days\n"; return 0; } - - // Unknown argument - if (arg != "-d" && arg != "-p" && arg != "--path" && - arg != "help" && arg != "--help" && arg != "-h" && - arg != "-g" && arg != "--generate") - { - std::cerr << "Unknown argument: " << arg << "\n" - << "Use 'help' for usage information.\n"; - return 1; - } } + // // Run days if (run_day == 0) @@ -153,40 +163,74 @@ int main(int argc, char** argv) File file1{path}; uint64_t partOne = day->PartOne(file); - int partTwo = day->PartTwo(file1); + uint64_t partTwo = day->PartTwo(file1); std::cout << "Part 1: " << partOne << "\n"; std::cout << "Part 2: " << partTwo << "\n"; } - } else + } + else { for (auto& [num, day] : GetRegisteredDays(run_day)) { - std::cout << "Running only Day " << num << ":\n"; + std::cout << "Running Day " << num; + if (num_runs > 1) { + std::cout << " (averaging over " << num_runs << " runs)"; + } + std::cout << ":\n"; std::string filename = std::to_string(num) + ".txt"; std::filesystem::path path = base / filename; std::cout << "Reading " << path << "..." << std::endl; - File file{path}; - File file1{path}; - auto start = std::chrono::high_resolution_clock::now(); + // Storage for timing results + std::vector part1_times; + std::vector part2_times; + std::vector total_times; - uint64_t partOne = day->PartOne(file); + part1_times.reserve(num_runs); + part2_times.reserve(num_runs); + total_times.reserve(num_runs); - auto endpart1 = std::chrono::high_resolution_clock::now(); - auto startpart2 = std::chrono::high_resolution_clock::now(); + uint64_t partOne = 0; + uint64_t partTwo = 0; - uint64_t partTwo = day->PartTwo(file1); + // Run multiple times + for (int run = 0; run < num_runs; ++run) + { + File file{path}; + File file1{path}; - auto end = std::chrono::high_resolution_clock::now(); + auto start = std::chrono::high_resolution_clock::now(); - std::cout << "Part 1: " << partOne << " - took " << std::chrono::duration(endpart1 - start).count() << "ms" << std::endl; - std::cout << "Part 2: " << partTwo << " - took " << std::chrono::duration(end - startpart2).count() << "ms" << std::endl; - std::cout << "Day " << run_day << " ran in " << std::chrono::duration(end - start).count() << "ms" << std::endl; + partOne = day->PartOne(file); + + auto endpart1 = std::chrono::high_resolution_clock::now(); + auto startpart2 = std::chrono::high_resolution_clock::now(); + + partTwo = day->PartTwo(file1); + + auto end = std::chrono::high_resolution_clock::now(); + + part1_times.push_back(std::chrono::duration(endpart1 - start).count()); + part2_times.push_back(std::chrono::duration(end - startpart2).count()); + total_times.push_back(std::chrono::duration(end - start).count()); + } + + // Calculate averages + double p1_avg = std::accumulate(part1_times.begin(), part1_times.end(), 0.0) / num_runs; + double p2_avg = std::accumulate(part2_times.begin(), part2_times.end(), 0.0) / num_runs; + double total_avg = std::accumulate(total_times.begin(), total_times.end(), 0.0) / num_runs; + + // Print results + std::cout << "Part 1: " << partOne << " - took " + << std::fixed << std::setprecision(3) << p1_avg << "ms" << std::endl; + std::cout << "Part 2: " << partTwo << " - took " + << std::fixed << std::setprecision(3) << p2_avg << "ms" << std::endl; + std::cout << "Day " << run_day << " ran in " + << std::fixed << std::setprecision(3) << total_avg << "ms" << std::endl; } } - } diff --git a/2025/aoc.hpp b/2025/aoc.hpp index b64a599..7a2ee58 100644 --- a/2025/aoc.hpp +++ b/2025/aoc.hpp @@ -9,79 +9,103 @@ template class Grid { - public: - Grid() = default; - Grid(size_t h, size_t w) : data(h, std::vector(w)) {} - Grid(const std::vector>& d) : data(d) {} +public: + Grid() = default; - size_t Height() const { return data.size(); } - size_t Width() const { return data.empty() ? 0 : data[0].size(); } + Grid(size_t h, size_t w) : height(h), width(w), data(h * w) {} - const T& At(size_t r, size_t c) const { return data[r][c]; } + Grid(const std::vector d) + : height(d.size()) + , width(d.empty() ? 0 : d[0].size()) + , data(d) {} - const T* SafeAt(size_t r, size_t c) const + size_t Height() const { return height; } + size_t Width() const { return width; } + + const T& At(size_t r, size_t c) const + { + return data[r * width + c]; + } + + const T* SafeAt(size_t r, size_t c) const + { + if (r >= height || c >= width) return nullptr; + return &data[r * width + c]; + } + + void ReplaceAt(size_t r, size_t c, const T& value) + { + data[r * width + c] = value; + } + + size_t Neighbours4(size_t r, size_t c, const T* out[4], bool wrap = false) const + { + size_t count = 0; + + if (wrap) { - if (r >= Height() || c >= Width()) return nullptr; - return &data[r][c]; + out[count++] = &data[((r - 1 + height) % height) * width + c]; + out[count++] = &data[((r + 1) % height) * width + c]; + out[count++] = &data[r * width + ((c - 1 + width) % width)]; + out[count++] = &data[r * width + ((c + 1) % width)]; + } else + { + if (r > 0) + out[count++] = &data[(r - 1) * width + c]; + if (r + 1 < height) + out[count++] = &data[(r + 1) * width + c]; + if (c > 0) + out[count++] = &data[r * width + (c - 1)]; + if (c + 1 < width) + out[count++] = &data[r * width + (c + 1)]; } - void ReplaceAt(size_t r, size_t c, const T& value) - { - data[r][c] = value; - } - // - // 4-neighbours (up, down, left, right) - std::vector Neighbours4(size_t r, size_t c, bool wrap = false) const - { - std::vector out; + return count; + } - auto H = Height(); - auto W = Width(); + size_t Neighbours8(size_t r, size_t c, const T* out[8], bool wrap = false) const + { + size_t count = 0; - auto idx = [&](size_t x, size_t limit) -> size_t { - return wrap ? ((x + limit) % limit) : x; - }; + if (wrap) { + for (int dr = -1; dr <= 1; ++dr) + { + for (int dc = -1; dc <= 1; ++dc) + { + if (dr == 0 && dc == 0) continue; - if (r > 0 || wrap) out.push_back(&data[idx(r - 1, H)][c]); - if (r + 1 < H || wrap) out.push_back(&data[idx(r + 1, H)][c]); - if (c > 0 || wrap) out.push_back(&data[r][idx(c - 1, W)]); - if (c + 1 < W || wrap) out.push_back(&data[r][idx(c + 1, W)]); - - return out; - } - - // 8-neighbours (diagonals) - std::vector Neighbours8(size_t r, size_t c, bool wrap = false) const - { - std::vector out; - auto H = Height(); - auto W = Width(); - - auto idx = [&](size_t x, size_t limit) -> size_t { - return wrap ? ((x + limit) % limit) : x; - }; - - for (int dr = -1; dr <= 1; dr++) { - for (int dc = -1; dc <= 1; dc++) { + size_t rr = (r + dr + height) % height; + size_t cc = (c + dc + width) % width; + out[count++] = &data[rr * width + cc]; + } + } + } else { + for (int dr = -1; dr <= 1; ++dr) + { + for (int dc = -1; dc <= 1; ++dc) + { if (dr == 0 && dc == 0) continue; size_t rr = r + dr; size_t cc = c + dc; - if (!wrap) { - if (rr >= H || cc >= W) continue; - } + if (rr >= height || cc >= width) continue; - out.push_back(&data[idx(rr, H)][idx(cc, W)]); + out[count++] = &data[rr * width + cc]; } } - - return out; } - private: - std::vector> data; + + return count; + } + +private: + size_t height = 0; + size_t width = 0; + std::vector data; }; + struct FileFragment { int Line, Col; @@ -238,28 +262,32 @@ class File template Grid AsGrid() const { - std::vector> d; - d.reserve(_lines.size()); + const size_t height = _lines.size(); + if (height == 0) return Grid(0, 0); - for (auto& line : _lines) + const size_t width = _lines[0].size(); + + Grid grid(height, width); + + for (size_t r = 0; r < height; ++r) { - std::vector row; - row.reserve(line.size()); - - for (char ch : line) + const auto& line = _lines[r]; + for (size_t c = 0; c < width; ++c) { + char ch = line[c]; + if constexpr (std::is_constructible_v) { - row.emplace_back(T(ch)); + grid.ReplaceAt(r, c, T(ch)); } else if constexpr (std::is_constructible_v) { - row.emplace_back(T(std::string_view(&ch, 1))); + grid.ReplaceAt(r, c, T(std::string_view(&ch, 1))); } else if constexpr (std::is_arithmetic_v) { if (std::isdigit(ch)) - row.emplace_back(T(ch - '0')); + grid.ReplaceAt(r, c, T(ch - '0')); else throw std::runtime_error("Grid: cannot convert character to numeric T"); } @@ -268,11 +296,9 @@ class File static_assert(sizeof(T) == 0, "Grid: T must be constructible from char or string_view"); } } - - d.push_back(std::move(row)); } - return Grid(d); + return grid; } diff --git a/2025/day4.hpp b/2025/day4.hpp index cfeb7b2..42d352a 100644 --- a/2025/day4.hpp +++ b/2025/day4.hpp @@ -1,3 +1,4 @@ + #pragma once #include "aoc.hpp" @@ -13,85 +14,121 @@ public: const auto grid = f.AsGrid(); int res = 0; + const size_t height = grid.Height(); + const size_t width = grid.Width(); + const char* neighbours[8]; - for (int i = 0; i < grid.Width(); i++) + for (size_t i = 0; i < height; i++) { - for (int j = 0; j < grid.Width(); j++) + for (size_t j = 0; j < width; j++) { if (grid.At(i, j) != '@') continue; - auto neighbors = grid.Neighbours8(i, j); + size_t count = grid.Neighbours8(i, j, neighbours); + + // Unroll, unroll unroll int rollsOfPaper = 0; - for (auto* n : neighbors) - { - if (*n == '@') - { - rollsOfPaper++; - if (rollsOfPaper > 4) - { - break; - } - } - } + rollsOfPaper += (count > 0 && *neighbours[0] == '@'); + rollsOfPaper += (count > 1 && *neighbours[1] == '@'); + rollsOfPaper += (count > 2 && *neighbours[2] == '@'); + rollsOfPaper += (count > 3 && *neighbours[3] == '@'); + rollsOfPaper += (count > 4 && *neighbours[4] == '@'); + rollsOfPaper += (count > 5 && *neighbours[5] == '@'); + rollsOfPaper += (count > 6 && *neighbours[6] == '@'); + rollsOfPaper += (count > 7 && *neighbours[7] == '@'); - if (rollsOfPaper < 4) - { - res++; - } + if (rollsOfPaper < 4) res++; } } return res; } - int MovePossibleRolls(Grid* grid) + uint64_t PartTwo(File& f) override { - int removed = 0; - for (int i = 0; i < grid->Width(); i++) - { - for (int j = 0; j < grid->Width(); j++) - { - if (grid->At(i, j) != '@') continue; - auto neighbors = grid->Neighbours8(i, j); + const auto input = f.AsGrid(); - int rollsOfPaper = 0; - for (auto* n : neighbors) + const size_t width = input.Width(); + const size_t height = input.Height(); + const char* neighbours[8]; + + std::vector counts(width * height); + + for (size_t i = 0; i < height; i++) + { + for (size_t j = 0; j < width; j++) + { + const size_t idx = i * width + j; + + if (input.At(i, j) == '.') { - if (*n == '@') + counts[idx] = 255; + continue; + } + + size_t count = input.Neighbours8(i, j, neighbours); + + uint8_t roll_count = 0; + for (size_t k = 0; k < count; k++) + { + roll_count += (*neighbours[k] != '.'); + } + + counts[idx] = roll_count; + } + } + + int64_t removed = 0; + bool updated = true; + + Grid grid(height, width); + for (size_t i = 0; i < height; i++) + { + for (size_t j = 0; j < width; j++) + { + grid.ReplaceAt(i, j, counts[i * width + j]); + } + } + + while (updated) + { + updated = false; + + for (size_t i = 0; i < height; i++) + { + for (size_t j = 0; j < width; j++) + { + uint8_t val = grid.At(i, j); + if (val >= 4) continue; + + updated = true; + grid.ReplaceAt(i, j, 255); + removed++; + + size_t count = grid.Neighbours8(i, j, (const uint8_t**)neighbours); + for (size_t k = 0; k < count; k++) { - rollsOfPaper++; - if (rollsOfPaper > 4) + size_t ni, nj; + // AAAAA + const uint8_t* base = &grid.At(0, 0); + size_t offset = (const uint8_t*)neighbours[k] - base; + ni = offset / width; + nj = offset % width; + + uint8_t nval = grid.At(ni, nj); + if (nval < 255 && nval > 0) { - break; + grid.ReplaceAt(ni, nj, nval - 1); } } } - - if (rollsOfPaper < 4) - { - grid->ReplaceAt(i, j, '.'); - removed++; - } } } + return removed; } - uint64_t PartTwo(File& f) override - { - auto grid = f.AsGrid(); - - int removedRolls = 0; - - int removedLastTime = 0; - do - { - removedLastTime = MovePossibleRolls(&grid); - removedRolls += removedLastTime; - } while (removedLastTime != 0); - - return removedRolls; - } }; ADD_AOC_DAY(Day04); +