diff options
author | Adam Spragg <adam@spra.gg> | 2022-12-18 16:11:32 +0000 |
---|---|---|
committer | Adam Spragg <adam@spra.gg> | 2022-12-18 16:11:32 +0000 |
commit | 4166c6630f4c1b0dab37a0a5fb7ae114d9b503d1 (patch) | |
tree | acff01c1356303aa0b00e99d68eae1eac269f2d0 /17.c | |
parent | f1985aae56d8869c66664573a74de54abc75759a (diff) |
Solve puzzle 17 part 1
Diffstat (limited to '17.c')
-rw-r--r-- | 17.c | 173 |
1 files changed, 173 insertions, 0 deletions
@@ -0,0 +1,173 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#define arrlen(x) (sizeof(x)/sizeof((x)[0])) + + +struct rock { + unsigned char s[4]; +}; + + +struct rock const rocks[] = { + { { 0x1e, 0, 0, 0 } }, // Horizontal line + { { 0x08, 0x1c, 0x08, 0 } }, // Cross + { { 0x1c, 0x04, 0x04, 0 } }, // Elbow + { { 0x10, 0x10, 0x10, 0x10 } }, // Line piece + { { 0x18, 0x18, 0, 0 } }, // Block +}; + + +#if 0 +void +chamber_dump(unsigned char * chamber, int chamberheight, struct rock * rock, int rockheight) +{ + int i; + + for (i = chamberheight - 1; i >= 0; --i) { + unsigned char c; + + fputc('|', stderr); + + for (c = 0x40; c != 0; c >>= 1) { + if (rock && i >= rockheight + && i < rockheight + arrlen(rock->s) + && (rock->s[i - rockheight] & c)) + fputc('@', stderr); + else if (chamber && (chamber[i] & c)) + fputc('#', stderr); + else + fputc('.', stderr); + } + + + fputc('|', stderr); + fputc('\n', stderr); + } + fprintf(stderr, "+-------+\n"); +} +#endif + + +int +main() +{ + size_t jetsize = 0; + char * jets = NULL; + unsigned char * chamber = NULL; + int chamberheight = 0, top = 0; + int movement, rocknum, rockheight; + struct rock rock; + int i; + + // Read jets. + while (1) { + void * p; + size_t s; + + if ((p = realloc(jets, jetsize + BUFSIZ)) == NULL) { + fprintf(stderr, "jets: bad realloc (%zu)\n", jetsize + BUFSIZ); + free(jets); + return -1; + } + jets = p; + if ((s = fread(jets + jetsize, 1, BUFSIZ, stdin)) == 0) + break; + jetsize += s; + } + + // Remove any characters that are not '<' or '>' (e.g. newlines) + for (i = 0; i < jetsize; ++i) { + while (i < jetsize && jets[i] != '<' && jets[i] != '>') { + memmove(jets + i, jets + i + 1, jetsize - (i + 1)); + --jetsize; + } + } + + // Place first rock, and start movement + rocknum = 0; + rock = rocks[rocknum]; + rockheight = 3; + + for (movement = 0; rocknum < 2022; ++movement) { + int jet; + + if (top > chamberheight - 10) { + void * p; + + if ((p = realloc(chamber, chamberheight + BUFSIZ)) == NULL) { + fprintf(stderr, "Bad realloc(%d)\n", chamberheight + BUFSIZ); + free(chamber); + return -1; + } + chamber = p; + memset(chamber + chamberheight, 0, BUFSIZ); + chamberheight += BUFSIZ; + } + + jet = jets[movement % jetsize]; + + // Check if jet can push rock. + for (i = 0; i < arrlen(rock.s); ++i) { + // Check left wall collision + if (jet == '<' && (rock.s[i] & 0x40) != 0) + jet = 0; + + // Check right wall collision + if (jet == '>' && (rock.s[i] & 0x01) != 0) + jet = 0; + + // Check moving left into existing rocks. + if (jet == '<' && ((rock.s[i] << 1) & chamber[rockheight + i]) != 0) + jet = 0; + + // Check moving right into existing rocks + if (jet == '>' && ((rock.s[i] >> 1) & chamber[rockheight + i]) != 0) + jet = 0; + } + + // If jet can push rock, do so. + if (jet == '<') + for (i = 0; jet && i < arrlen(rock.s); ++i) + rock.s[i] <<= 1; + if (jet == '>') + for (i = 0; jet && i < arrlen(rock.s); ++i) + rock.s[i] >>= 1; + + // Check if rock can fall. + for (i = 0; rockheight > 0 && i < arrlen(rock.s); ++i) + if ((rock.s[i] & chamber[rockheight - 1 + i]) != 0) + break; + if (i < arrlen(rock.s)) { + // Rock cannot fall. Place rock. + for (i = 0; i < arrlen(rock.s) && rock.s[i] != 0; ++i) { + chamber[rockheight + i] |= rock.s[i]; + if (rockheight + i > top) + top = rockheight + i; + } + + // Pick next rock. + rock = rocks[++rocknum % arrlen(rocks)]; + rockheight = top + 4; + +#if 0 + chamber_dump(chamber, top + 7, &rock, rockheight); +#endif + } + else { + // Rock can fall, so reduce its height by 1 + --rockheight; + } + } + + printf("Height of rocks in chamber: %d\n", top + 1); + + free(chamber); + free(jets); + + return 0; +} + |