10 static int debug_level
= -1;
11 static void __attribute__((unused
))
12 debug_raw(int level
, const char *fmt
, ...) {
15 debug_level
= atoi(getenv("DEBUG") ?: "0");
16 if (debug_level
>= level
) {
18 vfprintf(stderr
, fmt
, ap
);
22 #define debug(...) debug_raw(1, __VA_ARGS__)
29 static struct point grid
[LIMIT
][LIMIT
];
36 static struct info list
[LIMIT
* LIMIT
];
40 check_one (int to
, int from_x
, int from_y
) {
41 int to_x
= to
% bound
, to_y
= to
/ bound
;
42 int dx
= to_x
- from_x
, dy
= to_y
- from_y
;
43 int from
= from_y
* bound
+ from_x
;
46 debug_raw(2, " checking %d.%d, slope %d/%d", to_x
, to_y
, dy
, dx
);
47 if (grid
[to_y
][to_x
].blocked
== from
) {
48 debug_raw(2, " already visited\n");
52 if (grid
[to_y
][to_x
].asteroid
)
54 grid
[to_y
][to_x
].blocked
= from
;
55 debug_raw(2, " [visiting %d.%d]", to_x
, to_y
);
58 } while (to_x
>= 0 && to_x
< bound
&& to_y
>= 0 && to_y
< bound
);
59 debug_raw(2, " %s\n", result
? "hit" : "clear");
65 int x
= point
% bound
, y
= point
/ bound
;
68 debug_raw(2, "checking %d=%d.%d %c\n", point
, x
, y
,
69 grid
[y
][x
].asteroid
? '#' : '.');
70 if (!grid
[y
][x
].asteroid
)
72 for (i
= point
- 1; i
>= 0; i
--)
73 if (check_one(i
, x
, y
))
75 for (i
= point
+ 1; i
< bound
* bound
; i
++)
76 if (check_one(i
, x
, y
))
78 debug_raw(2, "hit %d\n", total
);
83 prep_one (int to
, int from_x
, int from_y
) {
84 int to_x
= to
% bound
, to_y
= to
/ bound
;
85 int dx
= to_x
- from_x
, dy
= to_y
- from_y
;
86 int from
= from_y
* bound
+ from_x
;
87 float slope
= (float)-dy
/ dx
;
90 debug(" prepping %d.%d, slope %d/%d=%g", to_x
, to_y
, dy
, dx
, slope
);
91 if (grid
[to_y
][to_x
].blocked
== -from
) {
92 debug(" already visited\n");
96 if (grid
[to_y
][to_x
].asteroid
) {
97 list
[next
].level
= level
+ (dx
< 0);
98 list
[next
].slope
= slope
;
99 list
[next
++].coord
= to_x
* 100 + to_y
;
102 grid
[to_y
][to_x
].blocked
= -from
;
103 debug(" [visiting %d.%d]", to_x
, to_y
);
106 } while (to_x
>= 0 && to_x
< bound
&& to_y
>= 0 && to_y
< bound
);
107 debug(" %d prepped\n", next
);
112 int x
= point
% bound
, y
= point
/ bound
;
115 list
[next
].level
= 0;
116 list
[next
].slope
= 0;
117 list
[next
++].coord
= x
* 10 + y
;
118 for (i
= point
- 1; i
>= 0; i
--)
120 for (i
= point
+ 1; i
< bound
* bound
; i
++)
125 comp(const void *pa
, const void *pb
) {
126 const struct info
*a
= pa
, *b
= pb
;
127 if (a
->level
< b
->level
)
129 if (a
->level
> b
->level
)
131 if (a
->slope
> b
->slope
)
133 if (a
->slope
< b
->slope
)
135 printf("unexpected equality for coord %d and %d\n", a
->coord
, b
->coord
);
139 int main(int argc
, char **argv
) {
140 size_t len
= 0, count
= 0, asteroids
= 0, total
= 0;
141 int i
, best_i
= 0, best_t
;
146 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
151 while ((i
= getline(&line
, &len
, stdin
)) >= 0) {
154 else if (bound
!= i
- 1) {
155 printf("input not a square: column\n");
158 for (i
= 0; i
< bound
; i
++)
159 if (line
[i
] == '#') {
160 grid
[count
][i
].asteroid
= true;
165 if (count
!= bound
) {
166 printf("input not a square: row\n");
169 printf("Read %zu lines, %zd asteroids\n", count
, asteroids
);
171 for (i
= 0; i
< bound
* bound
; i
++) {
173 if (total
> best_t
) {
178 printf("Best %d at %zd.%zd\n", best_t
, best_i
% bound
, best_i
/ bound
);
181 qsort(list
, asteroids
, sizeof list
[0], comp
);
182 for (i
= 0; i
< asteroids
; i
++)
183 debug("list[%d] = %d %g %d\n", i
, list
[i
].level
, list
[i
].slope
,
186 printf("200th vaporized at %d\n", list
[200].coord
);