diff options
Diffstat (limited to 'sumart.c')
| -rw-r--r-- | sumart.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/sumart.c b/sumart.c new file mode 100644 index 0000000..e5ae509 --- /dev/null +++ b/sumart.c @@ -0,0 +1,215 @@ +/* See LICENSE file for copyright and license details. */ +#include <libsimple.h> +#include <libsimple-arg.h> + +USAGE("[rows columns] [checksum]"); + +#define BITS 2 + + +int +main(int argc, char *argv[]) +{ +#if BITS == 5 + static const ssize_t x_movements[1 << BITS] = { + -3, -2, -1, +1, +2, +3, + -3, -2, -1, +1, +2, +3, + -3, -2, +2, +3, + -3, -2, +2, +3, + -3, -2, -1, +1, +2, +3, + -3, -2, -1, +1, +2, +3, + }; + static const ssize_t y_movements[1 << BITS] = { + -3, -3, -3, -3, -3, -3, + -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, + +1, +1, +1, +1, + +2, +2, +2, +2, +2, +2, + +3, +3, +3, +3, +3, +3, + }; +#elif BITS == 4 + static const ssize_t x_movements[1 << BITS] = { + -2, -1, 0, 0, +1, +2, + -2, -1, +1, +2, + -2, -1, 0, 0, +1, +2 + }; + static const ssize_t y_movements[1 << BITS] = { + -2, -1, -2, -1, -2, -1, + 0, 0, 0, 0, + +1, +2, +1, +2, +1, +2 + }; +#elif BITS == 3 + static const ssize_t x_movements[1 << BITS] = { + -1, 0, +1, + -1, +1, + -1, 0, +1 + }; + static const ssize_t y_movements[1 << BITS] = { + -1, -1, -1, + 0, 0, + +1, +1, +1 + }; +#elif BITS == 2 +# if 0 + static const ssize_t x_movements[1 << BITS] = { + -1, +1, + -1, +1 + }; + static const ssize_t y_movements[1 << BITS] = { + -1, -1, + +1, +1 + }; +# else + static const ssize_t x_movements[1 << BITS] = { + 0, -1, + +1, 0 + }; + static const ssize_t y_movements[1 << BITS] = { + -1, 0, + 0, +1 + }; +# endif +#endif + + static const char *const symbols[] = { + ":", ".", "+", "=", + "¤", "o", "*", "£", + "X", "%", "&", "B", + "@", "#", "/", "^" + }; + static const char *const colours[] = { + "", "34;1", "33;1" + }; + + const char *checksum; + char *data = NULL, *end; + size_t size = 0u; + size_t len = 0u, cell; + size_t i, n, x[2], y[2], v, bits; + int d, colour; + ssize_t r; + size_t rows = 15u, cols = 32u; + unsigned char *art; + + ARGBEGIN { + default: + usage(); + } ARGEND; + + if (argc > 1) { + if ('1' > argv[0][0u] || argv[0][0u] > '9' || + '1' > argv[1][0u] || argv[1][0u] > '9') + usage(); + + errno = 0; + rows = strtouz(argv[0], &end, 10); + if (!rows || *end || errno) + usage(); + cols = strtouz(argv[1], &end, 10); + if (!cols || *end || errno) + usage(); + + argc -= 2; + argv += 2; + } + + if (argc > 1) + usage(); + + if (argc) { + checksum = *argv; + } else { + for (;;) { + if (len == size) + data = erealloc(data, size += 128u); + r = read(STDIN_FILENO, &data[len], size - len); + if (r <= 0) { + if (!r) + break; + if (errno == EINVAL) + continue; + eprintf("read <stdin>:"); + } + n = len + (size_t)r; + for (i = len; i < n; i++) { + if (('0' <= data[i] && data[i] <= '9') || + ('A' <= data[i] && data[i] <= 'F') || + ('a' <= data[i] && data[i] <= 'f')) + data[len++] = data[i]; + } + } + data = erealloc(data, len + 1u); + data[len] = '\0'; + checksum = data; + } + + art = ecalloc(rows, cols); + + x[0] = x[1] = cols / 2u; + y[0] = y[1] = rows / 2u; + + colour = 0; + v = 0u; + bits = 0u; + for (i = 0u; checksum[i]; i++) { + if (('0' > checksum[i] || checksum[i] > '9') && + ('A' > checksum[i] || checksum[i] > 'F') && + ('a' > checksum[i] || checksum[i] > 'f')) + continue; + d = ((int)checksum[i] & 15) + (checksum[i] > '9' ? 9 : 0); + v <<= 4; + v |= (size_t)d; + bits += 4u; + while (bits >= BITS) { + x[colour] += (size_t)x_movements[v % ELEMSOF(x_movements)]; + y[colour] += (size_t)y_movements[v % ELEMSOF(y_movements)]; + x[colour] %= cols; + y[colour] %= rows; + cell = y[colour] * cols + x[colour]; + art[cell] = (unsigned char)(art[cell] + (colour ? 0x20u : 1u)); + art[cell] &= 0xEFu; + v >>= BITS; + bits -= BITS; + if (ELEMSOF(colours) > 1u) + colour ^= 1; + } + } + if (bits) { + x[colour] += (size_t)x_movements[v % ELEMSOF(x_movements)]; + y[colour] += (size_t)y_movements[v % ELEMSOF(y_movements)]; + x[colour] %= cols; + y[colour] %= rows; + cell = y[colour] * cols + x[colour]; + art[cell] = (unsigned char)(art[cell] + (colour ? 0x20u : 1u)); + art[cell] &= 0xEFu; + } + + printf("+"); + for (i = 0u; i < cols; i++) + printf("-"); + printf("+\n"); + for (*y = 0u; *y < rows; ++*y) { + printf("|"); + for (*x = 0u; *x < cols; ++*x) { + cell = *y * cols + *x; + if (!art[cell]) { + printf(" "); + continue; + } + printf("\033[%sm%s\033[m", + colours[(art[cell] / 0x20u) % ELEMSOF(colours)], + symbols[(art[cell] & 0x0Fu) % ELEMSOF(symbols)]); + } + printf("|\n"); + } + printf("+"); + for (i = 0u; i < cols; i++) + printf("-"); + printf("+\n"); + + if (ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + free(art); + free(data); + return 0; +} |
