diff --git a/.idea/editor.xml b/.idea/editor.xml index 822bae1..b0d69ef 100644 --- a/.idea/editor.xml +++ b/.idea/editor.xml @@ -1,244 +1,483 @@ - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 0a294a1..bf8431e 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,6 +3,5 @@ - \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fca806..ecc22bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.29) -project(Advent-Of-Code-2024 VERSION 0.0.4) +cmake_minimum_required(VERSION 3.25) +project(Advent-Of-Code-2024 VERSION 0.0.5) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/commit.py b/commit.py index 440e164..1163498 100755 --- a/commit.py +++ b/commit.py @@ -25,7 +25,7 @@ ENVIRONMENT_DATA_LOCATION = USER_HOME / ".brett_scripts.env" if sys.platform.startswith("win"): CONFIG_FILE_DIRECTORY = Path(os.getenv('APPDATA') + "\BLT") - CONFIG_FILE_LOCATION = Path(CONFIG_FILE_DIRECTORY + "\commit_config.env") + CONFIG_FILE_LOCATION = Path(CONFIG_FILE_DIRECTORY + "\commit_config.json") else: XDG_CONFIG_HOME = os.environ.get('XDG_CONFIG_HOME') if XDG_CONFIG_HOME is None: @@ -36,7 +36,7 @@ else: if len(str(XDG_CONFIG_HOME)) == 0: XDG_CONFIG_HOME = USER_HOME CONFIG_FILE_DIRECTORY = XDG_CONFIG_HOME / "blt" - CONFIG_FILE_LOCATION = CONFIG_FILE_DIRECTORY / "commit_config.env" + CONFIG_FILE_LOCATION = CONFIG_FILE_DIRECTORY / "commit_config.json" class Config: def __init__(self): diff --git a/include/day7.h b/include/day7.h new file mode 100644 index 0000000..a352032 --- /dev/null +++ b/include/day7.h @@ -0,0 +1,24 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DAY7_H +#define DAY7_H + +void run_day7(); + +#endif //DAY7_H diff --git a/problems/day6/example b/problems/day6/example new file mode 100644 index 0000000..b60e466 --- /dev/null +++ b/problems/day6/example @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#..^..... +........#. +#......... +......#... \ No newline at end of file diff --git a/problems/day6/example_loop b/problems/day6/example_loop new file mode 100644 index 0000000..9963315 --- /dev/null +++ b/problems/day6/example_loop @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#.#^..... +........#. +#......... +......#... \ No newline at end of file diff --git a/src/day6.cpp b/src/day6.cpp index f358c51..291d776 100644 --- a/src/day6.cpp +++ b/src/day6.cpp @@ -26,17 +26,25 @@ #include #include #include +#include +template <> +struct std::hash +{ + std::size_t operator()(const blt::vec2i& s) const noexcept + { + blt::size_t seed = 0x5F2D0AB0; + seed ^= (seed << 6) + (seed >> 2) + 0xCDA44F00 + std::hash{}(s.x()); + seed ^= (seed << 6) + (seed >> 2) + 0xF1284DE9 + std::hash{}(s.y()); + return seed; + } +}; namespace day6 { - std::vector> map; - - blt::vec2i guard_pos; - int width, height; - int print_map() + int print_map(const std::vector>& map) { int unique = 0; for (const auto& line : map) @@ -44,23 +52,189 @@ namespace day6 for (const auto c : line) { BLT_TRACE_STREAM << c; - if (c == 'X' || c == '+' || c == '-' || c == '=' || c == '|' || c == '!') + if (c == 'X') unique++; } BLT_TRACE_STREAM << "\n"; } return unique; } -} -bool loops() -{ + blt::vec2i find_guard_pos(const std::vector>& map) + { + for (auto [i, line] : blt::enumerate(map)) + { + for (auto [j, c] : blt::enumerate(line)) + { + if (c == '^' || c == '>' || c == '<' || c == 'v') + return {j, i}; + } + } + BLT_ABORT("Unable to find guard!"); + } + struct point + { + blt::vec2i pos; + char dir; + + point(const blt::vec2i& pos, const char dir): pos(pos), dir(dir) + { + } + + friend std::size_t hash_value(const point& obj) + { + std::size_t seed = 0x5410391E; + seed ^= (seed << 6) + (seed >> 2) + 0x0CDB4CE0 + std::hash{}(obj.pos); + seed ^= (seed << 6) + (seed >> 2) + 0x3923C237 + static_cast(obj.dir); + return seed; + } + + friend bool operator==(const point& lhs, const point& rhs) + { + return lhs.pos == rhs.pos + && lhs.dir == rhs.dir; + } + + friend bool operator!=(const point& lhs, const point& rhs) + { + return !(lhs == rhs); + } + }; + + bool execute_step(const char guard, std::vector>& map, blt::vec2i& guard_pos) + { + switch (guard) + { + case '^': + if (guard_pos.y() - 1 < 0) + return false; + if (map[guard_pos.y() - 1][guard_pos.x()] != '#') + { + guard_pos -= blt::vec2i{0, 1}; + map[guard_pos.y()][guard_pos.x()] = '^'; + } + else + { + // guard_pos += blt::vec2i{1, 0}; + map[guard_pos.y()][guard_pos.x()] = '>'; + } + break; + case '>': + if (guard_pos.x() + 1 >= day6::width) + return false; + if (map[guard_pos.y()][guard_pos.x() + 1] != '#') + { + guard_pos += blt::vec2i{1, 0}; + map[guard_pos.y()][guard_pos.x()] = '>'; + } + else + { + // guard_pos += blt::vec2i{0, 1}; + map[guard_pos.y()][guard_pos.x()] = 'v'; + } + break; + case 'v': + if (guard_pos.y() + 1 >= day6::height) + return false; + if (map[guard_pos.y() + 1][guard_pos.x()] != '#') + { + guard_pos += blt::vec2i{0, 1}; + map[guard_pos.y()][guard_pos.x()] = 'v'; + } + else + { + // guard_pos -= blt::vec2i{1, 0}; + map[guard_pos.y()][guard_pos.x()] = '<'; + } + break; + case '<': + if (guard_pos.x() - 1 < 0) + return false; + if (map[guard_pos.y()][guard_pos.x() - 1] != '#') + { + guard_pos -= blt::vec2i{1, 0}; + map[guard_pos.y()][guard_pos.x()] = '<'; + } + else + { + // guard_pos -= blt::vec2i{0, 1}; + map[guard_pos.y()][guard_pos.x()] = '^'; + } + break; + default: + BLT_ERROR("Hey this shouldn't be possible! %c", guard); + BLT_TRACE(day6::print_map(map)); + std::exit(-1); + } + return true; + } + + bool loops(std::vector>& map) + { + blt::hashset_t paths; + blt::vec2i guard_pos = find_guard_pos(map); + + while (true) + { + const char guard = map[guard_pos.y()][guard_pos.x()]; + if (paths.contains({guard_pos, guard})) + return true; + paths.insert({guard_pos, guard}); + map[guard_pos.y()][guard_pos.x()] = 'X'; + if (!execute_step(guard, map, guard_pos)) + return false; + } + } + + void run_part1(std::vector> map) + { + blt::vec2i guard_pos = find_guard_pos(map); + + while (true) + { + const char guard = map[guard_pos.y()][guard_pos.x()]; + map[guard_pos.y()][guard_pos.x()] = 'X'; + if (!execute_step(guard, map, guard_pos)) + goto exit; + } + exit: + + const auto unique = print_map(map); + + BLT_TRACE("Unique Pos %d", unique); + } + + void run_part2(const std::vector>& map) + { + int loopy = 0; + for (int j = 0; j < height; j++) + { + for (int i = 0; i < width; i++) + { + if (map[j][i] != '^' && map[j][i] != '#') + { + auto copy = map; + copy[j][i] = '#'; + if (loops(copy)) + { + loopy++; + BLT_TRACE("found a loopy at %d %d", j, i); + // print_map(copy); + } + } + } + } + BLT_TRACE("Loopy %d", loopy); + } } void run_day6() { using namespace day6; + + std::vector> map; + auto file = blt::fs::getLinesFromFile("../problems/day6/input"); for (const auto& line : file) @@ -74,97 +248,6 @@ void run_day6() width = static_cast(map.begin()->size()); BLT_TRACE("Width %d Height %d", width, height); - for (auto [i, line] : blt::enumerate(map)) - { - for (auto [j, c] : blt::enumerate(line)) - { - if (c == '^') - { - guard_pos = {j, i}; - BLT_TRACE(guard_pos); - goto out; - } - } - } -out: - - while (true) - { - const char guard = map[guard_pos.y()][guard_pos.x()]; - map[guard_pos.y()][guard_pos.x()] = 'X'; - switch (guard) - { - case '^': - if (guard_pos.y() - 1 < 0) - goto exit; - if (map[guard_pos.y() - 1][guard_pos.x()] != '#') - { - map[guard_pos.y()][guard_pos.x()] = '|'; - guard_pos -= blt::vec2i{0, 1}; - map[guard_pos.y()][guard_pos.x()] = '^'; - }else - { - map[guard_pos.y()][guard_pos.x()] = '+'; - guard_pos += blt::vec2i{1, 0}; - map[guard_pos.y()][guard_pos.x()] = '>'; - } - break; - case '>': - if (guard_pos.x() + 1 >= width) - goto exit; - if (map[guard_pos.y()][guard_pos.x() + 1] != '#') - { - map[guard_pos.y()][guard_pos.x()] = '-'; - guard_pos += blt::vec2i{1, 0}; - map[guard_pos.y()][guard_pos.x()] = '>'; - }else - { - map[guard_pos.y()][guard_pos.x()] = '+'; - guard_pos += blt::vec2i{0, 1}; - map[guard_pos.y()][guard_pos.x()] = 'v'; - } - break; - case 'v': - if (guard_pos.y() + 1 >= height) - goto exit; - if (map[guard_pos.y() + 1][guard_pos.x()] != '#') - { - map[guard_pos.y()][guard_pos.x()] = '!'; - guard_pos += blt::vec2i{0, 1}; - map[guard_pos.y()][guard_pos.x()] = 'v'; - }else - { - map[guard_pos.y()][guard_pos.x()] = '+'; - guard_pos -= blt::vec2i{1, 0}; - map[guard_pos.y()][guard_pos.x()] = '<'; - } - break; - case '<': - if (guard_pos.x() - 1 < 0) - goto exit; - if (map[guard_pos.y()][guard_pos.x() - 1] != '#') - { - map[guard_pos.y()][guard_pos.x()] = '='; - guard_pos -= blt::vec2i{1, 0}; - map[guard_pos.y()][guard_pos.x()] = '<'; - }else - { - map[guard_pos.y()][guard_pos.x()] = '+'; - guard_pos -= blt::vec2i{0, 1}; - map[guard_pos.y()][guard_pos.x()] = '^'; - } - break; - default: - BLT_ERROR("Hey this shouldn't be possible! %c", guard); - BLT_TRACE(print_map()); - std::exit(-1); - break; - } - } -exit: - - const auto unique = print_map(); - - BLT_TRACE("Unique Pos %d", unique); - + run_part1(map); + run_part2(map); } diff --git a/src/day7.cpp b/src/day7.cpp new file mode 100644 index 0000000..230638e --- /dev/null +++ b/src/day7.cpp @@ -0,0 +1,33 @@ +/* + * + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void run_day7() +{ +} diff --git a/src/main.cpp b/src/main.cpp index 4846816..dadd448 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include int main(const int argc, const char** argv) { @@ -42,6 +43,9 @@ int main(const int argc, const char** argv) run_day6(); break; case 7: + run_day7(); + break; + case 8: break; default: BLT_INFO("%d is not a day", day);