mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 05.
This commit is contained in:
@@ -12,7 +12,7 @@ add_executable(runner src/runner.cpp)
|
|||||||
target_compile_features(runner PUBLIC cxx_std_17)
|
target_compile_features(runner PUBLIC cxx_std_17)
|
||||||
target_link_libraries(runner AoCSolutions)
|
target_link_libraries(runner AoCSolutions)
|
||||||
|
|
||||||
add_executable(unit_tests tests/test_solutions.cpp)
|
add_executable(unit_tests tests/test_solutions.cpp tests/test_intcode.cpp)
|
||||||
target_compile_features(unit_tests PUBLIC cxx_std_17)
|
target_compile_features(unit_tests PUBLIC cxx_std_17)
|
||||||
target_link_libraries(unit_tests AoCSolutions 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_compile_definitions(unit_tests PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"")
|
||||||
|
|||||||
1
2019/inputs/05.txt
Normal file
1
2019/inputs/05.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3,225,1,225,6,6,1100,1,238,225,104,0,1102,27,28,225,1,113,14,224,1001,224,-34,224,4,224,102,8,223,223,101,7,224,224,1,224,223,223,1102,52,34,224,101,-1768,224,224,4,224,1002,223,8,223,101,6,224,224,1,223,224,223,1002,187,14,224,1001,224,-126,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,1102,54,74,225,1101,75,66,225,101,20,161,224,101,-54,224,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1101,6,30,225,2,88,84,224,101,-4884,224,224,4,224,1002,223,8,223,101,2,224,224,1,224,223,223,1001,214,55,224,1001,224,-89,224,4,224,102,8,223,223,1001,224,4,224,1,224,223,223,1101,34,69,225,1101,45,67,224,101,-112,224,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1102,9,81,225,102,81,218,224,101,-7290,224,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,1101,84,34,225,1102,94,90,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,677,677,224,102,2,223,223,1005,224,329,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,344,101,1,223,223,1008,677,677,224,102,2,223,223,1005,224,359,101,1,223,223,8,226,677,224,1002,223,2,223,1006,224,374,101,1,223,223,108,226,677,224,1002,223,2,223,1006,224,389,1001,223,1,223,1107,226,677,224,102,2,223,223,1005,224,404,1001,223,1,223,7,226,677,224,1002,223,2,223,1005,224,419,101,1,223,223,1107,677,226,224,102,2,223,223,1006,224,434,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,449,101,1,223,223,1108,226,226,224,1002,223,2,223,1005,224,464,101,1,223,223,8,677,226,224,102,2,223,223,1005,224,479,101,1,223,223,8,226,226,224,1002,223,2,223,1006,224,494,1001,223,1,223,1007,226,677,224,1002,223,2,223,1006,224,509,1001,223,1,223,108,226,226,224,1002,223,2,223,1006,224,524,1001,223,1,223,1108,677,226,224,102,2,223,223,1006,224,539,101,1,223,223,1008,677,226,224,102,2,223,223,1006,224,554,101,1,223,223,107,226,677,224,1002,223,2,223,1006,224,569,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,584,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,599,101,1,223,223,1008,226,226,224,1002,223,2,223,1005,224,614,1001,223,1,223,107,226,226,224,1002,223,2,223,1005,224,629,101,1,223,223,7,226,226,224,102,2,223,223,1006,224,644,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,659,101,1,223,223,108,677,677,224,102,2,223,223,1005,224,674,1001,223,1,223,4,223,99,226
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "days.hpp"
|
#include "days.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
void aoc2019::day05_part1(std::istream &input, std::ostream &output) {
|
void aoc2019::day05_part1(std::istream &input, std::ostream &output) {
|
||||||
output << "Not implemented\n";
|
auto program = read_intcode(input);
|
||||||
|
auto result = aoc2019::run_intcode(program, { 1 });
|
||||||
|
output << result.back() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aoc2019::day05_part2(std::istream &input, std::ostream &output) {
|
void aoc2019::day05_part2(std::istream &input, std::ostream &output) {
|
||||||
output << "Not implemented\n";
|
auto program = read_intcode(input);
|
||||||
|
auto result = run_intcode(program, { 5 });
|
||||||
|
output << result.back() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
std::string_view aoc2019::strtok(std::string_view &str, char token) {
|
std::string_view aoc2019::strtok(std::string_view &str, char token) {
|
||||||
@@ -10,3 +11,105 @@ std::string_view aoc2019::strtok(std::string_view &str, char token) {
|
|||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> aoc2019::run_intcode(std::vector<int> &program, std::deque<int> inputs) {
|
||||||
|
std::vector<int> outputs{};
|
||||||
|
int ip = 0;
|
||||||
|
auto interpret_value = [&program, &ip](int pos) {
|
||||||
|
bool immediate = false;
|
||||||
|
switch (pos) {
|
||||||
|
case 1:
|
||||||
|
immediate = program[ip] / 100 % 10;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
immediate = program[ip] / 1000 % 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
immediate = program[ip] / 10000 % 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::out_of_range("Invalid position");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (immediate) {
|
||||||
|
return program[ip + pos];
|
||||||
|
} else {
|
||||||
|
return program[program[ip + pos]];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (ip < program.size()) {
|
||||||
|
switch (program[ip] % 100) {
|
||||||
|
case 1:
|
||||||
|
program[program[ip + 3]] = interpret_value(1) + interpret_value(2);
|
||||||
|
ip += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
program[program[ip + 3]] = interpret_value(1) * interpret_value(2);
|
||||||
|
ip += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (inputs.empty()) {
|
||||||
|
throw std::out_of_range("No inputs left");
|
||||||
|
}
|
||||||
|
program[program[ip + 1]] = inputs.front();
|
||||||
|
inputs.pop_front();
|
||||||
|
ip += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
outputs.push_back(interpret_value(1));
|
||||||
|
ip += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // Jump if non-zero
|
||||||
|
if (interpret_value(1)) {
|
||||||
|
ip = interpret_value(2);
|
||||||
|
} else {
|
||||||
|
ip += 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // Jump if zero
|
||||||
|
if (!interpret_value(1)) {
|
||||||
|
ip = interpret_value(2);
|
||||||
|
} else {
|
||||||
|
ip += 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // equality
|
||||||
|
program[program[ip + 3]] = interpret_value(1) < interpret_value(2);
|
||||||
|
ip += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: // less than
|
||||||
|
program[program[ip + 3]] = interpret_value(1) == interpret_value(2) ? 1 : 0;
|
||||||
|
ip += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 99:
|
||||||
|
return outputs;
|
||||||
|
|
||||||
|
default:
|
||||||
|
char buffer[30];
|
||||||
|
std::snprintf(buffer, sizeof(buffer), "Invalid opcode: %d", program[ip]);
|
||||||
|
|
||||||
|
throw std::domain_error(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw std::out_of_range("Program read out of bounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> aoc2019::read_intcode(std::istream &input) {
|
||||||
|
std::vector<int> program{};
|
||||||
|
for (int current; input >> current; input.ignore()) {
|
||||||
|
program.push_back(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,22 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
#include <deque>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iosfwd>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace aoc2019 {
|
namespace aoc2019 {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::from_chars_result from_chars(std::string_view str, T& value) {
|
inline std::from_chars_result from_chars(std::string_view str, T &value) {
|
||||||
return std::from_chars(str.data(), str.data() + str.size(), value);
|
return std::from_chars(str.data(), str.data() + str.size(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void combine_hash(std::size_t& seed, const T& o) {
|
void combine_hash(std::size_t &seed, const T &o) {
|
||||||
// Algorithm taken from boost::combine_hash.
|
// Algorithm taken from boost::combine_hash.
|
||||||
std::hash<T> hash{};
|
std::hash<T> hash{};
|
||||||
seed ^= hash(o) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
seed ^= hash(o) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view strtok(std::string_view &str, char token = ',');
|
std::string_view strtok(std::string_view &str, char token = ',');
|
||||||
|
|
||||||
|
std::vector<int> read_intcode(std::istream &input);
|
||||||
|
|
||||||
|
std::vector<int> run_intcode(std::vector<int> &program, std::deque<int> inputs = {});
|
||||||
}
|
}
|
||||||
|
|||||||
54
2019/tests/test_intcode.cpp
Normal file
54
2019/tests/test_intcode.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
using aoc2019::run_intcode;
|
||||||
|
|
||||||
|
auto run_program(std::vector<int> program, std::deque<int> input) {
|
||||||
|
return run_intcode(program, std::move(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Intcode, TestPositionEquality) {
|
||||||
|
const std::vector<int> program = {3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8};
|
||||||
|
|
||||||
|
ASSERT_EQ(1, run_program(program, {8}).front());
|
||||||
|
ASSERT_EQ(0, run_program(program, {9}).front());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Intcode, TestPositionLess) {
|
||||||
|
const std::vector<int> program = {3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8};
|
||||||
|
|
||||||
|
ASSERT_EQ(1, run_program(program, {7}).front());
|
||||||
|
ASSERT_EQ(0, run_program(program, {9}).front());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Intcode, TestImmediateEquality) {
|
||||||
|
const std::vector<int> program = {3, 3, 1108, -1, 8, 3, 4, 3, 99};
|
||||||
|
|
||||||
|
ASSERT_EQ(1, run_program(program, {8}).front());
|
||||||
|
ASSERT_EQ(0, run_program(program, {9}).front());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Intcode, TestImmediateLess) {
|
||||||
|
const std::vector<int> program = {3, 3, 1107, -1, 8, 3, 4, 3, 99};
|
||||||
|
|
||||||
|
ASSERT_EQ(1, run_program(program, {7}).front());
|
||||||
|
ASSERT_EQ(0, run_program(program, {9}).front());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Intcode, TestComplicatedConditional) {
|
||||||
|
const std::vector<int> program = {3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31,
|
||||||
|
1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104,
|
||||||
|
999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99};
|
||||||
|
auto pcopy = program;
|
||||||
|
|
||||||
|
auto output = run_intcode(pcopy, {7});
|
||||||
|
ASSERT_EQ(999, output.front());
|
||||||
|
|
||||||
|
pcopy = program;
|
||||||
|
output = run_intcode(pcopy, {9});
|
||||||
|
ASSERT_EQ(1001, output.front());
|
||||||
|
|
||||||
|
pcopy = program;
|
||||||
|
output = run_intcode(pcopy, {8});
|
||||||
|
ASSERT_EQ(1000, output.front());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user