spgen.c (1966B)
1 #include <rcx/all.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #include "common.h" 6 7 #define USAGE \ 8 "usage: %s WIDTH HEIGHT RECT...\n" \ 9 "where RECT ::= X,Y:W,H:S\n" 10 11 typedef struct rect Rect; 12 13 struct rect { 14 u32 x, y; 15 u32 w, h; 16 u32 s; 17 }; 18 19 void 20 parse_rect(usize i, Rect *r, char *s) { 21 char **xy_wh_s = (char*[3]){}; 22 if (r_str_split(&xy_wh_s, s, ":", 3) != 3) 23 r_fatalf("rectangle %zu malformed", i); 24 25 char **x_y = (char*[2]){}; 26 if (r_str_split(&x_y, xy_wh_s[0], ",", 2) != 2) 27 r_fatalf("rectangle %zu malformed", i); 28 29 char **w_h = (char*[2]){}; 30 if (r_str_split(&w_h, xy_wh_s[1], ",", 2) != 2) 31 r_fatalf("rectangle %zu malformed", i); 32 33 if (r_conv_zstr_to_u32(&r->x, x_y[0], 0) < 0) 34 r_fatalf("invalid x position in rectangle %zu", i); 35 36 if (r_conv_zstr_to_u32(&r->y, x_y[1], 0) < 0) 37 r_fatalf("invalid y position in rectangle %zu", i); 38 39 if (r_conv_zstr_to_u32(&r->w, w_h[0], 0) < 0) 40 r_fatalf("invalid width in rectangle %zu", i); 41 42 if (r_conv_zstr_to_u32(&r->h, w_h[1], 0) < 0) 43 r_fatalf("invalid height in rectangle %zu", i); 44 45 if (r_conv_zstr_to_u32(&r->s, xy_wh_s[2], 0) < 0) 46 r_fatalf("invalid sand in rectangle %zu", i); 47 } 48 49 int 50 main(int argc, char **argv) { 51 CHECK_FOR_HELP_OPTION(USAGE, argc, argv); 52 53 if (argc < 3) { 54 fprintf(stderr, USAGE, argv[0]); 55 exit(1); 56 } 57 58 u32 w, h; 59 if (r_conv_zstr_to_u32(&w, argv[1], 0) < 0) r_fatalf("invalid width"); 60 if (r_conv_zstr_to_u32(&h, argv[2], 0) < 0) r_fatalf("invalid height"); 61 62 u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32)); 63 Sandpile sp = { .w = w, .h = h, .sand = sand }; 64 #define SAND(x, y) sand[((y) + 1) * (w + 2) + ((x) + 1)] 65 66 usize nrects = argc - 3; 67 for (usize i = 0; i < nrects; i++) { 68 Rect r; 69 parse_rect(i, &r, argv[3+i]); 70 71 usize xmin = r.x; 72 usize xmax = MIN(w, r.x + r.w); 73 74 usize ymin = r.y; 75 usize ymax = MIN(h, r.y + r.h); 76 77 for (usize y = ymin; y < ymax; y++) { 78 for (usize x = xmin; x < xmax; x++) 79 SAND(x, y) += r.s; 80 } 81 } 82 83 sp_fwrite(stdout, sp); 84 }