From cd4c32c2a3187f06acf88c2cd85d058c99f86b36 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 11:16:03 +0200 Subject: [PATCH 01/25] Initial set-up for 2019 AoC. --- 2019/.gitignore | 1 + 2019/CMakeLists.txt | 10 ++++++++++ 2019/src/day01.cpp | 35 +++++++++++++++++++++++++++++++++++ 2019/src/runner.cpp | 34 ++++++++++++++++++++++++++++++++++ 2019/src/solutions.cpp | 10 ++++++++++ 2019/src/solutions.hpp | 13 +++++++++++++ 6 files changed, 103 insertions(+) create mode 100644 2019/.gitignore create mode 100644 2019/CMakeLists.txt create mode 100644 2019/src/day01.cpp create mode 100644 2019/src/runner.cpp create mode 100644 2019/src/solutions.cpp create mode 100644 2019/src/solutions.hpp diff --git a/2019/.gitignore b/2019/.gitignore new file mode 100644 index 0000000..8eee68f --- /dev/null +++ b/2019/.gitignore @@ -0,0 +1 @@ +cmake-build-* diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt new file mode 100644 index 0000000..d321718 --- /dev/null +++ b/2019/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.15) + +project(aoc2019) + +add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) +target_compile_features(AoCSolutions PUBLIC cxx_std_17) + +add_executable(runner src/runner.cpp) +target_compile_features(runner PUBLIC cxx_std_17) +target_link_libraries(runner AoCSolutions) diff --git a/2019/src/day01.cpp b/2019/src/day01.cpp new file mode 100644 index 0000000..af57e58 --- /dev/null +++ b/2019/src/day01.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include "solutions.hpp" + +// Currently an implementation of 2018 day 1 +void aoc2019::day01_part1(std::istream &input, std::ostream &output) { + int sum = std::accumulate(std::istream_iterator(input), + std::istream_iterator(), + 0); + + output << sum << std::endl; +} + +void aoc2019::day01_part2(std::istream &input, std::ostream &output) { + std::vector drifts; + std::copy(std::istream_iterator(input), + std::istream_iterator(), + std::back_inserter(drifts)); + + int cur = 0; + std::unordered_set seen{cur}; + while (true) { + for (auto drift : drifts) { + cur += drift; + if (seen.count(cur) == 1) { + output << drift << std::endl; + return; + } else { + seen.insert(cur); + } + } + } +} diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp new file mode 100644 index 0000000..30543fd --- /dev/null +++ b/2019/src/runner.cpp @@ -0,0 +1,34 @@ +#include "solutions.hpp" +#include +#include +#include + +template +Int int_from_cstr(Int &value, const char *begin) { + const char *end = begin + std::strlen(begin); + auto result = std::from_chars(begin, end, value, Radix); + if (result.ec != std::errc()) { + throw std::invalid_argument("Unparseable integer"); + } + + return value; +} + +int main(int argc, const char *argv[]) { + if (argc < 2) { + std::cerr << "Specify a day to run.\n"; + return 1; + } + + int day; + int_from_cstr(day, argv[1]); + + const aoc2019::solution_t solution = aoc2019::get_implementation(day); + if (solution != nullptr) { + solution(std::cin, std::cout); + return 0; + } else { + std::cerr << "Unimplemented.\n"; + return 1; + } +} diff --git a/2019/src/solutions.cpp b/2019/src/solutions.cpp new file mode 100644 index 0000000..bb8fd0d --- /dev/null +++ b/2019/src/solutions.cpp @@ -0,0 +1,10 @@ +#include +#include "solutions.hpp" + +constexpr const std::array, 25> SOLUTIONS = { + {aoc2019::day01_part1, aoc2019::day01_part2} +}; + +aoc2019::solution_t aoc2019::get_implementation(int day, bool part2) { + return SOLUTIONS.at(day - 1).at((int) part2); +} diff --git a/2019/src/solutions.hpp b/2019/src/solutions.hpp new file mode 100644 index 0000000..7ac9747 --- /dev/null +++ b/2019/src/solutions.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace aoc2019 { + typedef void (*solution_t)(std::istream &, std::ostream &); + + solution_t get_implementation(int day, bool part2 = false); + + // Declarations of all implemented days. + void day01_part1(std::istream &input, std::ostream &output); + void day01_part2(std::istream &input, std::ostream &output); +} From 62f3e4c5de28349daa5b161b766317d7f19e64c9 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 11:43:46 +0200 Subject: [PATCH 02/25] Improve command line parser. --- 2019/CMakeLists.txt | 4 ++- 2019/src/runner.cpp | 60 ++++++++++++++++++++++++++++----------------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index d321718..f09fe54 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,9 +2,11 @@ cmake_minimum_required(VERSION 3.15) project(aoc2019) +find_package(Boost REQUIRED COMPONENTS program_options) + add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) target_compile_features(runner PUBLIC cxx_std_17) -target_link_libraries(runner AoCSolutions) +target_link_libraries(runner AoCSolutions Boost::program_options) diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index 30543fd..e07fb05 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -1,34 +1,48 @@ #include "solutions.hpp" #include -#include -#include +#include -template -Int int_from_cstr(Int &value, const char *begin) { - const char *end = begin + std::strlen(begin); - auto result = std::from_chars(begin, end, value, Radix); - if (result.ec != std::errc()) { - throw std::invalid_argument("Unparseable integer"); - } +namespace po = boost::program_options; - return value; +struct AoCOptions { + int day; + bool part2; +}; + +AoCOptions parse_options(const int argc, const char* argv[]) { + AoCOptions options{}; + po::options_description desc("Allowed options"); + desc.add_options() + ("day", po::value(&options.day)->required(), "The day to run.") + ("part2,2", po::bool_switch(&options.part2), "Whether to run part 2."); + + po::positional_options_description positionals; + positionals.add("day", 1); + + po::variables_map vm; + + po::store(po::command_line_parser(argc, argv).options(desc).positional(positionals).run(), vm); + po::notify(vm); + + return options; } int main(int argc, const char *argv[]) { - if (argc < 2) { - std::cerr << "Specify a day to run.\n"; + try { + const auto options = parse_options(argc, argv); + + const aoc2019::solution_t solution = aoc2019::get_implementation(options.day, options.part2); + if (solution != nullptr) { + solution(std::cin, std::cout); + return 0; + } else { + std::cerr << "Unimplemented.\n"; + return 1; + } + } catch (po::required_option &ignored) { return 1; - } - - int day; - int_from_cstr(day, argv[1]); - - const aoc2019::solution_t solution = aoc2019::get_implementation(day); - if (solution != nullptr) { - solution(std::cin, std::cout); - return 0; - } else { - std::cerr << "Unimplemented.\n"; + } catch (std::out_of_range &ignored) { + std::cerr << "Invalid day.\n"; return 1; } } From 944e595b971a5dc412c989a0d1f8898ef795a631 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:06:12 +0200 Subject: [PATCH 03/25] Wrong output variable. --- 2019/src/day01.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2019/src/day01.cpp b/2019/src/day01.cpp index af57e58..250339f 100644 --- a/2019/src/day01.cpp +++ b/2019/src/day01.cpp @@ -25,7 +25,7 @@ void aoc2019::day01_part2(std::istream &input, std::ostream &output) { for (auto drift : drifts) { cur += drift; if (seen.count(cur) == 1) { - output << drift << std::endl; + output << cur << std::endl; return; } else { seen.insert(cur); From 5cead82bee3c85b180784f9fd95cf487b90da26a Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:08:46 +0200 Subject: [PATCH 04/25] Add timing code. --- 2019/src/runner.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index e07fb05..7cf8004 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -1,4 +1,5 @@ #include "solutions.hpp" +#include #include #include @@ -7,14 +8,16 @@ namespace po = boost::program_options; struct AoCOptions { int day; bool part2; + bool run_timer; }; -AoCOptions parse_options(const int argc, const char* argv[]) { +static AoCOptions parse_options(const int argc, const char *argv[]) { AoCOptions options{}; po::options_description desc("Allowed options"); desc.add_options() ("day", po::value(&options.day)->required(), "The day to run.") - ("part2,2", po::bool_switch(&options.part2), "Whether to run part 2."); + ("part2,2", po::bool_switch(&options.part2), "Whether to run part 2.") + ("timer,t", po::bool_switch(&options.run_timer), "Show the execution time."); po::positional_options_description positionals; positionals.add("day", 1); @@ -33,7 +36,12 @@ int main(int argc, const char *argv[]) { const aoc2019::solution_t solution = aoc2019::get_implementation(options.day, options.part2); if (solution != nullptr) { + const auto start = std::chrono::high_resolution_clock::now(); solution(std::cin, std::cout); + if (options.run_timer) { + const std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; + std::cerr << "Time taken: " << duration.count() << "s\n"; + } return 0; } else { std::cerr << "Unimplemented.\n"; From 54c704a8219021217f8775f301cc7cb83bf4abfa Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:18:47 +0200 Subject: [PATCH 05/25] Cleaner runner. --- 2019/src/runner.cpp | 56 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index 7cf8004..5beefcb 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -6,51 +6,55 @@ namespace po = boost::program_options; struct AoCOptions { - int day; - bool part2; + aoc2019::solution_t implementation; bool run_timer; }; static AoCOptions parse_options(const int argc, const char *argv[]) { AoCOptions options{}; + int day; + bool part2; po::options_description desc("Allowed options"); desc.add_options() - ("day", po::value(&options.day)->required(), "The day to run.") - ("part2,2", po::bool_switch(&options.part2), "Whether to run part 2.") + ("day", po::value(&day)->required(), "The day to run.") + ("part2,2", po::bool_switch(&part2), "Whether to run part 2.") ("timer,t", po::bool_switch(&options.run_timer), "Show the execution time."); po::positional_options_description positionals; positionals.add("day", 1); - po::variables_map vm; + try { + po::variables_map vm; - po::store(po::command_line_parser(argc, argv).options(desc).positional(positionals).run(), vm); - po::notify(vm); + po::store(po::command_line_parser(argc, argv).options(desc).positional(positionals).run(), vm); + po::notify(vm); - return options; + options.implementation = aoc2019::get_implementation(day, part2); + + return options; + } catch (po::error &argument_error) { + std::cerr << argument_error.what() << std::endl; + std::exit(1); + } catch (std::out_of_range &) { + std::cerr << "Invalid day: " << day + << ".\n Valid range: [1, 25].\n"; + std::exit(1); + } } int main(int argc, const char *argv[]) { - try { - const auto options = parse_options(argc, argv); + const auto options = parse_options(argc, argv); - const aoc2019::solution_t solution = aoc2019::get_implementation(options.day, options.part2); - if (solution != nullptr) { - const auto start = std::chrono::high_resolution_clock::now(); - solution(std::cin, std::cout); - if (options.run_timer) { - const std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; - std::cerr << "Time taken: " << duration.count() << "s\n"; - } - return 0; - } else { - std::cerr << "Unimplemented.\n"; - return 1; + if (options.implementation != nullptr) { + const auto start = std::chrono::high_resolution_clock::now(); + options.implementation(std::cin, std::cout); + if (options.run_timer) { + const std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; + std::cerr << "Time taken: " << duration.count() << "s\n"; } - } catch (po::required_option &ignored) { - return 1; - } catch (std::out_of_range &ignored) { - std::cerr << "Invalid day.\n"; + return 0; + } else { + std::cerr << "Unimplemented.\n"; return 1; } } From a7587240c69bb8f91ffa5536db646777d854832d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:30:46 +0200 Subject: [PATCH 06/25] Update travis script for 2019. --- .travis.yml | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index f585909..48e8efd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,15 @@ -language: rust -rust: - - stable - - beta - - nightly - - 1.28.0 # Ubuntu Bionic and Xenial +language: cpp +dist: bionic +compiler: + - clang + - gcc -matrix: - allow_failures: - - rust: nightly - - rust: 1.28.0 - fast_finish: true - -cache: cargo # Custom directory, for the correct year before_script: - - cd 2018 + - cd 2019 -# After success on stable, run benchmark -after_success: - - if [ "$TRAVIS_RUST_VERSION" == "stable" ]; then - cargo bench; - fi +# CMake build +script: + - cmake . + - make From 11dd04ac828dd056416de1a912f7e43047233711 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:33:26 +0200 Subject: [PATCH 07/25] Relax CMake requirement. --- 2019/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index f09fe54..7492ad1 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.12) project(aoc2019) From 5585bce297dc268ef08afa5549a85af3d9399477 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 12:38:17 +0200 Subject: [PATCH 08/25] Add boost to build. --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 48e8efd..275187d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ before_script: - cd 2019 # CMake build -script: - - cmake . - - make +script: cmake . && make + +addons: + apt: + packages: + - libboost-program-options-dev From e26c90d54ad438424f317f5c7093c3500cf56f16 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 13:36:46 +0200 Subject: [PATCH 09/25] Add initial test set-up. --- .travis.yml | 1 + 2019/CMakeLists.txt | 10 +++++++++- 2019/tests/test_solutions.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 2019/tests/test_solutions.cpp diff --git a/.travis.yml b/.travis.yml index 275187d..1d6629a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,3 +16,4 @@ addons: apt: packages: - libboost-program-options-dev + - libboost-test-dev diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 7492ad1..90a4179 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) -find_package(Boost REQUIRED COMPONENTS program_options) +find_package(Boost REQUIRED COMPONENTS program_options unit_test_framework) add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) @@ -10,3 +10,11 @@ target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) target_compile_features(runner PUBLIC cxx_std_17) target_link_libraries(runner AoCSolutions Boost::program_options) + +add_executable(test_solutions tests/test_solutions.cpp) +target_compile_features(test_solutions PUBLIC cxx_std_17) +target_link_libraries(test_solutions AoCSolutions Boost::unit_test_framework) +target_include_directories(test_solutions PRIVATE ${CMAKE_SOURCE_DIR}/src) + +enable_testing() +add_test(test_solutions test_solutions) diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp new file mode 100644 index 0000000..c0ddf7a --- /dev/null +++ b/2019/tests/test_solutions.cpp @@ -0,0 +1,24 @@ +#define BOOST_TEST_MODULE solutions_tests + +#include +#include +#include "solutions.hpp" + +static std::string run_day1_part1(std::string_view input) { + std::stringstream input_stream; + input_stream.write(input.data(), input.size()); + + std::stringstream output_stream; + + aoc2019::day01_part1(input_stream, output_stream); + return output_stream.str(); +} + +BOOST_AUTO_TEST_CASE(sample_day1_part1) +{ + BOOST_TEST(run_day1_part1("+1\n-2\n+3\n+1") == "3\n"); + BOOST_TEST(run_day1_part1("+1\n+1\n+1") == "3\n"); + BOOST_TEST(run_day1_part1("+1\n+1\n-2") == "0\n"); +} + + From 4e5b3b5a15ab89464913ae31cb5b946403ffb2da Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 14:51:17 +0200 Subject: [PATCH 10/25] Implement generic testing for 2019. This method reads a specific directory and applies all inputs there to their proper implementation. --- .travis.yml | 2 +- 2019/CMakeLists.txt | 6 ++-- 2019/tests/samples/01-1-1.in | 4 +++ 2019/tests/samples/01-1-1.out | 1 + 2019/tests/samples/01-1-2.in | 3 ++ 2019/tests/samples/01-1-2.out | 1 + 2019/tests/samples/01-1-3.in | 3 ++ 2019/tests/samples/01-1-3.out | 1 + 2019/tests/samples/01-1-4.in | 3 ++ 2019/tests/samples/01-1-4.out | 1 + 2019/tests/test_solutions.cpp | 53 +++++++++++++++++++++++++++-------- 11 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 2019/tests/samples/01-1-1.in create mode 100644 2019/tests/samples/01-1-1.out create mode 100644 2019/tests/samples/01-1-2.in create mode 100644 2019/tests/samples/01-1-2.out create mode 100644 2019/tests/samples/01-1-3.in create mode 100644 2019/tests/samples/01-1-3.out create mode 100644 2019/tests/samples/01-1-4.in create mode 100644 2019/tests/samples/01-1-4.out diff --git a/.travis.yml b/.travis.yml index 1d6629a..99b9dda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_script: - cd 2019 # CMake build -script: cmake . && make +script: cmake . && make && ./test_solutions addons: apt: diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 90a4179..2c30c6f 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -14,7 +14,9 @@ target_link_libraries(runner AoCSolutions Boost::program_options) add_executable(test_solutions tests/test_solutions.cpp) target_compile_features(test_solutions PUBLIC cxx_std_17) target_link_libraries(test_solutions AoCSolutions Boost::unit_test_framework) -target_include_directories(test_solutions PRIVATE ${CMAKE_SOURCE_DIR}/src) +target_include_directories(test_solutions PRIVATE "${CMAKE_SOURCE_DIR}/src") enable_testing() -add_test(test_solutions test_solutions) +add_test(NAME test_solutions + COMMAND test_solutions + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests") diff --git a/2019/tests/samples/01-1-1.in b/2019/tests/samples/01-1-1.in new file mode 100644 index 0000000..9205ed4 --- /dev/null +++ b/2019/tests/samples/01-1-1.in @@ -0,0 +1,4 @@ ++1 +-2 ++3 ++1 diff --git a/2019/tests/samples/01-1-1.out b/2019/tests/samples/01-1-1.out new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/2019/tests/samples/01-1-1.out @@ -0,0 +1 @@ +3 diff --git a/2019/tests/samples/01-1-2.in b/2019/tests/samples/01-1-2.in new file mode 100644 index 0000000..5d703f6 --- /dev/null +++ b/2019/tests/samples/01-1-2.in @@ -0,0 +1,3 @@ ++1 ++1 ++1 diff --git a/2019/tests/samples/01-1-2.out b/2019/tests/samples/01-1-2.out new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/2019/tests/samples/01-1-2.out @@ -0,0 +1 @@ +3 diff --git a/2019/tests/samples/01-1-3.in b/2019/tests/samples/01-1-3.in new file mode 100644 index 0000000..399f99d --- /dev/null +++ b/2019/tests/samples/01-1-3.in @@ -0,0 +1,3 @@ ++1 ++1 +-2 diff --git a/2019/tests/samples/01-1-3.out b/2019/tests/samples/01-1-3.out new file mode 100644 index 0000000..573541a --- /dev/null +++ b/2019/tests/samples/01-1-3.out @@ -0,0 +1 @@ +0 diff --git a/2019/tests/samples/01-1-4.in b/2019/tests/samples/01-1-4.in new file mode 100644 index 0000000..5be202d --- /dev/null +++ b/2019/tests/samples/01-1-4.in @@ -0,0 +1,3 @@ +-1 +-2 +-3 diff --git a/2019/tests/samples/01-1-4.out b/2019/tests/samples/01-1-4.out new file mode 100644 index 0000000..3cfb5ef --- /dev/null +++ b/2019/tests/samples/01-1-4.out @@ -0,0 +1 @@ +-6 diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index c0ddf7a..464e10b 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -1,24 +1,53 @@ #define BOOST_TEST_MODULE solutions_tests +#include +#include #include +#include #include +#include #include "solutions.hpp" -static std::string run_day1_part1(std::string_view input) { - std::stringstream input_stream; - input_stream.write(input.data(), input.size()); +std::vector get_samples() { + std::vector samples; + for (auto entry : std::filesystem::directory_iterator("./samples")) { + if (entry.path().filename().extension() == ".in") { + samples.push_back(entry.path().string()); + } + } - std::stringstream output_stream; - - aoc2019::day01_part1(input_stream, output_stream); - return output_stream.str(); + return samples; } -BOOST_AUTO_TEST_CASE(sample_day1_part1) -{ - BOOST_TEST(run_day1_part1("+1\n-2\n+3\n+1") == "3\n"); - BOOST_TEST(run_day1_part1("+1\n+1\n+1") == "3\n"); - BOOST_TEST(run_day1_part1("+1\n+1\n-2") == "0\n"); +static std::string read_file(const std::string &file_name) { + std::ifstream file(file_name); + return std::string(std::istreambuf_iterator(file), + std::istreambuf_iterator()); } +static void test_solution_impl(const std::string &input_name) { + std::regex name_parser("/(\\d{2})-(1|2).*\\.in$"); + std::smatch match; + // Sanity check, is this a parseable input file? + BOOST_TEST(std::regex_search(input_name, match, name_parser)); + const auto output_filename = input_name.substr(0, input_name.length() - 3) + ".out"; + const int day = std::atoi(match[1].str().c_str()); + const int part2 = match[2].str() == "2"; + + const auto desired_output = read_file(output_filename); + const auto implementation = aoc2019::get_implementation(day, part2); + + std::stringstream output_buffer; + std::ifstream input(input_name); + + implementation(input, output_buffer); + + BOOST_TEST(desired_output == output_buffer.str()); +} + +BOOST_DATA_TEST_CASE(test_solution, + boost::unit_test::data::make(get_samples()), + input_name) { + test_solution_impl(input_name); +} From ab91276fca437bf76d87b8d08a1672971d1c53cd Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 12 Sep 2019 14:59:24 +0200 Subject: [PATCH 11/25] Replace std::filesystem with boost::filesystem. Somehow, travis still doesn't support the right one. --- .travis.yml | 3 ++- 2019/CMakeLists.txt | 4 ++-- 2019/tests/test_solutions.cpp | 5 ++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 99b9dda..cd0dd7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,10 +10,11 @@ before_script: - cd 2019 # CMake build -script: cmake . && make && ./test_solutions +script: cmake . && make && make test addons: apt: packages: + - libboost-filesystem-dev - libboost-program-options-dev - libboost-test-dev diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 2c30c6f..d8c7ad6 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) -find_package(Boost REQUIRED COMPONENTS program_options unit_test_framework) +find_package(Boost REQUIRED COMPONENTS program_options unit_test_framework filesystem) add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) @@ -13,7 +13,7 @@ target_link_libraries(runner AoCSolutions Boost::program_options) add_executable(test_solutions tests/test_solutions.cpp) target_compile_features(test_solutions PUBLIC cxx_std_17) -target_link_libraries(test_solutions AoCSolutions Boost::unit_test_framework) +target_link_libraries(test_solutions AoCSolutions Boost::unit_test_framework Boost::filesystem) target_include_directories(test_solutions PRIVATE "${CMAKE_SOURCE_DIR}/src") enable_testing() diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 464e10b..81e24fa 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -1,16 +1,15 @@ #define BOOST_TEST_MODULE solutions_tests -#include #include #include -#include +#include #include #include #include "solutions.hpp" std::vector get_samples() { std::vector samples; - for (auto entry : std::filesystem::directory_iterator("./samples")) { + for (const auto &entry : boost::filesystem::directory_iterator("./samples")) { if (entry.path().filename().extension() == ".in") { samples.push_back(entry.path().string()); } From 4f1ddec0027e024035ea039ec51ea888ddbba7e2 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 15 Sep 2019 13:12:00 +0200 Subject: [PATCH 12/25] Ensure the test order is consistent. --- 2019/tests/test_solutions.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 81e24fa..454043a 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -15,6 +15,9 @@ std::vector get_samples() { } } + // Ensure a consistent order. + std::sort(samples.begin(), samples.end()); + return samples; } From c046d5da01d85e5ec4757c05a42d0337ae49d0cd Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 15 Sep 2019 13:44:26 +0200 Subject: [PATCH 13/25] Restructure header files. This should prevent the tests from being recompiled. --- 2019/CMakeLists.txt | 2 +- 2019/src/day01.cpp | 2 +- 2019/src/{solutions.hpp => days.hpp} | 4 ---- 2019/src/{solutions.cpp => implementations.cpp} | 3 ++- 2019/src/implementations.hpp | 9 +++++++++ 2019/src/runner.cpp | 2 +- 2019/tests/test_solutions.cpp | 2 +- 7 files changed, 15 insertions(+), 9 deletions(-) rename 2019/src/{solutions.hpp => days.hpp} (63%) rename 2019/src/{solutions.cpp => implementations.cpp} (84%) create mode 100644 2019/src/implementations.hpp diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index d8c7ad6..7e17420 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -4,7 +4,7 @@ project(aoc2019) find_package(Boost REQUIRED COMPONENTS program_options unit_test_framework filesystem) -add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) +add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) diff --git a/2019/src/day01.cpp b/2019/src/day01.cpp index 250339f..a51511b 100644 --- a/2019/src/day01.cpp +++ b/2019/src/day01.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "solutions.hpp" +#include "days.hpp" // Currently an implementation of 2018 day 1 void aoc2019::day01_part1(std::istream &input, std::ostream &output) { diff --git a/2019/src/solutions.hpp b/2019/src/days.hpp similarity index 63% rename from 2019/src/solutions.hpp rename to 2019/src/days.hpp index 7ac9747..f511242 100644 --- a/2019/src/solutions.hpp +++ b/2019/src/days.hpp @@ -3,10 +3,6 @@ #include namespace aoc2019 { - typedef void (*solution_t)(std::istream &, std::ostream &); - - solution_t get_implementation(int day, bool part2 = false); - // Declarations of all implemented days. void day01_part1(std::istream &input, std::ostream &output); void day01_part2(std::istream &input, std::ostream &output); diff --git a/2019/src/solutions.cpp b/2019/src/implementations.cpp similarity index 84% rename from 2019/src/solutions.cpp rename to 2019/src/implementations.cpp index bb8fd0d..570aca2 100644 --- a/2019/src/solutions.cpp +++ b/2019/src/implementations.cpp @@ -1,5 +1,6 @@ #include -#include "solutions.hpp" +#include "days.hpp" +#include "implementations.hpp" constexpr const std::array, 25> SOLUTIONS = { {aoc2019::day01_part1, aoc2019::day01_part2} diff --git a/2019/src/implementations.hpp b/2019/src/implementations.hpp new file mode 100644 index 0000000..24e9820 --- /dev/null +++ b/2019/src/implementations.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace aoc2019 { + typedef void (*solution_t)(std::istream &, std::ostream &); + + solution_t get_implementation(int day, bool part2 = false); +} diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index 5beefcb..d47951c 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -1,4 +1,4 @@ -#include "solutions.hpp" +#include "implementations.hpp" #include #include #include diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 454043a..370412d 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "solutions.hpp" +#include "implementations.hpp" std::vector get_samples() { std::vector samples; From 02066bf54a586a3af12a036f0f63e409ebbfdbb1 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 15 Sep 2019 15:46:34 +0200 Subject: [PATCH 14/25] Add README and update general one. --- 2019/README.md | 6 ++++++ README.md | 1 + 2 files changed, 7 insertions(+) create mode 100644 2019/README.md diff --git a/2019/README.md b/2019/README.md new file mode 100644 index 0000000..c8bb59a --- /dev/null +++ b/2019/README.md @@ -0,0 +1,6 @@ +# Advent of Code 2019 + +This project contains my implementations for Advent of Code 2019. The +goal is to create reasonably fast C++ implementations in readable and +ergonomic C++. At the end of the contest, I will probably do a write- +up of some sorts. diff --git a/README.md b/README.md index 01b3570..f469c8c 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,4 @@ This repository contains my solutions for Advent of Code. See: - [2016 edition](./2016) - [2017 edition](./2017) - [2018 edition](./2018) +- [2019 edition](./2019) From 1f8e19c49b70340dc216b453fa7f162a5d9ca05e Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 17:13:31 +0200 Subject: [PATCH 15/25] Move to GTest for better integration. --- .travis.yml | 2 +- 2019/CMakeLists.txt | 11 ++-- 2019/tests/test_solutions.cpp | 98 ++++++++++++++++++++++------------- 3 files changed, 68 insertions(+), 43 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd0dd7a..643a033 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,4 @@ addons: packages: - libboost-filesystem-dev - libboost-program-options-dev - - libboost-test-dev + - libgtest-dev diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 7e17420..e58e7e4 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) -find_package(Boost REQUIRED COMPONENTS program_options unit_test_framework filesystem) +find_package(Boost REQUIRED COMPONENTS program_options filesystem) +find_package(GTest) add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) @@ -13,10 +14,10 @@ target_link_libraries(runner AoCSolutions Boost::program_options) add_executable(test_solutions tests/test_solutions.cpp) target_compile_features(test_solutions PUBLIC cxx_std_17) -target_link_libraries(test_solutions AoCSolutions Boost::unit_test_framework Boost::filesystem) +target_link_libraries(test_solutions AoCSolutions Boost::filesystem gtest gtest_main) +target_compile_definitions(test_solutions PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"") target_include_directories(test_solutions PRIVATE "${CMAKE_SOURCE_DIR}/src") enable_testing() -add_test(NAME test_solutions - COMMAND test_solutions - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests") +include(GoogleTest) +gtest_discover_tests(test_solutions) diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 370412d..399ff3c 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -1,15 +1,69 @@ #define BOOST_TEST_MODULE solutions_tests -#include +#include +#include #include #include -#include -#include +#include #include "implementations.hpp" -std::vector get_samples() { +class SolutionsTest : public testing::TestWithParam { +protected: + std::string input_data = ""; + std::string output_data = ""; + aoc2019::solution_t implementation = nullptr; + + // Read input data + void SetUp() override; + +private: + static void readToString(const std::string &name, std::string &target); +}; + +void SolutionsTest::SetUp() { + const auto input_name = GetParam(); + const auto output_name = input_name.substr(0, input_name.length() - 3) + ".out"; + + const char *base_name = input_name.c_str(); + if (const auto last_slash = input_name.rfind('/'); last_slash != std::string::npos) { + base_name += last_slash + 1; + } + + int day, part; + const auto read_result = std::sscanf(base_name, "%02d-%1d-", &day, &part); // NOLINT(cert-err34-c) + // Ensure that we've read the input files. + assert(read_result != 0); + + const bool part2 = part == 2; + implementation = aoc2019::get_implementation(day, part2); + + readToString(input_name, input_data); + readToString(output_name, output_data); +} + +void SolutionsTest::readToString(const std::string &name, std::string &target) { + std::ifstream source(name); + + target.assign(std::istreambuf_iterator(source), + std::istreambuf_iterator()); +} + +TEST_P(SolutionsTest, TestExpectedOutcome) { + std::stringstream input_buffer, output_buffer; + + // Sanity check, don't call null implementation + ASSERT_NE(implementation, nullptr); + + input_buffer.str(input_data); + + implementation(input_buffer, output_buffer); + + ASSERT_EQ(output_data, output_buffer.str()); +} + +static std::vector get_samples() { std::vector samples; - for (const auto &entry : boost::filesystem::directory_iterator("./samples")) { + for (const auto &entry : boost::filesystem::directory_iterator(TEST_SAMPLES_DIR)) { if (entry.path().filename().extension() == ".in") { samples.push_back(entry.path().string()); } @@ -21,35 +75,5 @@ std::vector get_samples() { return samples; } -static std::string read_file(const std::string &file_name) { - std::ifstream file(file_name); - return std::string(std::istreambuf_iterator(file), - std::istreambuf_iterator()); -} - -static void test_solution_impl(const std::string &input_name) { - std::regex name_parser("/(\\d{2})-(1|2).*\\.in$"); - std::smatch match; - // Sanity check, is this a parseable input file? - BOOST_TEST(std::regex_search(input_name, match, name_parser)); - - const auto output_filename = input_name.substr(0, input_name.length() - 3) + ".out"; - const int day = std::atoi(match[1].str().c_str()); - const int part2 = match[2].str() == "2"; - - const auto desired_output = read_file(output_filename); - const auto implementation = aoc2019::get_implementation(day, part2); - - std::stringstream output_buffer; - std::ifstream input(input_name); - - implementation(input, output_buffer); - - BOOST_TEST(desired_output == output_buffer.str()); -} - -BOOST_DATA_TEST_CASE(test_solution, - boost::unit_test::data::make(get_samples()), - input_name) { - test_solution_impl(input_name); -} +INSTANTIATE_TEST_CASE_P(InstantiatedSolutionsTest, SolutionsTest, + testing::ValuesIn(get_samples())); From 7219712be423a59f92bbd2ff6bd80a1f8a1f19dc Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 17:30:09 +0200 Subject: [PATCH 16/25] Improve GTest configuration. --- 2019/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index e58e7e4..6edf706 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) find_package(Boost REQUIRED COMPONENTS program_options filesystem) -find_package(GTest) +find_package(GTest REQUIRED) add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) @@ -12,12 +12,11 @@ add_executable(runner src/runner.cpp) target_compile_features(runner PUBLIC cxx_std_17) target_link_libraries(runner AoCSolutions Boost::program_options) -add_executable(test_solutions tests/test_solutions.cpp) -target_compile_features(test_solutions PUBLIC cxx_std_17) -target_link_libraries(test_solutions AoCSolutions Boost::filesystem gtest gtest_main) -target_compile_definitions(test_solutions PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"") -target_include_directories(test_solutions PRIVATE "${CMAKE_SOURCE_DIR}/src") +add_executable(unit_tests tests/test_solutions.cpp) +target_compile_features(unit_tests PUBLIC cxx_std_17) +target_link_libraries(unit_tests AoCSolutions Boost::filesystem GTest::GTest GTest::Main) +target_compile_definitions(unit_tests PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"") +target_include_directories(unit_tests PRIVATE "${CMAKE_SOURCE_DIR}/src") enable_testing() -include(GoogleTest) -gtest_discover_tests(test_solutions) +gtest_discover_tests(unit_tests) From c1dd06e65399a332f8ba09566e5d4fce4ddcd721 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 17:52:12 +0200 Subject: [PATCH 17/25] Build my own gtest. Since the bundled version doesn't have a shared library. --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 643a033..1be8373 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,19 @@ language: cpp dist: bionic +sudo: true compiler: - clang - gcc +# Install GTest properly since it is only available as a static library. +install: + - mkdir gtest_build + - pushd gtest_build + - cmake /usr/src/gtest -DBUILD_SHARED_LIBS=true + - make && sudo make install + - popd + # Custom directory, for the correct year before_script: - cd 2019 @@ -18,3 +27,7 @@ addons: - libboost-filesystem-dev - libboost-program-options-dev - libgtest-dev + +cache: + directories: + - /home/travis/gtest_build From 99c1522122a2f37ff1cb2c2780a487ccea0561e6 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 18:00:22 +0200 Subject: [PATCH 18/25] Don't soil build directory. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1be8373..30b1e30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,8 @@ compiler: # Install GTest properly since it is only available as a static library. install: - - mkdir gtest_build - - pushd gtest_build + - mkdir ~/gtest_build + - pushd ~/gtest_build - cmake /usr/src/gtest -DBUILD_SHARED_LIBS=true - make && sudo make install - popd From c7a7a98a39fd715cb6b924c23a76487d7f18a043 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 18:46:00 +0200 Subject: [PATCH 19/25] Rework test case names. --- 2019/README.md | 2 ++ 2019/tests/test_solutions.cpp | 59 ++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/2019/README.md b/2019/README.md index c8bb59a..dc723dd 100644 --- a/2019/README.md +++ b/2019/README.md @@ -1,5 +1,7 @@ # Advent of Code 2019 +[![Build Status](https://travis-ci.org/bertptrs/adventofcode.svg?branch=master)](https://travis-ci.org/bertptrs/adventofcode) + This project contains my implementations for Advent of Code 2019. The goal is to create reasonably fast C++ implementations in readable and ergonomic C++. At the end of the contest, I will probably do a write- diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 399ff3c..6a9cd6b 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -1,13 +1,17 @@ #define BOOST_TEST_MODULE solutions_tests #include -#include +#include +#include #include #include #include #include "implementations.hpp" class SolutionsTest : public testing::TestWithParam { +public: + static std::string nameInstantiatedTest(const testing::TestParamInfo ¶mInfo); + protected: std::string input_data = ""; std::string output_data = ""; @@ -18,23 +22,17 @@ protected: private: static void readToString(const std::string &name, std::string &target); + + static std::tuple parseInputName(const std::string &name); }; void SolutionsTest::SetUp() { const auto input_name = GetParam(); const auto output_name = input_name.substr(0, input_name.length() - 3) + ".out"; - const char *base_name = input_name.c_str(); - if (const auto last_slash = input_name.rfind('/'); last_slash != std::string::npos) { - base_name += last_slash + 1; - } - - int day, part; - const auto read_result = std::sscanf(base_name, "%02d-%1d-", &day, &part); // NOLINT(cert-err34-c) - // Ensure that we've read the input files. - assert(read_result != 0); - - const bool part2 = part == 2; + int day; + bool part2; + std::tie(day, part2, std::ignore) = parseInputName(input_name); implementation = aoc2019::get_implementation(day, part2); readToString(input_name, input_data); @@ -48,6 +46,38 @@ void SolutionsTest::readToString(const std::string &name, std::string &target) { std::istreambuf_iterator()); } +std::tuple SolutionsTest::parseInputName(const std::string &name) { + const char *base_name = name.c_str(); + if (const auto last_slash = name.rfind('/'); last_slash != std::string::npos) { + base_name += last_slash + 1; + } + int day, part; + auto res = std::from_chars(base_name, base_name + 2, day); + assert(res.ec == std::errc()); + res = std::from_chars(base_name + 3, base_name + 4, part); + assert(res.ec == std::errc()); + + return {day, part == 2, std::string(base_name + 5, std::strchr(base_name, '.'))}; +} + +std::string SolutionsTest::nameInstantiatedTest(const testing::TestParamInfo ¶mInfo) { + int day; + bool part2; + std::string sampleName; + + std::tie(day, part2, sampleName) = parseInputName(paramInfo.param); + + std::stringstream nameBuilder; + + nameBuilder << "Day" << day << "Part" << (part2 ? 2 : 1) << "Sample"; + + std::copy_if(sampleName.cbegin(), sampleName.cend(), std::ostream_iterator(nameBuilder), [](char c) { + return std::isalnum(c); + }); + + return nameBuilder.str(); +} + TEST_P(SolutionsTest, TestExpectedOutcome) { std::stringstream input_buffer, output_buffer; @@ -75,5 +105,6 @@ static std::vector get_samples() { return samples; } -INSTANTIATE_TEST_CASE_P(InstantiatedSolutionsTest, SolutionsTest, - testing::ValuesIn(get_samples())); +INSTANTIATE_TEST_CASE_P(DaysTest, SolutionsTest, + testing::ValuesIn(get_samples()), + SolutionsTest::nameInstantiatedTest); From 0130fedb61c409ce5b8dae61651653a5b5f28b9d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 18:48:43 +0200 Subject: [PATCH 20/25] Recreate gtest dir only if necessary. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 30b1e30..993a085 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ compiler: # Install GTest properly since it is only available as a static library. install: - - mkdir ~/gtest_build + - mkdir -p ~/gtest_build - pushd ~/gtest_build - cmake /usr/src/gtest -DBUILD_SHARED_LIBS=true - make && sudo make install From 4ba6fe48d1730c243423f80a7916fe8b8ee85071 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 19:06:03 +0200 Subject: [PATCH 21/25] Use recent GCC and Clang versions. --- .travis.yml | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 993a085..71dbe1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,27 @@ language: cpp dist: bionic sudo: true -compiler: - - clang - - gcc +matrix: + include: + - addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-bionic-8 + packages: + - clang-8 + - libc++-8-dev + - libc++abi-8-dev + - libboost-filesystem-dev + - libboost-program-options-dev + - libgtest-dev + env: + - MATRIX_EVAL="CC=clang-8 && CXX=clang++-8" + + +before_install: + - eval "$MATRIX_EVAL" # Install GTest properly since it is only available as a static library. install: @@ -20,14 +37,3 @@ before_script: # CMake build script: cmake . && make && make test - -addons: - apt: - packages: - - libboost-filesystem-dev - - libboost-program-options-dev - - libgtest-dev - -cache: - directories: - - /home/travis/gtest_build From 90b067ce0d9aaf5a2bb7bb56505ba163522a334d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 22 Sep 2019 19:43:42 +0200 Subject: [PATCH 22/25] Scratch running in travis. Modern C++ is too difficult to run in travis/ --- .travis.yml | 39 ----------------------------------- 2019/CMakeLists.txt | 6 +++--- 2019/README.md | 28 +++++++++++++++++++++++-- 2019/tests/test_solutions.cpp | 6 ++++-- 4 files changed, 33 insertions(+), 46 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 71dbe1d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: cpp -dist: bionic -sudo: true - -matrix: - include: - - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-bionic-8 - packages: - - clang-8 - - libc++-8-dev - - libc++abi-8-dev - - libboost-filesystem-dev - - libboost-program-options-dev - - libgtest-dev - env: - - MATRIX_EVAL="CC=clang-8 && CXX=clang++-8" - - -before_install: - - eval "$MATRIX_EVAL" - -# Install GTest properly since it is only available as a static library. -install: - - mkdir -p ~/gtest_build - - pushd ~/gtest_build - - cmake /usr/src/gtest -DBUILD_SHARED_LIBS=true - - make && sudo make install - - popd - -# Custom directory, for the correct year -before_script: - - cd 2019 - -# CMake build -script: cmake . && make && make test diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 6edf706..5dea4ae 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) -find_package(Boost REQUIRED COMPONENTS program_options filesystem) +find_package(Boost REQUIRED COMPONENTS program_options) find_package(GTest REQUIRED) add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) @@ -14,9 +14,9 @@ target_link_libraries(runner AoCSolutions Boost::program_options) add_executable(unit_tests tests/test_solutions.cpp) target_compile_features(unit_tests PUBLIC cxx_std_17) -target_link_libraries(unit_tests AoCSolutions Boost::filesystem GTest::GTest GTest::Main) +target_link_libraries(unit_tests AoCSolutions GTest::GTest GTest::Main) target_compile_definitions(unit_tests PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"") target_include_directories(unit_tests PRIVATE "${CMAKE_SOURCE_DIR}/src") enable_testing() -gtest_discover_tests(unit_tests) +gtest_discover_tests(unit_tests NO_PRETTY_VALUES) diff --git a/2019/README.md b/2019/README.md index dc723dd..160afe3 100644 --- a/2019/README.md +++ b/2019/README.md @@ -1,8 +1,32 @@ # Advent of Code 2019 -[![Build Status](https://travis-ci.org/bertptrs/adventofcode.svg?branch=master)](https://travis-ci.org/bertptrs/adventofcode) - This project contains my implementations for Advent of Code 2019. The goal is to create reasonably fast C++ implementations in readable and ergonomic C++. At the end of the contest, I will probably do a write- up of some sorts. + + +## How to compile + +Install the dependencies: + +- [GTest](https://github.com/google/googletest) **Note:** this project + by default tries to dynamically link GTest, and the Ubuntu packages + only provide a statically linked archive. You may need to compile it + for yourself. +- [Boost.Program_options](https://www.boost.org/doc/libs/1_71_0/doc/html/program_options.html) + +``` +mkdir build && cd build +cmake .. +make +``` + +You can then use the generated executable `runner`. + +## Running tests + +Tests can be executed with `make test`. The `tests` folder contains a +`samples` folder. This folder contains pairs of `XX-Y-something.in` and +`XX-Y-something.out`, which will be taken as the expected input and +output of the implementations. You can add your own samples to this mix. diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 6a9cd6b..620c003 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -2,9 +2,11 @@ #include #include +#include #include +#include +#include #include -#include #include #include "implementations.hpp" @@ -93,7 +95,7 @@ TEST_P(SolutionsTest, TestExpectedOutcome) { static std::vector get_samples() { std::vector samples; - for (const auto &entry : boost::filesystem::directory_iterator(TEST_SAMPLES_DIR)) { + for (const auto &entry : std::filesystem::directory_iterator(TEST_SAMPLES_DIR)) { if (entry.path().filename().extension() == ".in") { samples.push_back(entry.path().string()); } From 5b91fd4da3b3a7eafa76159741e67deb6c1c39c9 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Wed, 25 Sep 2019 12:56:57 +0200 Subject: [PATCH 23/25] No longer depend on Boost.program_options. --- 2019/CMakeLists.txt | 3 +- 2019/README.md | 1 - 2019/src/runner.cpp | 99 +++++++++++++++++++++++++++++++++------------ 3 files changed, 74 insertions(+), 29 deletions(-) diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index 5dea4ae..a679e78 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.12) project(aoc2019) -find_package(Boost REQUIRED COMPONENTS program_options) find_package(GTest REQUIRED) add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) @@ -10,7 +9,7 @@ target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) target_compile_features(runner PUBLIC cxx_std_17) -target_link_libraries(runner AoCSolutions Boost::program_options) +target_link_libraries(runner AoCSolutions) add_executable(unit_tests tests/test_solutions.cpp) target_compile_features(unit_tests PUBLIC cxx_std_17) diff --git a/2019/README.md b/2019/README.md index 160afe3..f857611 100644 --- a/2019/README.md +++ b/2019/README.md @@ -14,7 +14,6 @@ Install the dependencies: by default tries to dynamically link GTest, and the Ubuntu packages only provide a statically linked archive. You may need to compile it for yourself. -- [Boost.Program_options](https://www.boost.org/doc/libs/1_71_0/doc/html/program_options.html) ``` mkdir build && cd build diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index d47951c..c3f6b5a 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -1,45 +1,92 @@ #include "implementations.hpp" +#include #include #include -#include - -namespace po = boost::program_options; struct AoCOptions { aoc2019::solution_t implementation; bool run_timer; }; -static AoCOptions parse_options(const int argc, const char *argv[]) { +static AoCOptions parse_options(const int argc, const char* argv[]) { + using namespace std::string_view_literals; AoCOptions options{}; - int day; - bool part2; - po::options_description desc("Allowed options"); - desc.add_options() - ("day", po::value(&day)->required(), "The day to run.") - ("part2,2", po::bool_switch(&part2), "Whether to run part 2.") - ("timer,t", po::bool_switch(&options.run_timer), "Show the execution time."); - po::positional_options_description positionals; - positionals.add("day", 1); + auto show_help = [argv] (int exit_status = 0) { + std::cerr << "Usage: " << argv[0] << " [--timer|-t] [--part2|-2] [--help|-h] DAY\n" + << "\t--timer|-t: print execution time\n" + << "\t--part2|-2: run part 2\n" + << "\t --help|-h: show this message\n"; + std::exit(exit_status); + }; - try { - po::variables_map vm; + int day = -1; + bool part2 = false; - po::store(po::command_line_parser(argc, argv).options(desc).positional(positionals).run(), vm); - po::notify(vm); + // Here follows a manual implementation of getopt, since getopt doesn't work on windows… + for (int i = 1; i < argc; ++i) { + std::string_view arg(argv[i]); + if (arg[0] == '-') { + // Handle flag arguments + if (arg[1] != '-') { + // Shorthand flags + for (char c : arg.substr(1)) { + switch (c) { + case '2': + part2 = true; + break; - options.implementation = aoc2019::get_implementation(day, part2); + case 't': + options.run_timer = true; + break; - return options; - } catch (po::error &argument_error) { - std::cerr << argument_error.what() << std::endl; - std::exit(1); - } catch (std::out_of_range &) { - std::cerr << "Invalid day: " << day - << ".\n Valid range: [1, 25].\n"; - std::exit(1); + case 'h': + show_help(); + break; + + default: + std::cerr << "Unknown flag '" << c << "'.\n\n"; + show_help(1); + } + } + } else { + // Handle long form versions + if (arg == "--timer"sv) { + part2 = true; + } else if (arg == "--timer"sv) { + options.run_timer = true; + } else if (arg == "--help"sv) { + show_help(); + } else { + show_help(1); + } + } + } else { + if (day != -1) { + // Double date specification, bail. + show_help(1); + } + + // Try to parse the date number + if (auto res = std::from_chars(arg.data(), arg.data() + arg.size(), day); res.ec != std::errc()) { + auto error_code = std::make_error_code(res.ec); + std::cerr << error_code.message() << "\n\n"; + show_help(1); + } + } } + + if (day == -1) { + std::cerr << "Argument DAY is required.\n\n"; + show_help(1); + } else if (day < 1 || day > 25) { + std::cerr << "Invalid day. Valid range: [1, 25]\n"; + show_help(1); + } + + options.implementation = aoc2019::get_implementation(day, part2); + + return options; } int main(int argc, const char *argv[]) { From e9bf399af40524a5e0614f52b901745165d9b229 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 28 Nov 2019 08:00:46 +0100 Subject: [PATCH 24/25] Prepare all days skeletons. --- 2019/CMakeLists.txt | 3 ++- 2019/src/day01.cpp | 31 +++------------------- 2019/src/day02.cpp | 10 ++++++++ 2019/src/day03.cpp | 10 ++++++++ 2019/src/day04.cpp | 10 ++++++++ 2019/src/day05.cpp | 10 ++++++++ 2019/src/day06.cpp | 10 ++++++++ 2019/src/day07.cpp | 10 ++++++++ 2019/src/day08.cpp | 10 ++++++++ 2019/src/day09.cpp | 10 ++++++++ 2019/src/day10.cpp | 10 ++++++++ 2019/src/day11.cpp | 10 ++++++++ 2019/src/day12.cpp | 10 ++++++++ 2019/src/day13.cpp | 10 ++++++++ 2019/src/day14.cpp | 10 ++++++++ 2019/src/day15.cpp | 10 ++++++++ 2019/src/day16.cpp | 10 ++++++++ 2019/src/day17.cpp | 10 ++++++++ 2019/src/day18.cpp | 10 ++++++++ 2019/src/day19.cpp | 10 ++++++++ 2019/src/day20.cpp | 10 ++++++++ 2019/src/day21.cpp | 10 ++++++++ 2019/src/day22.cpp | 10 ++++++++ 2019/src/day23.cpp | 10 ++++++++ 2019/src/day24.cpp | 10 ++++++++ 2019/src/day25.cpp | 10 ++++++++ 2019/src/days.hpp | 48 +++++++++++++++++++++++++++++++++++ 2019/src/implementations.cpp | 30 +++++++++++++++++++--- 2019/tests/samples/.gitkeep | 1 + 2019/tests/samples/01-1-1.in | 4 --- 2019/tests/samples/01-1-1.out | 1 - 2019/tests/samples/01-1-2.in | 3 --- 2019/tests/samples/01-1-2.out | 1 - 2019/tests/samples/01-1-3.in | 3 --- 2019/tests/samples/01-1-3.out | 1 - 2019/tests/samples/01-1-4.in | 3 --- 2019/tests/samples/01-1-4.out | 1 - 37 files changed, 321 insertions(+), 49 deletions(-) create mode 100644 2019/src/day02.cpp create mode 100644 2019/src/day03.cpp create mode 100644 2019/src/day04.cpp create mode 100644 2019/src/day05.cpp create mode 100644 2019/src/day06.cpp create mode 100644 2019/src/day07.cpp create mode 100644 2019/src/day08.cpp create mode 100644 2019/src/day09.cpp create mode 100644 2019/src/day10.cpp create mode 100644 2019/src/day11.cpp create mode 100644 2019/src/day12.cpp create mode 100644 2019/src/day13.cpp create mode 100644 2019/src/day14.cpp create mode 100644 2019/src/day15.cpp create mode 100644 2019/src/day16.cpp create mode 100644 2019/src/day17.cpp create mode 100644 2019/src/day18.cpp create mode 100644 2019/src/day19.cpp create mode 100644 2019/src/day20.cpp create mode 100644 2019/src/day21.cpp create mode 100644 2019/src/day22.cpp create mode 100644 2019/src/day23.cpp create mode 100644 2019/src/day24.cpp create mode 100644 2019/src/day25.cpp create mode 100644 2019/tests/samples/.gitkeep delete mode 100644 2019/tests/samples/01-1-1.in delete mode 100644 2019/tests/samples/01-1-1.out delete mode 100644 2019/tests/samples/01-1-2.in delete mode 100644 2019/tests/samples/01-1-2.out delete mode 100644 2019/tests/samples/01-1-3.in delete mode 100644 2019/tests/samples/01-1-3.out delete mode 100644 2019/tests/samples/01-1-4.in delete mode 100644 2019/tests/samples/01-1-4.out diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index a679e78..1ee4f27 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -4,7 +4,8 @@ project(aoc2019) find_package(GTest REQUIRED) -add_library(AoCSolutions src/implementations.hpp src/implementations.cpp src/day01.cpp src/days.hpp) +file(GLOB DAYS_FILES src/day*.cpp) +add_library(AoCSolutions src/implementations.cpp "${DAYS_FILES}") target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) diff --git a/2019/src/day01.cpp b/2019/src/day01.cpp index a51511b..c4ff5e4 100644 --- a/2019/src/day01.cpp +++ b/2019/src/day01.cpp @@ -1,35 +1,10 @@ -#include -#include -#include -#include +#include #include "days.hpp" -// Currently an implementation of 2018 day 1 void aoc2019::day01_part1(std::istream &input, std::ostream &output) { - int sum = std::accumulate(std::istream_iterator(input), - std::istream_iterator(), - 0); - - output << sum << std::endl; + output << "Not implemented\n"; } void aoc2019::day01_part2(std::istream &input, std::ostream &output) { - std::vector drifts; - std::copy(std::istream_iterator(input), - std::istream_iterator(), - std::back_inserter(drifts)); - - int cur = 0; - std::unordered_set seen{cur}; - while (true) { - for (auto drift : drifts) { - cur += drift; - if (seen.count(cur) == 1) { - output << cur << std::endl; - return; - } else { - seen.insert(cur); - } - } - } + output << "Not implemented\n"; } diff --git a/2019/src/day02.cpp b/2019/src/day02.cpp new file mode 100644 index 0000000..5bb6abf --- /dev/null +++ b/2019/src/day02.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day02_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day02_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day03.cpp b/2019/src/day03.cpp new file mode 100644 index 0000000..dfc74de --- /dev/null +++ b/2019/src/day03.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day03_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day03_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day04.cpp b/2019/src/day04.cpp new file mode 100644 index 0000000..c9f113f --- /dev/null +++ b/2019/src/day04.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day04_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day04_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day05.cpp b/2019/src/day05.cpp new file mode 100644 index 0000000..af62105 --- /dev/null +++ b/2019/src/day05.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day05_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day05_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day06.cpp b/2019/src/day06.cpp new file mode 100644 index 0000000..52421fd --- /dev/null +++ b/2019/src/day06.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day06_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day06_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day07.cpp b/2019/src/day07.cpp new file mode 100644 index 0000000..603b222 --- /dev/null +++ b/2019/src/day07.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day07_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day07_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day08.cpp b/2019/src/day08.cpp new file mode 100644 index 0000000..03855f3 --- /dev/null +++ b/2019/src/day08.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day08_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day08_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day09.cpp b/2019/src/day09.cpp new file mode 100644 index 0000000..28f8285 --- /dev/null +++ b/2019/src/day09.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day09_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day09_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day10.cpp b/2019/src/day10.cpp new file mode 100644 index 0000000..391e112 --- /dev/null +++ b/2019/src/day10.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day10_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day10_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day11.cpp b/2019/src/day11.cpp new file mode 100644 index 0000000..508ed43 --- /dev/null +++ b/2019/src/day11.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day11_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day11_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day12.cpp b/2019/src/day12.cpp new file mode 100644 index 0000000..16cb2a8 --- /dev/null +++ b/2019/src/day12.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day12_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day12_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day13.cpp b/2019/src/day13.cpp new file mode 100644 index 0000000..39dd64c --- /dev/null +++ b/2019/src/day13.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day13_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day13_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day14.cpp b/2019/src/day14.cpp new file mode 100644 index 0000000..b0441a4 --- /dev/null +++ b/2019/src/day14.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day14_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day14_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day15.cpp b/2019/src/day15.cpp new file mode 100644 index 0000000..6fa383f --- /dev/null +++ b/2019/src/day15.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day15_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day15_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day16.cpp b/2019/src/day16.cpp new file mode 100644 index 0000000..61765e5 --- /dev/null +++ b/2019/src/day16.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day16_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day16_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day17.cpp b/2019/src/day17.cpp new file mode 100644 index 0000000..a979207 --- /dev/null +++ b/2019/src/day17.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day17_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day17_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day18.cpp b/2019/src/day18.cpp new file mode 100644 index 0000000..4783ee1 --- /dev/null +++ b/2019/src/day18.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day18_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day18_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day19.cpp b/2019/src/day19.cpp new file mode 100644 index 0000000..aa2248c --- /dev/null +++ b/2019/src/day19.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day19_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day19_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day20.cpp b/2019/src/day20.cpp new file mode 100644 index 0000000..bb8a3a7 --- /dev/null +++ b/2019/src/day20.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day20_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day20_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day21.cpp b/2019/src/day21.cpp new file mode 100644 index 0000000..89decc1 --- /dev/null +++ b/2019/src/day21.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day21_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day21_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day22.cpp b/2019/src/day22.cpp new file mode 100644 index 0000000..70e3852 --- /dev/null +++ b/2019/src/day22.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day22_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day22_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day23.cpp b/2019/src/day23.cpp new file mode 100644 index 0000000..383e9f5 --- /dev/null +++ b/2019/src/day23.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day23_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day23_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day24.cpp b/2019/src/day24.cpp new file mode 100644 index 0000000..632ed30 --- /dev/null +++ b/2019/src/day24.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day24_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day24_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/day25.cpp b/2019/src/day25.cpp new file mode 100644 index 0000000..0eb6ade --- /dev/null +++ b/2019/src/day25.cpp @@ -0,0 +1,10 @@ +#include +#include "days.hpp" + +void aoc2019::day25_part1(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} + +void aoc2019::day25_part2(std::istream &input, std::ostream &output) { + output << "Not implemented\n"; +} diff --git a/2019/src/days.hpp b/2019/src/days.hpp index f511242..f34ed64 100644 --- a/2019/src/days.hpp +++ b/2019/src/days.hpp @@ -6,4 +6,52 @@ namespace aoc2019 { // Declarations of all implemented days. void day01_part1(std::istream &input, std::ostream &output); void day01_part2(std::istream &input, std::ostream &output); + void day02_part1(std::istream &input, std::ostream &output); + void day02_part2(std::istream &input, std::ostream &output); + void day03_part1(std::istream &input, std::ostream &output); + void day03_part2(std::istream &input, std::ostream &output); + void day04_part1(std::istream &input, std::ostream &output); + void day04_part2(std::istream &input, std::ostream &output); + void day05_part1(std::istream &input, std::ostream &output); + void day05_part2(std::istream &input, std::ostream &output); + void day06_part1(std::istream &input, std::ostream &output); + void day06_part2(std::istream &input, std::ostream &output); + void day07_part1(std::istream &input, std::ostream &output); + void day07_part2(std::istream &input, std::ostream &output); + void day08_part1(std::istream &input, std::ostream &output); + void day08_part2(std::istream &input, std::ostream &output); + void day09_part1(std::istream &input, std::ostream &output); + void day09_part2(std::istream &input, std::ostream &output); + void day10_part1(std::istream &input, std::ostream &output); + void day10_part2(std::istream &input, std::ostream &output); + void day11_part1(std::istream &input, std::ostream &output); + void day11_part2(std::istream &input, std::ostream &output); + void day12_part1(std::istream &input, std::ostream &output); + void day12_part2(std::istream &input, std::ostream &output); + void day13_part1(std::istream &input, std::ostream &output); + void day13_part2(std::istream &input, std::ostream &output); + void day14_part1(std::istream &input, std::ostream &output); + void day14_part2(std::istream &input, std::ostream &output); + void day15_part1(std::istream &input, std::ostream &output); + void day15_part2(std::istream &input, std::ostream &output); + void day16_part1(std::istream &input, std::ostream &output); + void day16_part2(std::istream &input, std::ostream &output); + void day17_part1(std::istream &input, std::ostream &output); + void day17_part2(std::istream &input, std::ostream &output); + void day18_part1(std::istream &input, std::ostream &output); + void day18_part2(std::istream &input, std::ostream &output); + void day19_part1(std::istream &input, std::ostream &output); + void day19_part2(std::istream &input, std::ostream &output); + void day20_part1(std::istream &input, std::ostream &output); + void day20_part2(std::istream &input, std::ostream &output); + void day21_part1(std::istream &input, std::ostream &output); + void day21_part2(std::istream &input, std::ostream &output); + void day22_part1(std::istream &input, std::ostream &output); + void day22_part2(std::istream &input, std::ostream &output); + void day23_part1(std::istream &input, std::ostream &output); + void day23_part2(std::istream &input, std::ostream &output); + void day24_part1(std::istream &input, std::ostream &output); + void day24_part2(std::istream &input, std::ostream &output); + void day25_part1(std::istream &input, std::ostream &output); + void day25_part2(std::istream &input, std::ostream &output); } diff --git a/2019/src/implementations.cpp b/2019/src/implementations.cpp index 570aca2..9111331 100644 --- a/2019/src/implementations.cpp +++ b/2019/src/implementations.cpp @@ -2,9 +2,33 @@ #include "days.hpp" #include "implementations.hpp" -constexpr const std::array, 25> SOLUTIONS = { - {aoc2019::day01_part1, aoc2019::day01_part2} -}; +constexpr const std::array, 25> SOLUTIONS = {{ + {aoc2019::day01_part1, aoc2019::day01_part2}, + {aoc2019::day02_part1, aoc2019::day02_part2}, + {aoc2019::day03_part1, aoc2019::day03_part2}, + {aoc2019::day04_part1, aoc2019::day04_part2}, + {aoc2019::day05_part1, aoc2019::day05_part2}, + {aoc2019::day06_part1, aoc2019::day06_part2}, + {aoc2019::day07_part1, aoc2019::day07_part2}, + {aoc2019::day08_part1, aoc2019::day08_part2}, + {aoc2019::day09_part1, aoc2019::day09_part2}, + {aoc2019::day10_part1, aoc2019::day10_part2}, + {aoc2019::day11_part1, aoc2019::day11_part2}, + {aoc2019::day12_part1, aoc2019::day12_part2}, + {aoc2019::day13_part1, aoc2019::day13_part2}, + {aoc2019::day14_part1, aoc2019::day14_part2}, + {aoc2019::day15_part1, aoc2019::day15_part2}, + {aoc2019::day16_part1, aoc2019::day16_part2}, + {aoc2019::day17_part1, aoc2019::day17_part2}, + {aoc2019::day18_part1, aoc2019::day18_part2}, + {aoc2019::day19_part1, aoc2019::day19_part2}, + {aoc2019::day20_part1, aoc2019::day20_part2}, + {aoc2019::day21_part1, aoc2019::day21_part2}, + {aoc2019::day22_part1, aoc2019::day22_part2}, + {aoc2019::day23_part1, aoc2019::day23_part2}, + {aoc2019::day24_part1, aoc2019::day24_part2}, + {aoc2019::day25_part1, aoc2019::day25_part2}, +}}; aoc2019::solution_t aoc2019::get_implementation(int day, bool part2) { return SOLUTIONS.at(day - 1).at((int) part2); diff --git a/2019/tests/samples/.gitkeep b/2019/tests/samples/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/2019/tests/samples/.gitkeep @@ -0,0 +1 @@ + diff --git a/2019/tests/samples/01-1-1.in b/2019/tests/samples/01-1-1.in deleted file mode 100644 index 9205ed4..0000000 --- a/2019/tests/samples/01-1-1.in +++ /dev/null @@ -1,4 +0,0 @@ -+1 --2 -+3 -+1 diff --git a/2019/tests/samples/01-1-1.out b/2019/tests/samples/01-1-1.out deleted file mode 100644 index 00750ed..0000000 --- a/2019/tests/samples/01-1-1.out +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/2019/tests/samples/01-1-2.in b/2019/tests/samples/01-1-2.in deleted file mode 100644 index 5d703f6..0000000 --- a/2019/tests/samples/01-1-2.in +++ /dev/null @@ -1,3 +0,0 @@ -+1 -+1 -+1 diff --git a/2019/tests/samples/01-1-2.out b/2019/tests/samples/01-1-2.out deleted file mode 100644 index 00750ed..0000000 --- a/2019/tests/samples/01-1-2.out +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/2019/tests/samples/01-1-3.in b/2019/tests/samples/01-1-3.in deleted file mode 100644 index 399f99d..0000000 --- a/2019/tests/samples/01-1-3.in +++ /dev/null @@ -1,3 +0,0 @@ -+1 -+1 --2 diff --git a/2019/tests/samples/01-1-3.out b/2019/tests/samples/01-1-3.out deleted file mode 100644 index 573541a..0000000 --- a/2019/tests/samples/01-1-3.out +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/2019/tests/samples/01-1-4.in b/2019/tests/samples/01-1-4.in deleted file mode 100644 index 5be202d..0000000 --- a/2019/tests/samples/01-1-4.in +++ /dev/null @@ -1,3 +0,0 @@ --1 --2 --3 diff --git a/2019/tests/samples/01-1-4.out b/2019/tests/samples/01-1-4.out deleted file mode 100644 index 3cfb5ef..0000000 --- a/2019/tests/samples/01-1-4.out +++ /dev/null @@ -1 +0,0 @@ --6 From c63b962cb31ec4c2577a9466eb3848db402ab9b7 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 28 Nov 2019 08:09:37 +0100 Subject: [PATCH 25/25] Fix Clang incompatibility. std::strchar should return const pointer for const input but it doesn't. --- 2019/tests/test_solutions.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp index 620c003..ea870bc 100644 --- a/2019/tests/test_solutions.cpp +++ b/2019/tests/test_solutions.cpp @@ -1,5 +1,3 @@ -#define BOOST_TEST_MODULE solutions_tests - #include #include #include @@ -59,7 +57,7 @@ std::tuple SolutionsTest::parseInputName(const std::stri res = std::from_chars(base_name + 3, base_name + 4, part); assert(res.ec == std::errc()); - return {day, part == 2, std::string(base_name + 5, std::strchr(base_name, '.'))}; + return {day, part == 2, std::string(base_name + 5, (const char*) std::strchr(base_name, '.'))}; } std::string SolutionsTest::nameInstantiatedTest(const testing::TestParamInfo ¶mInfo) {