Skip to content

Instantly share code, notes, and snippets.

@ericmlujan
Created December 6, 2019 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericmlujan/c83ed88f03f9ec3b8ca21936877a2fd5 to your computer and use it in GitHub Desktop.
Save ericmlujan/c83ed88f03f9ec3b8ca21936877a2fd5 to your computer and use it in GitHub Desktop.
Advent of Code 2019 - Day 3
#include <iostream>
#include <vector>
struct Point {
Point() : x(0), y(0) {}
Point(int newX, int newY) : x(newX), y(newY) {}
int x;
int y;
};
inline bool operator==(const Point &p1, const Point &p2) {
return p1.x == p2.x && p1.y == p2.y;
}
inline bool operator!=(const Point &p1, const Point &p2) { return !(p1 == p2); }
// Segments are horizontal or vertical segments between two points.
// To ease intersection checks, ordered intervals of x and y coordinates are precomputed.
struct Segment {
Segment(const Point &a, const Point &b) {
p1 = a;
p2 = b;
xMin = std::min(p1.x, p2.x);
xMax = std::max(p1.x, p2.x);
yMin = std::min(p1.y, p2.y);
yMax = std::max(p1.y, p2.y);
}
Point p1;
Point p2;
int xMin;
int xMax;
int yMin;
int yMax;
};
// Check if two segments intersect. Returns true if segments intersect. If they
// do, intersection will be modified with the intersection if non-null.
bool intersects(const Segment &s1, const Segment &s2, Point *intersection) {
if ((s1.xMin >= s2.xMin && s1.xMin <= s2.xMax) &&
(s2.yMin >= s1.yMin && s2.yMin <= s1.yMax)) {
if (intersection) {
intersection->x = s1.xMin;
intersection->y = s2.yMin;
}
return true;
} else if ((s2.xMin >= s1.xMin && s2.xMin <= s1.xMax) &&
(s1.yMin >= s2.yMin && s1.yMin <= s2.yMax)) {
if (intersection) {
intersection->x = s2.xMin;
intersection->y = s1.yMin;
}
return true;
}
return false;
};
int manhattanDist(const Point &a, const Point &b) {
return std::abs(a.x - b.x) + std::abs(a.y - b.y);
}
std::vector<Segment> parseWire(std::istream &in) {
std::vector<Segment> wire;
// Wires by definition start at the origin
Point currPoint;
Point newPoint;
for (char direction; in >> direction;) {
int n;
std::cin >> n;
if (std::cin.peek() == ',') {
std::cin.ignore();
}
newPoint = currPoint;
switch (direction) {
case 'U':
newPoint.y += n;
break;
case 'D':
newPoint.y -= n;
break;
case 'L':
newPoint.x -= n;
break;
case 'R':
newPoint.x += n;
break;
default:
continue;
}
wire.emplace_back(currPoint, newPoint);
currPoint = newPoint;
if (std::cin.peek() == '\n' || std::cin.peek() == EOF) {
std::cin.ignore();
break;
}
}
return wire;
}
int main() {
std::vector<Segment> wireOne = parseWire(std::cin);
std::vector<Segment> wireTwo = parseWire(std::cin);
const Point ORIGIN(0, 0);
////////////////////////////////////////////////////////////
// PART ONE
////////////////////////////////////////////////////////////
int minDist = std::numeric_limits<int>::max();
////////////////////////////////////////////////////////////
// PART TWO
////////////////////////////////////////////////////////////
int minDelay = std::numeric_limits<int>::max();
Point intersection;
int oneDist = 0;
for (const auto &i : wireOne) {
int twoDist = 0;
for (const auto &j : wireTwo) {
if (intersects(i, j, &intersection) && intersection != ORIGIN) {
minDelay = std::min(minDelay, (oneDist + twoDist +
manhattanDist(intersection, i.p1) +
manhattanDist(intersection, j.p1)));
minDist = std::min(minDist, manhattanDist(intersection, ORIGIN));
}
twoDist += manhattanDist(j.p1, j.p2);
}
oneDist += manhattanDist(i.p1, i.p2);
}
std::cout << minDist << std::endl;
std::cout << minDelay << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment