AdventOfCode2021/source/day5/part1.d

118 lines
3.0 KiB
D

module day5.part1;
import std.file;
import std.stdio;
import std.format;
import std.math;
bool between(int a, int b, int x) {
if (a < b) {
return x >= a && x <= b;
}
return x >= b && x <= a;
}
void updateMin(ref int m, int[] values...) {
foreach (v; values) {
if (v < m) m = v;
}
}
void updateMax(ref int m, int[] values...) {
foreach (v; values) {
if (v > m) m = v;
}
}
struct Point {
int x;
int y;
}
struct LineSegment {
Point p1;
Point p2;
float slope() {
return (p2.y - p1.y) / cast(float) (p2.x - p1.x);
}
bool isOrthogonal() {
return isVertical || isHorizontal;
}
bool isVertical() {
return p1.x == p2.x;
}
bool isHorizontal() {
return p1.y == p2.y;
}
bool isDiagonal() {
return abs(p2.x - p1.x) == abs(p2.y - p1.y);
}
bool occupiesPoint(Point p) {
if (isVertical()) {
return p.x == p1.x && between(p1.y, p2.y, p.y);
} else if (isHorizontal()) {
return p.y == p1.y && between(p1.x, p2.x, p.x);
} else if (isDiagonal()) {
return between(p1.x, p2.x, p.x) && between(p1.y, p2.y, p.y) && abs(p.x - p1.x) == abs(p.y - p1.y);
}
return false;
}
}
void draw(Point minCorner, Point maxCorner, LineSegment[] segments) {
for (int y = minCorner.y; y <= maxCorner.y; y++) {
for (int x = minCorner.x; x <= maxCorner.x; x++) {
Point p = Point(x, y);
int overlaps = 0;
foreach (ls; segments) {
if (ls.occupiesPoint(p)) overlaps++;
}
if (overlaps > 0) {
writef("%d", overlaps);
} else {
write(".");
}
}
writeln();
}
}
void hydrothermalVents() {
auto f = File("source/day5/input.txt", "r");
LineSegment[] segments = [];
Point minCorner = Point(1_000_000, 1_000_000);
Point maxCorner = Point(0, 0);
foreach (line; f.byLine) {
LineSegment ls;
formattedRead!"%d,%d -> %d,%d"(line, ls.p1.x, ls.p1.y, ls.p2.x, ls.p2.y);
if (ls.isOrthogonal() || ls.isDiagonal()) {
updateMin(minCorner.x, ls.p1.x, ls.p2.x);
updateMin(minCorner.y, ls.p1.y, ls.p2.y);
updateMax(maxCorner.x, ls.p1.x, ls.p2.x);
updateMax(maxCorner.y, ls.p1.y, ls.p2.y);
segments ~= ls;
}
}
writefln("Checking %d segments between %s and %s", segments.length, minCorner, maxCorner);
// draw(minCorner, maxCorner, segments);
int intersects = 0;
for (int x = minCorner.x; x <= maxCorner.x; x++) {
for (int y = minCorner.y; y <= maxCorner.y; y++) {
Point p = Point(x, y);
int overlaps = 0;
foreach (ls; segments) {
if (ls.occupiesPoint(p)) {
overlaps++;
}
}
if (overlaps > 1) intersects++;
}
}
writefln("%d", intersects);
}