diff --git a/CMakeLists.txt b/CMakeLists.txt index db86a9c..9d73e29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,33 @@ set(CMAKE_CXX_COMPILER /usr/bin/clang++-21) project(aoc25 VERSION 0.1.0 LANGUAGES C CXX) +# Helper to add AoC day targets and auto-copy any input files +function(aoc_add_day name src_dir) + # remaining args are source files + set(sources ${ARGN}) + + add_executable(${name} ${sources}) + set_target_properties(${name} PROPERTIES CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON) + # Use GCC toolchain compatibility for clang++-21 + target_compile_options(${name} PRIVATE --gcc-toolchain=/usr) + + # Gather common input files in the source directory + file(GLOB INPUT_FILES + "${src_dir}/*_input" + "${src_dir}/puzzle_input" + "${src_dir}/test_input" + ) + + foreach(f IN LISTS INPUT_FILES) + get_filename_component(fname ${f} NAME) + add_custom_command(TARGET ${name} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${f} $/${fname} + COMMENT "Copying ${fname} to build directory for ${name}" + ) + endforeach() +endfunction() + # Per-day subprojects (example: day1) add_subdirectory(day1) +add_subdirectory(day2) diff --git a/day1/CMakeLists.txt b/day1/CMakeLists.txt index 36ff4eb..623d629 100644 --- a/day1/CMakeLists.txt +++ b/day1/CMakeLists.txt @@ -1,11 +1,2 @@ -add_executable(day1 main.cpp) -set_target_properties(day1 PROPERTIES CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON) -# Use GCC 15's libstdc++ with Clang 21 -target_compile_options(day1 PRIVATE --gcc-toolchain=/usr) - -add_custom_command(TARGET day1 POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/day1_input - $/day1_input - COMMENT "Copying day1_input to build directory" -) + # Use top-level helper to add the target and copy input files + aoc_add_day(day1 "${CMAKE_CURRENT_SOURCE_DIR}" main.cpp) diff --git a/day1/main.cpp b/day1/main.cpp index 4397e8c..2c152fe 100644 --- a/day1/main.cpp +++ b/day1/main.cpp @@ -67,10 +67,6 @@ auto executeSafeCrack(const std::vector& dialRotations){ } } - - - - std::println("{} : {:3}, Dial now at: {:5} cnt: {}", curDial.direction, curDial.distance, dial, countZero); if (dial < 0){ std::cout << "Shit's fucked!\n"; @@ -86,7 +82,6 @@ auto executeSafeCrack(const std::vector& dialRotations){ } auto main(int, char**) -> int { - std::cout << "Hello, from aoc25 day1!!\n"; auto retval = parseRotations("day1_input"); std::vector testCase = { @@ -103,8 +98,7 @@ auto main(int, char**) -> int { {'L', 1000}, }; - if(retval) - { + if(retval) { auto realResult = executeSafeCrack(*retval); auto result = executeSafeCrack(testCase); std::println("Testcase result: {}", result); diff --git a/day2/CMakeLists.txt b/day2/CMakeLists.txt new file mode 100644 index 0000000..ebc71e2 --- /dev/null +++ b/day2/CMakeLists.txt @@ -0,0 +1,2 @@ + # Use top-level helper to add the target and copy input files + aoc_add_day(day2 "${CMAKE_CURRENT_SOURCE_DIR}" main.cpp) \ No newline at end of file diff --git a/day2/main.cpp b/day2/main.cpp new file mode 100644 index 0000000..81b0e45 --- /dev/null +++ b/day2/main.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include + +struct IDRange { + std::string leftRange; + std::string rightRange; +}; + +auto parseRanges(const std::string& filename) -> std::expected, std::string> { + std::ifstream inputF {filename}; + + if (!inputF){ + return std::unexpected{"Some file open error.\n"}; + } + std::vector idRanges{}; + + std::string bigString{}; + std::getline(inputF,bigString); + auto ranges = std::ranges::to>(std::views::split(bigString, ',')); + + for(const auto& range : ranges){ + auto subParts = std::ranges::to>(std::views::split(range, '-')); + idRanges.emplace_back(subParts[0], subParts[1]); + } + + inputF.close(); + + return std::move(idRanges); +} + + + +auto countDoubles(const std::vector& idRanges) { + long doubles{}; + for(const auto& rng : idRanges){ + //std::println("{}-{}", rng.leftRange, rng.rightRange); + for( long i = std::stol(rng.leftRange); i <= std::stol(rng.rightRange); i++){ + auto str_version = std::to_string(i) ; + auto str_len = str_version.size(); + //std::print("Checking {}. Length: {}", str_version, str_version.size()); + if (str_len % 2 == 0) { + //std::print(" Divisible by two, splitting..."); + std::string_view left_half = std::string_view(str_version).substr(0, str_len/2); + std::string_view right_half = std::string_view(str_version).substr(str_len/2, str_len); + //std::print("Halves: {}/{}",left_half, right_half); + if(left_half == right_half){ + //std::print(" EQUAL!"); + doubles += i; + } + } + //std::println(); + } + } + return doubles; +} + +auto main() -> int { + auto testCase = parseRanges("test_input"); + if(testCase) { + auto testResult = countDoubles(*testCase); + std::println("Testcase result: {}", testResult); + } + else{ + std::print("{}\n", testCase.error()); + } + + + auto realRanges = parseRanges("puzzle_input"); + if(realRanges) { + auto realResult = countDoubles(*realRanges); + std::println("Real result: {}", realResult); + } + else{ + std::print("{}\n", realRanges.error()); + } + + return 0; +} diff --git a/day2/puzzle_input b/day2/puzzle_input new file mode 100644 index 0000000..28ec75c --- /dev/null +++ b/day2/puzzle_input @@ -0,0 +1 @@ +9191906840-9191941337,7671-13230,2669677096-2669816099,2-12,229599-392092,48403409-48523311,96763-229430,1919163519-1919240770,74928-96389,638049-668065,34781-73835,736781-819688,831765539-831907263,5615884-5749554,14101091-14196519,7134383-7169141,413340-625418,849755289-849920418,7745350-7815119,16717-26267,4396832-4549887,87161544-87241541,4747436629-4747494891,335-549,867623-929630,53-77,1414-3089,940604-1043283,3444659-3500714,3629-7368,79-129,5488908-5597446,97922755-98097602,182-281,8336644992-8336729448,24-47,613-1077 \ No newline at end of file diff --git a/day2/test_input b/day2/test_input new file mode 100644 index 0000000..bd04584 --- /dev/null +++ b/day2/test_input @@ -0,0 +1 @@ +11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 \ No newline at end of file