mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
24
.travis.yml
24
.travis.yml
@@ -1,24 +0,0 @@
|
||||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
- 1.28.0 # Ubuntu Bionic and Xenial
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rust: nightly
|
||||
- rust: 1.28.0
|
||||
fast_finish: true
|
||||
|
||||
cache: cargo
|
||||
|
||||
# Custom directory, for the correct year
|
||||
before_script:
|
||||
- cd 2018
|
||||
|
||||
# After success on stable, run benchmark
|
||||
after_success:
|
||||
- if [ "$TRAVIS_RUST_VERSION" == "stable" ]; then
|
||||
cargo bench;
|
||||
fi
|
||||
1
2019/.gitignore
vendored
Normal file
1
2019/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cmake-build-*
|
||||
22
2019/CMakeLists.txt
Normal file
22
2019/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(aoc2019)
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
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)
|
||||
target_compile_features(runner PUBLIC cxx_std_17)
|
||||
target_link_libraries(runner AoCSolutions)
|
||||
|
||||
add_executable(unit_tests tests/test_solutions.cpp)
|
||||
target_compile_features(unit_tests PUBLIC cxx_std_17)
|
||||
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 NO_PRETTY_VALUES)
|
||||
31
2019/README.md
Normal file
31
2019/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 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.
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
```
|
||||
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.
|
||||
10
2019/src/day01.cpp
Normal file
10
2019/src/day01.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include "days.hpp"
|
||||
|
||||
void aoc2019::day01_part1(std::istream &input, std::ostream &output) {
|
||||
output << "Not implemented\n";
|
||||
}
|
||||
|
||||
void aoc2019::day01_part2(std::istream &input, std::ostream &output) {
|
||||
output << "Not implemented\n";
|
||||
}
|
||||
10
2019/src/day02.cpp
Normal file
10
2019/src/day02.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day03.cpp
Normal file
10
2019/src/day03.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day04.cpp
Normal file
10
2019/src/day04.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day05.cpp
Normal file
10
2019/src/day05.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day06.cpp
Normal file
10
2019/src/day06.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day07.cpp
Normal file
10
2019/src/day07.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day08.cpp
Normal file
10
2019/src/day08.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day09.cpp
Normal file
10
2019/src/day09.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day10.cpp
Normal file
10
2019/src/day10.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day11.cpp
Normal file
10
2019/src/day11.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day12.cpp
Normal file
10
2019/src/day12.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day13.cpp
Normal file
10
2019/src/day13.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day14.cpp
Normal file
10
2019/src/day14.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day15.cpp
Normal file
10
2019/src/day15.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day16.cpp
Normal file
10
2019/src/day16.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day17.cpp
Normal file
10
2019/src/day17.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day18.cpp
Normal file
10
2019/src/day18.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day19.cpp
Normal file
10
2019/src/day19.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day20.cpp
Normal file
10
2019/src/day20.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day21.cpp
Normal file
10
2019/src/day21.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day22.cpp
Normal file
10
2019/src/day22.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day23.cpp
Normal file
10
2019/src/day23.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day24.cpp
Normal file
10
2019/src/day24.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
10
2019/src/day25.cpp
Normal file
10
2019/src/day25.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#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";
|
||||
}
|
||||
57
2019/src/days.hpp
Normal file
57
2019/src/days.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
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);
|
||||
}
|
||||
35
2019/src/implementations.cpp
Normal file
35
2019/src/implementations.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <array>
|
||||
#include "days.hpp"
|
||||
#include "implementations.hpp"
|
||||
|
||||
constexpr const std::array<std::array<aoc2019::solution_t, 2>, 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);
|
||||
}
|
||||
9
2019/src/implementations.hpp
Normal file
9
2019/src/implementations.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace aoc2019 {
|
||||
typedef void (*solution_t)(std::istream &, std::ostream &);
|
||||
|
||||
solution_t get_implementation(int day, bool part2 = false);
|
||||
}
|
||||
107
2019/src/runner.cpp
Normal file
107
2019/src/runner.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "implementations.hpp"
|
||||
#include <charconv>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
struct AoCOptions {
|
||||
aoc2019::solution_t implementation;
|
||||
bool run_timer;
|
||||
};
|
||||
|
||||
static AoCOptions parse_options(const int argc, const char* argv[]) {
|
||||
using namespace std::string_view_literals;
|
||||
AoCOptions options{};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
int day = -1;
|
||||
bool part2 = false;
|
||||
|
||||
// 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;
|
||||
|
||||
case 't':
|
||||
options.run_timer = true;
|
||||
break;
|
||||
|
||||
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[]) {
|
||||
const auto options = parse_options(argc, argv);
|
||||
|
||||
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<double> 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;
|
||||
}
|
||||
}
|
||||
1
2019/tests/samples/.gitkeep
Normal file
1
2019/tests/samples/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
110
2019/tests/test_solutions.cpp
Normal file
110
2019/tests/test_solutions.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <charconv>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <gtest/gtest.h>
|
||||
#include "implementations.hpp"
|
||||
|
||||
class SolutionsTest : public testing::TestWithParam<std::string> {
|
||||
public:
|
||||
static std::string nameInstantiatedTest(const testing::TestParamInfo<SolutionsTest::ParamType> ¶mInfo);
|
||||
|
||||
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);
|
||||
|
||||
static std::tuple<int, bool, std::string> 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";
|
||||
|
||||
int day;
|
||||
bool part2;
|
||||
std::tie(day, part2, std::ignore) = parseInputName(input_name);
|
||||
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<char>(source),
|
||||
std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
std::tuple<int, bool, std::string> 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, (const char*) std::strchr(base_name, '.'))};
|
||||
}
|
||||
|
||||
std::string SolutionsTest::nameInstantiatedTest(const testing::TestParamInfo<SolutionsTest::ParamType> ¶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<char>(nameBuilder), [](char c) {
|
||||
return std::isalnum(c);
|
||||
});
|
||||
|
||||
return nameBuilder.str();
|
||||
}
|
||||
|
||||
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<std::string> get_samples() {
|
||||
std::vector<std::string> samples;
|
||||
for (const auto &entry : std::filesystem::directory_iterator(TEST_SAMPLES_DIR)) {
|
||||
if (entry.path().filename().extension() == ".in") {
|
||||
samples.push_back(entry.path().string());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure a consistent order.
|
||||
std::sort(samples.begin(), samples.end());
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DaysTest, SolutionsTest,
|
||||
testing::ValuesIn(get_samples()),
|
||||
SolutionsTest::nameInstantiatedTest);
|
||||
Reference in New Issue
Block a user