From 56e890cec0a28c0a485212ccebfaf774235a79a2 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Wed, 3 Jan 2024 23:35:54 +0100 Subject: prepare for more puzzles ... :) --- 2023/src/day21.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 2023/src/day21.cpp (limited to '2023/src/day21.cpp') diff --git a/2023/src/day21.cpp b/2023/src/day21.cpp new file mode 100644 index 0000000..c633155 --- /dev/null +++ b/2023/src/day21.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +using position = tuple; + +vector +read_file(string_view filename) +{ + fstream input{ filename }; + vector data; + + for ( string line; getline(input, line); ) { + data.emplace_back(line); + } + + return data; +} + +position +find_start_position(const vector& lines) +{ + for ( size_t row = 0; row != lines.size(); ++row ) { + for ( size_t col = 0; col != lines[row].size(); ++col ) { + if ( lines[row][col] == 'S' ) { + return { row, col }; + } + } + } + return {}; +} + +set +find_neighbours(position pos, const vector& lines) +{ + static const vector movements = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; + + set neighbours; + const auto [row, col] = pos; + + for ( const auto& [drow, dcol]: movements ) { + const auto nrow = row + drow; + const auto ncol = col + dcol; + + if ( nrow < lines.size() && ncol < lines[0].size() && (lines[nrow][ncol] == '.' || lines[nrow][ncol] == 'S') ) { + neighbours.emplace(nrow, ncol); + } + } + + return neighbours; +} + +size_t +count(vector lines, position start, size_t rounds) +{ + queue positions; + positions.emplace(start); + + size_t sum = 0; + for ( size_t round = 0; round != rounds; ++round ) { + set next_positions; + + sum = 0; + while ( !positions.empty() ) { + const auto [curr_row, curr_col] = positions.front(); + lines[curr_row][curr_col] = '.'; + + const auto neighbours = find_neighbours(positions.front(), lines); + positions.pop(); + + for ( const auto& [row, col]: neighbours ) { + lines[row][col] = 'O'; + next_positions.emplace(row, col); + ++sum; + } + } + + for ( const auto& position: next_positions ) { + positions.emplace(position); + } + } + return sum; +} + +void +part1(const vector& lines) +{ + const auto start = find_start_position(lines); + cout << count(lines, start, 64) << endl; +} + +void +part2(const vector& lines) +{ + const auto start = find_start_position(lines); + const auto [row, col] = start; + + const auto pow2 = [](size_t val) -> size_t { + return val * val; + }; + + const auto size = lines.size(); + const size_t steps = 26501365; + const auto grid_width = steps / size - 1; + + const auto num_odd_tiles = pow2(grid_width / 2 * 2 + 1); + const auto num_even_tiles = pow2((grid_width + 1) / 2 * 2); + const auto num_odd_points = count(lines, start, size * 2 + 1); + const auto num_even_points = count(lines, start, size * 2); + + auto sum = num_odd_tiles * num_odd_points + num_even_tiles * num_even_points; + + const auto corner_top = count(lines, { size - 1, col }, size - 1); + const auto corner_right = count(lines, { row, 0 }, size - 1); + const auto corner_bottom = count(lines, { 0, col }, size - 1); + const auto corner_left = count(lines, { row, size - 1 }, size - 1); + + sum += corner_top + corner_right + corner_bottom + corner_left; + + const auto small_top_right = count(lines, { size - 1, 0 }, size / 2 - 1); + const auto small_top_left = count(lines, { size - 1, size - 1 }, size / 2 - 1); + const auto small_bottom_right = count(lines, { 0, 0 }, size / 2 - 1); + const auto small_bottom_left = count(lines, { 0, size - 1 }, size / 2 - 1); + + sum += (grid_width + 1) * (small_top_right + small_top_left + small_bottom_right + small_bottom_left); + + const auto large_top_right = count(lines, { size - 1, 0 }, size * 3 / 2 - 1); + const auto large_top_left = count(lines, { size - 1, size - 1 }, size * 3 / 2 - 1); + const auto large_bottom_right = count(lines, { 0, 0 }, size * 3 / 2 - 1); + const auto large_bottom_left = count(lines, { 0, size - 1 }, size * 3 / 2 - 1); + + sum += grid_width * (large_top_right + large_top_left + large_bottom_right + large_bottom_left); + + cout << sum << endl; +} + +int +main() +{ + auto lines = read_file("data/day21.txt"); + part1(lines); + part2(lines); +} -- cgit v1.3