mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 13 part 2.
This commit is contained in:
@@ -4,10 +4,16 @@ project(aoc2019)
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
option(ANIMATE_DAY13 "Animate the Arkanoid game in day 13." Off)
|
||||
|
||||
file(GLOB DAYS_FILES src/day*.cpp)
|
||||
add_library(AoCSolutions src/implementations.cpp "${DAYS_FILES}" src/point.hpp src/utils.cpp src/utils.hpp)
|
||||
target_compile_features(AoCSolutions PUBLIC cxx_std_17)
|
||||
|
||||
if (ANIMATE_DAY13)
|
||||
target_compile_definitions(AoCSolutions ANIMATE_DAY13)
|
||||
endif ()
|
||||
|
||||
add_executable(runner src/runner.cpp)
|
||||
target_compile_features(runner PUBLIC cxx_std_17)
|
||||
target_link_libraries(runner AoCSolutions)
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#include <iostream>
|
||||
#ifdef ANIMATE_DAY13
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#endif
|
||||
#include "days.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "point.hpp"
|
||||
@@ -13,28 +17,128 @@ namespace {
|
||||
PADDLE,
|
||||
BALL,
|
||||
};
|
||||
|
||||
typedef std::unordered_map<point_t, Tile> Screen;
|
||||
|
||||
std::optional<std::int64_t> update_screen(std::deque<std::int64_t> &output_buffer, Screen &screen) {
|
||||
std::optional<std::int64_t> score;
|
||||
while (!output_buffer.empty()) {
|
||||
auto x = output_buffer.front(); output_buffer.pop_front();
|
||||
auto y = output_buffer.front(); output_buffer.pop_front();
|
||||
auto type = output_buffer.front(); output_buffer.pop_front();
|
||||
|
||||
if (x == -1 && y == 0) {
|
||||
score = type;
|
||||
continue;
|
||||
}
|
||||
|
||||
screen[{x, y}] = static_cast<Tile>(type);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
void draw_screen(const Screen &screen, std::ostream& output) {
|
||||
// Determine bounding box
|
||||
using limits = std::numeric_limits<int>;
|
||||
|
||||
std::int64_t left_edge = limits::max(), right_edge = limits::min(), top_edge = limits::max(), bottom_edge = limits::min();
|
||||
for (auto& entry : screen) {
|
||||
left_edge = std::min(entry.first[0], left_edge);
|
||||
right_edge = std::max(entry.first[0], right_edge);
|
||||
top_edge = std::min(entry.first[1], top_edge);
|
||||
bottom_edge = std::max(entry.first[1], bottom_edge);
|
||||
}
|
||||
|
||||
for (auto y = top_edge; y <= bottom_edge; ++y) {
|
||||
for (auto x = left_edge; x <= right_edge; ++x) {
|
||||
char c = ' ';
|
||||
if (auto it = screen.find({x, y}); it != screen.end()) {
|
||||
switch (it->second) {
|
||||
case Tile::EMPTY:
|
||||
c = ' ';
|
||||
break;
|
||||
|
||||
case Tile::BALL:
|
||||
c = '*';
|
||||
break;
|
||||
|
||||
case Tile::BLOCK:
|
||||
c = '=';
|
||||
break;
|
||||
|
||||
case Tile::PADDLE:
|
||||
c = '_';
|
||||
break;
|
||||
|
||||
case Tile::WALL:
|
||||
c = '#';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output << c;
|
||||
}
|
||||
|
||||
output << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
auto find_pos(const Screen &screen, Tile to_find) {
|
||||
return std::find_if(screen.begin(), screen.end(), [to_find](const auto& x) {
|
||||
return x.second == to_find;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void aoc2019::day13_part1(std::istream &input, std::ostream &output) {
|
||||
Screen screen;
|
||||
aoc2019::IntCodeComputer computer(aoc2019::IntCodeComputer::read_intcode(input));
|
||||
std::deque<std::int64_t> output_buffer;
|
||||
|
||||
computer.connectOutput(output_buffer);
|
||||
computer.run();
|
||||
update_screen(output_buffer, screen);
|
||||
|
||||
std::unordered_map<point_t, Tile> drawn;
|
||||
|
||||
while (!output_buffer.empty()) {
|
||||
auto x = output_buffer.front(); output_buffer.pop_front();
|
||||
auto y = output_buffer.front(); output_buffer.pop_front();
|
||||
auto type = output_buffer.front(); output_buffer.pop_front();
|
||||
|
||||
drawn[{x, y}] = static_cast<Tile>(type);
|
||||
}
|
||||
|
||||
output << std::count_if(drawn.begin(), drawn.end(), [](const auto& x) { return x.second == Tile::BLOCK; })<< std::endl;
|
||||
output << std::count_if(screen.begin(), screen.end(), [](const auto &x) { return x.second == Tile::BLOCK; })
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void aoc2019::day13_part2(std::istream &input, std::ostream &output) {
|
||||
output << "Not implemented\n";
|
||||
auto program = aoc2019::IntCodeComputer::read_intcode(input);
|
||||
program[0] = 2;
|
||||
|
||||
aoc2019::IntCodeComputer computer(std::move(program));
|
||||
std::deque<std::int64_t> output_buffer;
|
||||
computer.connectOutput(output_buffer);
|
||||
computer.run();
|
||||
|
||||
Screen screen;
|
||||
|
||||
std::int64_t score = 0;
|
||||
|
||||
while (!computer.isTerminated()) {
|
||||
computer.run();
|
||||
auto new_score = update_screen(output_buffer, screen);
|
||||
if (new_score) {
|
||||
score = *new_score;
|
||||
}
|
||||
|
||||
#ifdef ANIMATE_DAY13
|
||||
output << "Score: " << score << std::endl;
|
||||
draw_screen(screen, output);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
#endif
|
||||
|
||||
auto ball_pos = find_pos(screen, Tile::BALL)->first;
|
||||
auto paddle_pos = find_pos(screen, Tile::PADDLE)->first;
|
||||
|
||||
if (ball_pos[0] < paddle_pos[0]) {
|
||||
computer.sendInput(-1);
|
||||
} else if (ball_pos[0] > paddle_pos[0]) {
|
||||
computer.sendInput(1);
|
||||
} else {
|
||||
computer.sendInput(0);
|
||||
}
|
||||
}
|
||||
|
||||
output << score << std::endl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user