diff options
| -rw-r--r-- | 17.c | 132 | 
1 files changed, 125 insertions, 7 deletions
| @@ -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); | 
