From c4e76b391e97b99d641657da61dbeb0ce9683f72 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 8 Dec 2024 16:14:39 +0200 Subject: [PATCH] aoc2024: Implement day8 solution I did not feel like optimizing this one, so its a O(n^2) looking over every cell in the grid. Performs way faster than my optimized day6 solution tho :DD --- userspace/aoc2024/CMakeLists.txt | 1 + userspace/aoc2024/day8/CMakeLists.txt | 9 ++ userspace/aoc2024/day8/main.cpp | 166 ++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 userspace/aoc2024/day8/CMakeLists.txt create mode 100644 userspace/aoc2024/day8/main.cpp diff --git a/userspace/aoc2024/CMakeLists.txt b/userspace/aoc2024/CMakeLists.txt index f480b0e3..8f5bf874 100644 --- a/userspace/aoc2024/CMakeLists.txt +++ b/userspace/aoc2024/CMakeLists.txt @@ -6,6 +6,7 @@ set(AOC2024_PROJECTS day5 day6 day7 + day8 full ) diff --git a/userspace/aoc2024/day8/CMakeLists.txt b/userspace/aoc2024/day8/CMakeLists.txt new file mode 100644 index 00000000..0b9eadfa --- /dev/null +++ b/userspace/aoc2024/day8/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SOURCES + main.cpp +) + +add_executable(aoc2024_day8 ${SOURCES}) +banan_include_headers(aoc2024_day8 ban) +banan_link_library(aoc2024_day8 libc) + +install(TARGETS aoc2024_day8 OPTIONAL) diff --git a/userspace/aoc2024/day8/main.cpp b/userspace/aoc2024/day8/main.cpp new file mode 100644 index 00000000..9e7de0c9 --- /dev/null +++ b/userspace/aoc2024/day8/main.cpp @@ -0,0 +1,166 @@ +#include +#include + +#include +#include + +using i8 = int8_t; +using i16 = int16_t; +using i32 = int32_t; +using i64 = int64_t; + +using u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using u64 = uint64_t; + +struct Position +{ + u32 x, y; + + constexpr bool operator==(const Position& other) const + { + return x == other.x && y == other.y; + } +}; + +struct PositionHash +{ + constexpr BAN::hash_t operator()(Position state) const + { + return BAN::hash{}((u64)state.x << 32 | (u64)state.y); + } +}; + +static BAN::Vector> parse_input(FILE* fp) +{ + BAN::Vector> result; + + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), fp)) + { + if (!buffer[0] || buffer[0] == '\n') + break; + + const size_t row_len = strlen(buffer) - 1; + ASSERT(buffer[row_len] == '\n'); + + if (!result.empty()) + ASSERT(result.back().size() == row_len); + + BAN::Vector row; + MUST(row.resize(row_len)); + memcpy(row.data(), buffer, row_len); + + MUST(result.push_back(BAN::move(row))); + } + + return result; +} + +i64 part1(FILE* fp) +{ + auto input = parse_input(fp); + + BAN::HashSet antinodes; + + for (size_t y1 = 0; y1 < input.size(); y1++) + { + for (size_t x1 = 0; x1 < input[y1].size(); x1++) + { + if (input[y1][x1] == '.') + continue; + + for (size_t y2 = y1; y2 < input.size(); y2++) + { + for (size_t x2 = (y2 == y1) ? x1 + 1 : 0; x2 < input[y2].size(); x2++) + { + if (input[y2][x2] != input[y1][x1]) + continue; + + const size_t x_diff = x2 - x1; + const size_t y_diff = y2 - y1; + + auto antinode1 = Position { .x = (u32)(x1 - x_diff), .y = (u32)(y1 - y_diff) }; + if (antinode1.y < input.size() && antinode1.x < input[antinode1.y].size()) + MUST(antinodes.insert(antinode1)); + + auto antinode2 = Position { .x = (u32)(x2 + x_diff), .y = (u32)(y2 + y_diff) }; + if (antinode2.y < input.size() && antinode2.x < input[antinode2.y].size()) + MUST(antinodes.insert(antinode2)); + } + } + } + } + + return antinodes.size(); +} + +i64 part2(FILE* fp) +{ + auto input = parse_input(fp); + + BAN::HashSet antinodes; + + for (size_t y1 = 0; y1 < input.size(); y1++) + { + for (size_t x1 = 0; x1 < input[y1].size(); x1++) + { + if (input[y1][x1] == '.') + continue; + + for (size_t y2 = y1; y2 < input.size(); y2++) + { + for (size_t x2 = (y2 == y1) ? x1 + 1 : 0; x2 < input[y2].size(); x2++) + { + if (input[y2][x2] != input[y1][x1]) + continue; + + const size_t x_diff = x2 - x1; + const size_t y_diff = y2 - y1; + + for (size_t t = 0;; t++) + { + auto antinode = Position { .x = (u32)(x1 - t * x_diff), .y = (u32)(y1 - t * y_diff) }; + if (antinode.y >= input.size() || antinode.x >= input[antinode.y].size()) + break; + MUST(antinodes.insert(antinode)); + } + + for (size_t t = 0;; t++) + { + auto antinode = Position { .x = (u32)(x2 + t * x_diff), .y = (u32)(y2 + t * y_diff) }; + if (antinode.y >= input.size() || antinode.x >= input[antinode.y].size()) + break; + MUST(antinodes.insert(antinode)); + } + } + } + } + } + + return antinodes.size(); +} + +int main(int argc, char** argv) +{ + const char* file_path = "/usr/share/aoc2024/day8_input.txt"; + + if (argc >= 2) + file_path = argv[1]; + + FILE* fp = fopen(file_path, "r"); + if (fp == nullptr) + { + perror("fopen"); + return 1; + } + + printf("part1: %" PRId64 "\n", part1(fp)); + + fseek(fp, 0, SEEK_SET); + + printf("part2: %" PRId64 "\n", part2(fp)); + + fclose(fp); +}