122 lines
2.8 KiB
C++
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;
|
||
|
}
|