aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

24a.c (1718B)


      1 #include <stdbool.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 
      5 #define N    300
      6 #define XMIN 2e14
      7 #define XMAX 4e14
      8 #define eps  1e-6
      9 
     10 #define ABS(x) ((x)>0?(x):-(x))
     11 
     12 typedef struct { double x, y, z; } point_t;
     13 typedef struct { point_t p, v; } line_t;
     14 
     15 char *buf, line[N];
     16 int n, s;
     17 line_t l[N];
     18 
     19 bool isnum(char c) { return (c >= '0' && c <= '9') || c == '-'; }
     20 
     21 line_t readl(char *buf) {
     22 	double a[6];
     23 	for (int i = 0; i < 6; i++) {
     24 		a[i] = (double)atoll(buf);
     25 		while (isnum(*buf)) buf++;
     26 		while (*buf != '\n' && !isnum(*buf)) buf++;
     27 	}
     28 	return (line_t) {
     29 	    .p = (point_t){.x = a[0], .y = a[1], .z = a[2]},
     30 	    .v = (point_t){.x = a[3], .y = a[4], .z = a[5]}
     31 	};
     32 }
     33 
     34 double det(double a, double b, double c, double d) { return a*d-b*c; }
     35 
     36 bool parallel2d(line_t l1, line_t l2) {
     37 	double d = det(l1.v.x, l2.v.x, l1.v.y, l2.v.y);
     38 	return ABS(d) < eps;
     39 }
     40 
     41 point_t collide2d(line_t l1, line_t l2, double *t1, double *t2) {
     42 	double a1 = l1.v.x;
     43 	double b1 = -l2.v.x;
     44 	double c1 = l2.p.x - l1.p.x;
     45 	double a2 = l1.v.y;
     46 	double b2 = -l2.v.y;
     47 	double c2 = l2.p.y - l1.p.y;
     48 	
     49 	double d = det(a1, b1, a2, b2);
     50 	*t1 = det(c1, b1, c2, b2) / d;
     51 	*t2 = det(a1, c1, a2, c2) / d;
     52 
     53 	double x = l1.p.x + l1.v.x * (*t1);
     54 	double y = l1.p.y + l1.v.y * (*t1);
     55 
     56 	return (point_t) {.x = x, .y = y};
     57 }
     58 
     59 int main() {
     60 	for (n = 0; (buf = fgets(line, N, stdin)) != NULL; n++)
     61 		l[n] = readl(buf);
     62 
     63 	for (int i = 0; i < n; i++) {
     64 		for (int j = i+1; j < n; j++) {
     65 			if (parallel2d(l[i], l[j])) continue;
     66 			double t1, t2;
     67 			point_t p = collide2d(l[i], l[j], &t1, &t2);
     68 			if (t1 < -eps || t2 < -eps) continue;
     69 			s += p.x > XMIN-eps && p.x < XMAX+eps &&
     70 			     p.y > XMIN-eps && p.y < XMAX+eps;
     71 		}
     72 	}
     73 
     74 	printf("%d\n", s);
     75 	return 0;
     76 }