summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--17.c132
1 files changed, 125 insertions, 7 deletions
diff --git a/17.c b/17.c
index 67230fb..897d7d1 100644
--- a/17.c
+++ b/17.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#define arrlen(x) (sizeof(x)/sizeof((x)[0]))
@@ -21,6 +22,72 @@ struct rock const rocks[] = {
};
+struct cheat {
+ unsigned long depth;
+ struct rock rock;
+ unsigned long num;
+ unsigned long pos;
+};
+
+
+unsigned long
+cheat_numdiff(struct cheat * cheats, int ncheats)
+{
+ return cheats[0].num - cheats[1].num;
+}
+
+
+unsigned long
+cheat_posdiff(struct cheat * cheats, int ncheats)
+{
+ return cheats[0].pos - cheats[1].pos;
+}
+
+
+int
+cheat_check(struct cheat * cheats, int ncheats,
+ unsigned long depth, struct rock const * rock,
+ unsigned long rocknum, unsigned long position)
+{
+ unsigned long numdiff, posdiff;
+ int i;
+
+ if (depth < cheats[0].depth)
+ // Not deep enough.
+ return 0;
+
+ if (depth == cheats[0].depth
+ && memcmp(rock, &cheats[0].rock, sizeof(struct rock)) != 0)
+ // Same depth as previously, but differnt rock, or in different
+ // position in chamber.
+ return 0;
+
+ // Rock is either deeper than any previous, or is as deep and is the
+ // same rock in the same position in the chamber
+
+ fprintf(stderr, "Deepest rock %lu (depth %lu, height %lu)\n",
+ rocknum, depth, position);
+
+ memmove(cheats + 1, cheats, sizeof(struct cheat) * (ncheats - 1));
+ cheats[0].depth = depth;
+ cheats[0].rock = *rock;
+ cheats[0].num = rocknum;
+ cheats[0].pos = position;
+
+ numdiff = cheat_numdiff(cheats, ncheats);
+ posdiff = cheat_posdiff(cheats, ncheats);
+
+ for (i = 2; i < ncheats; ++i)
+ if (cheats[i - 1].num - cheats[i].num != numdiff
+ || cheats[i - 1].pos - cheats[i].pos != posdiff)
+ // Not all the cheats are the same
+ return 0;
+
+ // All the cheats are the same!
+ return 1;
+}
+
+
#if 0
void
chamber_dump(unsigned char * chamber, int chamberheight, struct rock * rock, int rockheight)
@@ -53,16 +120,44 @@ chamber_dump(unsigned char * chamber, int chamberheight, struct rock * rock, int
int
-main()
+main(int argc, char ** argv)
{
+ int docheat = 0;
size_t jetsize = 0;
char * jets = NULL;
unsigned char * chamber = NULL;
- int chamberheight = 0, top = 0;
- int movement, rocknum, rockheight;
+ unsigned long chamberheight = 0, top = 0, cheatby = 0;
+ unsigned long movement, rocknum, rockheight;
+ unsigned long rocklimit = 2022;
+ struct cheat cheats[10] = {0};
struct rock rock;
int i;
+ while ((i = getopt(argc, argv, "p:r:c")) != -1) {
+ switch (i) {
+ case 'p':
+ switch (atoi(optarg)) {
+ case 1: rocklimit = 2022; break;
+ case 2: rocklimit = 1000000000000; break;
+ default:
+ fprintf(stderr, "Bad part: %s\n", optarg);
+ return -1;
+ }
+ break;
+
+ case 'r':
+ rocklimit = atol(optarg);
+ break;
+
+ case 'c':
+ docheat = 1;
+ break;
+
+ default:
+ return -1;
+ }
+ }
+
// Read jets.
while (1) {
void * p;
@@ -92,15 +187,16 @@ main()
rock = rocks[rocknum];
rockheight = 3;
- for (movement = 0; rocknum < 2022; ++movement) {
+ for (movement = 0; rocknum < rocklimit; ++movement) {
int jet;
- if (top > chamberheight - 10) {
+ if (!chamberheight || top > chamberheight - 10) {
void * p;
if ((p = realloc(chamber, chamberheight + BUFSIZ)) == NULL) {
- fprintf(stderr, "Bad realloc(%d)\n", chamberheight + BUFSIZ);
+ fprintf(stderr, "Bad realloc(%lu)\n", chamberheight + BUFSIZ);
free(chamber);
+ free(jets);
return -1;
}
chamber = p;
@@ -149,6 +245,28 @@ main()
top = rockheight + i;
}
+ // Check to see if we can cheat
+ if (docheat
+ && rocknum > arrlen(rocks) * jetsize
+ && rockheight < top
+ && cheat_check(cheats, arrlen(cheats),
+ top - rockheight, &rock,
+ rocknum, rockheight))
+ {
+ unsigned long numdiff, posdiff, steps;
+
+ numdiff = cheat_numdiff(cheats, arrlen(cheats));
+ posdiff = cheat_posdiff(cheats, arrlen(cheats));
+
+ steps = (rocklimit - rocknum) / numdiff;
+
+ fprintf(stderr, "Cheating from rock %lu to %lu in %lu steps of %lu rocks/%lu height\n",
+ rocknum, rocklimit, steps, numdiff, posdiff);
+
+ rocknum += steps * numdiff;
+ cheatby += steps * posdiff;
+ }
+
// Pick next rock.
rock = rocks[++rocknum % arrlen(rocks)];
rockheight = top + 4;
@@ -163,7 +281,7 @@ main()
}
}
- printf("Height of rocks in chamber: %d\n", top + 1);
+ printf("Height of rocks in chamber: %lu\n", top + cheatby + 1);
free(chamber);
free(jets);