diff options
Diffstat (limited to '5.c')
-rw-r--r-- | 5.c | 189 |
1 files changed, 189 insertions, 0 deletions
@@ -0,0 +1,189 @@ + +#include <ctype.h> +#include <regex.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +struct crate { + struct crate * next; + char id; +}; + + +int +crates_move_9000(struct crate ** stack, int stacks, int dest, int src, int count) +{ + int i; + + if (dest < 0 || dest >= stacks + || src < 0 || src >= stacks) + { + fprintf(stderr, "Invalid src/dest stack (%d/%d/%d)\n", + stacks, dest, src); + return -1; + } + + for (i = 0; i < count; ++i) { + struct crate * c; + + if (stack[src] == NULL) { + fprintf(stderr, "No crates available in stack %d\n", + src); + return -1; + } + + c = stack[src]; + stack[src] = c->next; + c->next = stack[dest]; + stack[dest] = c; + } + + return 0; +} + + +int +crates_move_9001(struct crate ** stack, int stacks, int dest, int src, int count) +{ + int i; + struct crate * first, * last; + + if (dest < 0 || dest >= stacks + || src < 0 || src >= stacks) + { + fprintf(stderr, "Invalid src/dest stack (%d/%d/%d)\n", + stacks, dest, src); + return -1; + } + + last = first = stack[src]; + for (i = 1; i < count; ++i) { + if (last) + last = last->next; + } + if (!last) { + fprintf(stderr, "Fewer than %d crates available in stack %d\n", + count, src); + return -1; + } + + stack[src] = last->next; + last->next = stack[dest]; + stack[dest] = first; + + return 0; +} + + +int +crates_dump(struct crate ** stack, int stacks) +{ + int i; + + for (i = 0; i < stacks; ++i) { + struct crate * c; + + fprintf(stderr, "%d:", i + 1); + for (c = stack[i]; c != NULL; c = c->next) { + fprintf(stderr, " %c", c->id); + } + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + + return 0; +} + + +int +main(int argc, char ** argv) +{ + int (*crates_move)(struct crate **, int, int, int, int) = crates_move_9000; + char buf[BUFSIZ]; + int stacks = 0, i; + struct crate ** stack = NULL; + regex_t movecmd; + + while ((i = getopt(argc, argv, "m:")) != -1) { + switch (i) { + case 'm': + if (strcmp(optarg, "9000") == 0) + crates_move = crates_move_9000; + else if (strcmp(optarg, "9001") == 0) + crates_move = crates_move_9001; + else { + fprintf(stderr, "Unknown CrateMover %s\n", optarg); + return -1; + } + break; + + default: + return -1; + } + } + + while (fgets(buf, sizeof(buf), stdin)) { + int len; + + len = strlen(buf); + + if (len == 1 && buf[0] == '\n') { + break; + } + if (stacks == 0 && stack == NULL) { + if (len % 4 != 0) { + fprintf(stderr, "Unexpected first line width: %d\n", len); + return -1; + } + stacks = len / 4; + stack = calloc(stacks, sizeof(struct crate *)); + } + if (len != stacks * 4) { + fprintf(stderr, "Unexpected input line width: %d/%d\n", len, stacks * 4); + return -1; + } + + for (i = 0; i < stacks; ++i) { + if (isupper(buf[i * 4 + 1])) { + struct crate ** pc = stack + i; + while (*pc != NULL) + pc = &(*pc)->next; + *pc = malloc(sizeof(struct crate)); + (*pc)->next = NULL; + (*pc)->id = buf[i * 4 + 1]; + } + } + +#ifdef CRATES_DUMP + crates_dump(stack, stacks); +#endif + } + + regcomp(&movecmd, "move ([[:digit:]]+) from ([[:digit:]]+) to ([[:digit:]]+)\n", REG_EXTENDED); + while (fgets(buf, sizeof(buf), stdin)) { + regmatch_t matches[4]; + if (regexec(&movecmd, buf, 4, matches, 0) != 0) { + fprintf(stderr, "Unexpected move command: %s\n", buf); + } + crates_move(stack, stacks, + atoi(buf + matches[3].rm_so) - 1, + atoi(buf + matches[2].rm_so) - 1, + atoi(buf + matches[1].rm_so)); + +#ifdef CRATES_DUMP + crates_dump(stack, stacks); +#endif + } + regfree(&movecmd); + + for (i = 0; i < stacks; ++i) { + fputc(stack[i] ? stack[i]->id : ' ', stdout); + } + fputc('\n', stdout); + + return 0; +} + |