start adding doctests
This commit is contained in:
parent
c3b3de5416
commit
e6f19d8ee3
49
2019/01.cpp
49
2019/01.cpp
|
@ -5,22 +5,57 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
auto fuel1(std::int64_t weight) -> std::int64_t {
|
||||||
|
return weight / 3 - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fuel2(std::int64_t weight) -> std::int64_t {
|
||||||
|
std::int64_t total = 0;
|
||||||
|
for(;;) {
|
||||||
|
weight = fuel1(weight);
|
||||||
|
if (weight <= 0) break;
|
||||||
|
total += weight;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUITE("documented examples") {
|
||||||
|
|
||||||
|
TEST_CASE("part 1") {
|
||||||
|
REQUIRE(fuel1(12) == 2);
|
||||||
|
REQUIRE(fuel1(14) == 2);
|
||||||
|
REQUIRE(fuel1(1969) == 654);
|
||||||
|
REQUIRE(fuel1(100756) == 33583);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("part 2") {
|
||||||
|
REQUIRE(fuel2(14) == 2);
|
||||||
|
REQUIRE(fuel2(1969) == 966);
|
||||||
|
REQUIRE(fuel2(100756) == 50346);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
auto& in = aocpp::Startup(argc, argv);
|
auto& in = aocpp::Startup(argc, argv);
|
||||||
auto fuel = [](std::int64_t& x) { return x=x/3-2; };
|
|
||||||
|
|
||||||
std::int64_t x;
|
std::int64_t weight;
|
||||||
std::int64_t part1 = 0;
|
std::int64_t part1 = 0;
|
||||||
std::int64_t part2 = 0;
|
std::int64_t part2 = 0;
|
||||||
|
|
||||||
while (in >> x) {
|
while (in >> weight) {
|
||||||
part1 += fuel(x);
|
part1 += fuel1(weight);
|
||||||
for (; x > 0; fuel(x)) {
|
part2 += fuel2(weight);
|
||||||
part2 += x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Part 1: " << part1 << std::endl;
|
std::cout << "Part 1: " << part1 << std::endl;
|
||||||
std::cout << "Part 2: " << part2 << std::endl;
|
std::cout << "Part 2: " << part2 << std::endl;
|
||||||
}
|
}
|
||||||
|
|
19
2019/02.cpp
19
2019/02.cpp
|
@ -1,9 +1,12 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
#include <intcode/intcode.hpp>
|
#include <intcode/intcode.hpp>
|
||||||
|
|
||||||
|
|
||||||
using namespace intcode;
|
using namespace intcode;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -17,6 +20,22 @@ auto Compute(Machine machine, ValueType x, ValueType y) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST_SUITE("documented examples") {
|
||||||
|
|
||||||
|
auto eval = [](std::vector<ValueType> program, std::vector<ValueType> output) {
|
||||||
|
Machine m{program};
|
||||||
|
REQUIRE(std::holds_alternative<Halt>(Step(m)));
|
||||||
|
REQUIRE(m.Dump() == output);
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("part 1") {
|
||||||
|
eval({1,0,0,0,99}, {2,0,0,0,99});
|
||||||
|
eval({2,3,0,3,99}, {2,3,0,6,99});
|
||||||
|
eval({2,4,4,5,99,0}, {2,4,4,5,99,9801});
|
||||||
|
eval({1,1,1,4,99,5,6,0,99}, {30,1,1,4,2,5,6,0,99});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||||
|
|
||||||
|
|
14
2019/06.cpp
14
2019/06.cpp
|
@ -5,6 +5,9 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
|
@ -74,6 +77,17 @@ auto Part2(std::map<std::string, std::string> const& parents) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST_SUITE("documented examples") {
|
||||||
|
TEST_CASE("part 1") {
|
||||||
|
std::istringstream in {"COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L\n"};
|
||||||
|
REQUIRE(Part1(Parse(in)) == 42);
|
||||||
|
}
|
||||||
|
TEST_CASE("part 2") {
|
||||||
|
std::istringstream in {"COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L\nK)YOU\nI)SAN\n"};
|
||||||
|
REQUIRE(Part2(Parse(in)) == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
auto parents = Parse(aocpp::Startup(argc, argv));
|
auto parents = Parse(aocpp::Startup(argc, argv));
|
||||||
std::cout << "Part 1: " << Part1(parents) << std::endl;
|
std::cout << "Part 1: " << Part1(parents) << std::endl;
|
||||||
|
|
34
2019/07.cpp
34
2019/07.cpp
|
@ -5,6 +5,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
#include <intcode/intcode.hpp>
|
#include <intcode/intcode.hpp>
|
||||||
using namespace intcode;
|
using namespace intcode;
|
||||||
|
@ -36,11 +38,11 @@ auto Feed(R &&s, ValueType start) -> std::optional<ValueType> {
|
||||||
return {start};
|
return {start};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compute1(Machine machine, std::vector<ValueType> const ¶ms)
|
auto Compute1(Machine machine, std::vector<ValueType> const ¶ms)
|
||||||
-> ValueType {
|
-> ValueType {
|
||||||
return *Feed(Controller(std::move(machine), params), 0);
|
return *Feed(Controller(std::move(machine), params), 0);
|
||||||
}
|
}
|
||||||
auto compute2(Machine machine, std::vector<ValueType> const ¶ms)
|
auto Compute2(Machine machine, std::vector<ValueType> const ¶ms)
|
||||||
-> ValueType {
|
-> ValueType {
|
||||||
auto amps = Controller(std::move(machine), params);
|
auto amps = Controller(std::move(machine), params);
|
||||||
ValueType last = 0;
|
ValueType last = 0;
|
||||||
|
@ -51,7 +53,7 @@ auto compute2(Machine machine, std::vector<ValueType> const ¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::invocable<Machine, std::vector<ValueType> const &> F>
|
template <std::invocable<Machine, std::vector<ValueType> const &> F>
|
||||||
auto optimize(Machine machine, std::vector<ValueType> params, F f) {
|
auto Optimize(Machine machine, std::vector<ValueType> params, F f) {
|
||||||
ValueType best = 0;
|
ValueType best = 0;
|
||||||
do {
|
do {
|
||||||
best = std::max(best, f(machine, params));
|
best = std::max(best, f(machine, params));
|
||||||
|
@ -59,10 +61,32 @@ auto optimize(Machine machine, std::vector<ValueType> params, F f) {
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Part1(Machine machine) -> ValueType {
|
||||||
|
return Optimize(std::move(machine), {0, 1, 2, 3, 4}, Compute1);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Part2(Machine machine) -> ValueType {
|
||||||
|
return Optimize(std::move(machine), {5, 6, 7, 8, 9}, Compute2);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST_SUITE("documented examples") {
|
||||||
|
TEST_CASE("part 1") {
|
||||||
|
auto eval = [](std::vector<ValueType> pgm) { return Part1(Machine{pgm}); };
|
||||||
|
REQUIRE(eval({3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0}) == 43210);
|
||||||
|
REQUIRE(eval({3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0}) == 54321);
|
||||||
|
REQUIRE(eval({3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0}) == 65210);
|
||||||
|
}
|
||||||
|
TEST_CASE("part 2") {
|
||||||
|
auto eval = [](std::vector<ValueType> pgm) { return Part2(Machine{pgm}); };
|
||||||
|
REQUIRE(eval({3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5}) == 139629729);
|
||||||
|
REQUIRE(eval({3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10})== 18216);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||||
std::cout << "Part 1: " << optimize(machine, {0, 1, 2, 3, 4}, compute1) << std::endl;
|
std::cout << "Part 1: " << Part1(machine) << std::endl;
|
||||||
std::cout << "Part 2: " << optimize(std::move(machine), {5, 6, 7, 8, 9}, compute2) << std::endl;
|
std::cout << "Part 2: " << Part2(std::move(machine)) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,13 @@ public:
|
||||||
/// @param offset from base pointer
|
/// @param offset from base pointer
|
||||||
/// @return reference to memory at given offset
|
/// @return reference to memory at given offset
|
||||||
auto Rel(std::size_t offset) -> ValueType &;
|
auto Rel(std::size_t offset) -> ValueType &;
|
||||||
|
auto Rel(std::size_t offset) const -> ValueType;
|
||||||
|
|
||||||
auto Next() -> ValueType &;
|
auto Next() -> ValueType &;
|
||||||
auto Goto(std::size_t address) -> void;
|
auto Goto(std::size_t address) -> void;
|
||||||
auto Rebase(std::size_t offset) -> void;
|
auto Rebase(std::size_t offset) -> void;
|
||||||
|
|
||||||
|
auto Dump() const -> std::vector<ValueType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -21,6 +21,10 @@ auto Machine::Rel(std::size_t const i) -> ValueType & {
|
||||||
return At(base_ + i);
|
return At(base_ + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Machine::Rel(std::size_t const i) const -> ValueType {
|
||||||
|
return At(base_ + i);
|
||||||
|
}
|
||||||
|
|
||||||
auto Machine::Rebase(std::size_t const offset) -> void {
|
auto Machine::Rebase(std::size_t const offset) -> void {
|
||||||
base_ += offset;
|
base_ += offset;
|
||||||
}
|
}
|
||||||
|
@ -33,4 +37,21 @@ auto Machine::Goto(std::size_t const address) -> void {
|
||||||
pc_ = address;
|
pc_ = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Machine::Dump() const -> std::vector<ValueType> {
|
||||||
|
if (ram_.empty()) { return rom_; }
|
||||||
|
|
||||||
|
std::size_t size = rom_.size();
|
||||||
|
for (auto const& [k,v] : ram_) {
|
||||||
|
if (k >= size) { size = k+1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ValueType> result(size);
|
||||||
|
std::copy(rom_.begin(), rom_.end(), result.begin());
|
||||||
|
for (auto const& [k,v] : ram_) {
|
||||||
|
result[k] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
7019
lib/include/doctest.h
Normal file
7019
lib/include/doctest.h
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -5,10 +5,18 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#define DOCTEST_CONFIG_IMPLEMENT
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
namespace aocpp {
|
namespace aocpp {
|
||||||
|
|
||||||
auto Startup(int argc, char ** argv) -> std::istream& {
|
auto Startup(int argc, char ** argv) -> std::istream& {
|
||||||
|
if (std::getenv("DOCTEST")) {
|
||||||
|
exit(doctest::Context{argc, argv}.run());
|
||||||
|
}
|
||||||
|
|
||||||
static std::ifstream fin;
|
static std::ifstream fin;
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 2: fin = std::ifstream{argv[1]}; return fin;
|
case 2: fin = std::ifstream{argv[1]}; return fin;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user