advent_of_code_2021/17/main.cpp
2021-12-17 09:47:05 +01:00

122 lines
2.8 KiB
C++

#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using Area = std::pair<std::pair<long, long>, std::pair<long, long>>;
Area getTargetArea(const std::string &file_name) {
Area area{};
std::ifstream file(file_name);
std::string str;
std::getline(file, str);
std::stringstream ss(str);
std::string tmp;
char tmp_char;
long x1, x2, y1, y2;
ss >> tmp;
ss >> tmp;
ss >> tmp_char;
ss >> tmp_char;
ss >> x1;
ss >> tmp_char;
ss >> tmp_char;
ss >> x2;
ss >> tmp_char;
ss >> tmp_char;
ss >> tmp_char;
ss >> y1;
ss >> tmp_char;
ss >> tmp_char;
ss >> y2;
if (x1 < x2) {
area.first = { x1, x2 };
} else {
area.first = { x2, x1 };
}
if (y1 < y2) {
area.second = { y1, y2 };
} else {
area.second = { y2, y1 };
}
return area;
}
uint64_t sumUntilN(uint64_t n) {
return (n * (n + 1)) / 2;
}
long getMaxYSpeed(long lowest_area_y) {
return abs(lowest_area_y) - 1;
}
uint64_t part1(const Area &area) {
return sumUntilN(getMaxYSpeed(area.second.first));
}
bool willEverReach(long min_x, long max_x, long min_y, long max_y,
long initial_x, long initial_y) {
std::pair<long, long> pos = { 0, 0 };
while (true) {
pos.first += initial_x;
pos.second += initial_y;
if (pos.first >= min_x && pos.first <= max_x && pos.second <= min_y &&
pos.second >= max_y) {
return true;
}
if (initial_x == 0 && pos.first < min_x) {
break;
}
if (pos.first > max_x) {
break;
}
if (pos.second < max_y) {
break;
}
if (initial_x > 0) {
initial_x--;
}
initial_y--;
}
return false;
}
uint64_t part2(Area &area) {
uint64_t valid_trajectory = 0;
auto max_dist_y = abs(area.second.first);
auto max_dist_x = area.first.second;
for (long y = getMaxYSpeed(area.second.first); y >= area.second.first;
y--) {
for (long x = 0; x <= area.first.second; x++) {
if (willEverReach(area.first.first, area.first.second,
area.second.second, area.second.first, x, y)) {
valid_trajectory++;
}
}
}
return valid_trajectory;
}
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "You must provide input file!" << std::endl;
return 1;
}
auto area = getTargetArea(argv[1]);
std::cout << "The highest possible y is \033[91;1m" << part1(area)
<< "\033[0m." << std::endl;
std::cout << "There are \033[91;1m" << part2(area)
<< "\033[0m possible trajectories." << std::endl;
return 0;
}