#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#define BUFSIZE 20000
struct grid {
bool *data;
size_t w;
size_t h;
};
bool grid_get(const struct grid g, size_t x, size_t y) {
assert(x < g.w && y < g.h);
return g.data[x + y * g.w];
}
void grid_set(struct grid g, size_t x, size_t y, bool value) {
assert(x < g.w && y < g.h);
g.data[x + y * g.w] = value;
}
struct grid read_input() {
struct grid g;
char buf[BUFSIZE];
size_t bufsize = fread(buf, 1, sizeof buf, stdin);
assert(bufsize < sizeof buf);
/* First pass, get size */
g.w = 0;
g.h = 0;
for (size_t i = 0; i < bufsize; ++i) {
if (buf[i] == '\n') {
if (g.w == 0) {
g.w = i;
}
++g.h;
}
}
assert(g.w > 0);
/* Second pass, read into result */
g.data = calloc(g.w * g.h, sizeof *g.data);
assert(g.data != NULL);
size_t i_x = 0;
size_t i_y = 0;
for (size_t i = 0; i < bufsize; ++i) {
char c = buf[i];
if (c == '#') {
grid_set(g, i_x, i_y, true);
}
if (c == '\n') {
assert(i_x == g.w);
i_x = 0;
++i_y;
}
else {
++i_x;
}
}
return g;
}
size_t part1(const struct grid g, size_t dx, size_t dy) {
size_t x = 0;
size_t y = 0;
size_t count = 0;
do {
count += grid_get(g, x, y);
x = (x + dx) % g.w;
y += dy;
} while (y < g.h);
return count;
}
int main(void) {
struct grid g = read_input();
size_t count = part1(g, 3, 1);
printf("%zu\n", count);
count *= part1(g, 1, 1);
count *= part1(g, 5, 1);
count *= part1(g, 7, 1);
count *= part1(g, 1, 2);
printf("%zu\n", count);
free(g.data);
}