74 lines
2.1 KiB
C
74 lines
2.1 KiB
C
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "common.c"
|
|
|
|
/// This one does not rely on pointers of pointers to represent a 2d
|
|
/// array. So no `[x][y]` access. Instead it represents the surface
|
|
/// as an 1d line, in which, if the current cell is `i`:
|
|
///
|
|
/// - the previous cell is at `surface[i - 1]`
|
|
/// - the cell in the next row is at `surface[i + width]`
|
|
/// - the cell in the previous row is at `surface[i - width]`
|
|
/// - the next cell is at `surface[i + 1]`
|
|
|
|
|
|
void apply_gravity(int width, int *terrain)
|
|
{
|
|
bool did_something;
|
|
int div;
|
|
int grid_size = width * width;
|
|
|
|
while (1) {
|
|
did_something = false;
|
|
for (int x = 0; x < grid_size; x++) {
|
|
if (terrain[x] >= 4) {
|
|
did_something = true;
|
|
div = terrain[x] / 4;
|
|
terrain[x] %= 4;
|
|
terrain[x - 1] += div;
|
|
terrain[x + 1] += div;
|
|
terrain[x - width] += div;
|
|
terrain[x + width] += div;
|
|
}
|
|
}
|
|
if (!did_something) {
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "looped %i times:\n", loops);
|
|
for (int i = 0; i < 9; i++) {
|
|
fprintf(stderr, "- %"PRIu64" times to break a pile of %i grains\n", by_height[i], i);
|
|
}
|
|
fprintf(stderr, "- %"PRIu64" times to break a pile of more than 13 grains\n", by_height[9]);
|
|
fprintf(stderr, "Total %i collapses\n", collapses);
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
args args = {0};
|
|
|
|
if (parse_args(argc, argv, &args))
|
|
return EXIT_FAILURE;
|
|
|
|
int width = sandpile_width(args.height);
|
|
int *terrain = calloc(width * width, sizeof(int*));
|
|
terrain[width * (width / 2) + (width / 2)] = args.height;
|
|
apply_gravity(width, terrain);
|
|
|
|
// "convert" to 2D for printing:
|
|
int **terrain_2d = calloc(width, sizeof(int*));
|
|
for (int i = 0; i < width; i++) {
|
|
terrain_2d[i] = terrain + i * width;
|
|
}
|
|
|
|
save_terrain(width, terrain_2d, &args);
|
|
return EXIT_SUCCESS;
|
|
}
|