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/day14.cpp | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 2023/src/day14.cpp (limited to '2023/src/day14.cpp') diff --git a/2023/src/day14.cpp b/2023/src/day14.cpp new file mode 100644 index 0000000..8816ce1 --- /dev/null +++ b/2023/src/day14.cpp @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +vector +read_file(string_view filename) +{ + fstream input{ filename }; + vector data; + + for ( string line; getline(input, line); ) { + data.emplace_back(line); + } + + return data; +} + +void +part1(const vector& lines) +{ + auto start = chrono::steady_clock::now(); + + size_t sum = 0; + for ( size_t col = 0; col != lines[0].size(); ++col ) { + size_t counter = lines.size(); + + for ( size_t row = 0; row != lines.size(); ++row ) { + if ( lines[row][col] == 'O' ) { + sum += counter; + --counter; + } + if ( lines[row][col] == '#' ) { + counter = lines.size() - row - 1; + } + } + } + + auto duration = chrono::duration_cast(chrono::steady_clock::now() - start).count(); + + cout << sum << " (" << duration << " μs)" << endl; +} + +void +tilt_north(vector& lines) +{ + for ( size_t col = 0; col != lines[0].size(); ++col ) { + size_t row = 0; + while ( row != lines.size() ) { + size_t stones = 0; + size_t empty = 0; + + for ( size_t idx = row; idx != lines.size() && lines[idx][col] != '#'; ++idx ) { + if ( lines[idx][col] == '.' ) { + ++empty; + } + if ( lines[idx][col] == 'O' ) { + ++stones; + } + } + + while ( stones-- != 0 ) { + lines[row++][col] = 'O'; + } + + while ( empty-- != 0 ) { + lines[row++][col] = '.'; + } + + while ( row != lines.size() && lines[row][col] == '#' ) { + ++row; + } + } + } +} + +void +tilt_south(vector& lines) +{ + for ( size_t col = 0; col != lines[0].size(); ++col ) { + size_t row = 0; + while ( row != lines.size() ) { + size_t stones = 0; + size_t empty = 0; + + for ( size_t idx = row; idx != lines.size() && lines[idx][col] != '#'; ++idx ) { + if ( lines[idx][col] == '.' ) { + ++empty; + } + if ( lines[idx][col] == 'O' ) { + ++stones; + } + } + + while ( empty-- != 0 ) { + lines[row++][col] = '.'; + } + + while ( stones-- != 0 ) { + lines[row++][col] = 'O'; + } + + while ( row != lines.size() && lines[row][col] == '#' ) { + ++row; + } + } + } +} + +void +tilt_west(vector& lines) +{ + for ( size_t row = 0; row != lines.size(); ++row ) { + size_t col = 0; + while ( col != lines[0].size() ) { + size_t stones = 0; + size_t empty = 0; + + for ( size_t idx = col; idx != lines[0].size() && lines[row][idx] != '#'; ++idx ) { + if ( lines[row][idx] == '.' ) { + ++empty; + } + if ( lines[row][idx] == 'O' ) { + ++stones; + } + } + + while ( stones-- != 0 ) { + lines[row][col++] = 'O'; + } + + while ( empty-- != 0 ) { + lines[row][col++] = '.'; + } + + while ( col != lines[0].size() && lines[row][col] == '#' ) { + ++col; + } + } + } +} + +void +tilt_east(vector& lines) +{ + for ( size_t row = 0; row != lines.size(); ++row ) { + size_t col = 0; + while ( col != lines[0].size() ) { + size_t stones = 0; + size_t empty = 0; + + for ( size_t idx = col; idx != lines[0].size() && lines[row][idx] != '#'; ++idx ) { + if ( lines[row][idx] == '.' ) { + ++empty; + } + if ( lines[row][idx] == 'O' ) { + ++stones; + } + } + + while ( empty-- != 0 ) { + lines[row][col++] = '.'; + } + + while ( stones-- != 0 ) { + lines[row][col++] = 'O'; + } + + while ( col != lines[0].size() && lines[row][col] == '#' ) { + ++col; + } + } + } +} + +void +tilt(vector& lines) +{ + for ( auto tilt: { tilt_north, tilt_west, tilt_south, tilt_east } ) { + tilt(lines); + } +} + +size_t +calc(const vector& lines) +{ + size_t sum = 0; + size_t counter = lines.size(); + for ( const auto& line: lines ) { + sum += counter * static_cast(count_if(line.begin(), line.end(), [](char chr) { return chr == 'O'; })); + --counter; + } + return sum; +} + +void +part2(vector lines) +{ + auto start = chrono::steady_clock::now(); + map, long> cache; + + const long dest = 1'000'000'000; + + for ( long index = 0;; ++index ) { + auto iter = cache.find(lines); + if ( iter != cache.end() ) { + auto offset = iter->second; + auto cycle_length = index - offset; + + auto moves_required = (dest - offset) % cycle_length; + + while ( moves_required-- != 0 ) { + tilt(lines); + } + + auto duration = chrono::duration_cast(chrono::steady_clock::now() - start).count(); + + cout << calc(lines) << " (" << duration << " ms)" << endl; + break; + } + else { + cache[lines] = index; + } + + tilt(lines); + } +} + +int +main() +{ + const auto lines = read_file("data/day14.txt"); + part1(lines); + part2(lines); +} -- cgit v1.3