#include #include #include static struct Point { int x, y; } Point(int x, int y) { return (struct Point) { x, y }; } static int eq(struct Point a, struct Point b) { return a.x == b.x && a.y == b.y; } static struct Point sub(struct Point a, struct Point b) { return Point(a.x - b.x, a.y - b.y); } static struct Point reduce(struct Point p) { int max = (abs(p.x) > abs(p.y) ? abs(p.x) : abs(p.y)); for (int i = max; i > 1; --i) { if (p.x / i * i != p.x) continue; if (p.y / i * i != p.y) continue; return Point(p.x / i, p.y / i); } return p; } static double angle(struct Point p) { double theta = atan2(p.x, -p.y); return (theta < 0.0 ? theta + 2.0 * M_PI : theta); } static int compar(const void *_a, const void *_b) { struct Point a = *(const struct Point *)_a; struct Point b = *(const struct Point *)_b; if (angle(a) == angle(b)) { return copysign(1.0, hypot(a.x, a.y) - hypot(b.x, b.y)); } else { return copysign(1.0, angle(a) - angle(b)); } } int main(void) { struct Point ps[2048]; size_t len = 0; int y = 0, x = 0; int ch; while (EOF != (ch = getchar())) { switch (ch) { break; case '.': x++; break; case '#': ps[len++] = Point(x++, y); break; case '\n': y++; x = 0; } } size_t m, max = 0; for (size_t i = 0; i < len; ++i) { struct Point ds[2048]; size_t dlen = 0; for (size_t j = 0; j < len; ++j) { if (j == i) continue; struct Point a = reduce(sub(ps[j], ps[i])); size_t d; for (d = 0; d < dlen; ++d) { if (eq(ds[d], a)) break; } if (d == dlen) ds[dlen++] = a; } if (dlen > max) { max = dlen; m = i; } } printf("%zu\n", max); struct Point o = ps[m]; ps[m] = ps[--len]; for (size_t i = 0; i < len; ++i) { ps[i] = sub(ps[i], o); } qsort(ps, len, sizeof(ps[0]), compar); for (int n = 0;;) { for (size_t i = 0; i < len; ++i) { if (eq(ps[i], Point(0, 0))) continue; if (++n == 200) { printf("%d\n", 100 * (o.x + ps[i].x) + (o.y + ps[i].y)); return 0; } double theta = angle(ps[i]); ps[i] = Point(0, 0); while (i + 1 < len && angle(ps[i + 1]) == theta) i++; } } }