puzzle.c (2996B)
1 #define _DEFAULT_SOURCE 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <errno.h> 6 #include <string.h> 7 #include <strings.h> 8 #include <assert.h> 9 #include <stdbool.h> 10 #include <unistd.h> 11 12 #include "util.h" 13 14 #define STR_LEN 1024 15 16 struct vec2_t { 17 int x, y; 18 }; 19 20 void array_push(struct array_t *array, int val); 21 bool probe(struct vec2_t velocity, struct vec2_t (*target)[2], int *max_y); 22 void add_velocity(struct array_t *array, struct vec2_t *velocity); 23 int compare(const void *l, const void *r); 24 25 void puzzle(const char *filename, long long *result1, long long *result2) { 26 FILE *infile = fopen(filename, "r"); 27 if (infile == NULL) { 28 fprintf(stderr, "fopen() error: %s\n", strerror(errno)); 29 return; 30 } 31 32 char buf[STR_LEN] = {0}; 33 unsigned int line_num = 0; 34 35 *result1 = 0; 36 *result2 = 0; 37 38 //@todo actual parsing 39 40 while (fgets(buf, STR_LEN, infile) != NULL) { 41 ++line_num; 42 bzero(buf, STR_LEN); 43 } 44 45 struct vec2_t target[2] = { 46 // {.x=20, .y=-5}, 47 // {.x=30, .y=-10} 48 {.x=156, .y=-69}, 49 {.x=202, .y=-110} 50 }; 51 52 struct array_t heights = { .data=NULL }; 53 array_init(&heights, sizeof(int), 100); 54 55 struct array_t velocities = { .data=NULL }; 56 array_init(&velocities, sizeof(struct vec2_t), 100); 57 58 for (int x = 0; x < 1000; ++x) { 59 for (int y = target[1].y; y < 1000; ++y) { 60 struct vec2_t velocity = {.x=x, .y=y}; 61 int max_y = 0; 62 63 if (probe(velocity, &target, &max_y)) { 64 array_push(&heights, max_y); 65 add_velocity(&velocities, &velocity); 66 } 67 } 68 } 69 70 if (heights.count > 0) { 71 qsort(heights.data, heights.count, heights.elem_size, compare); 72 int *data = heights.data; 73 *result1 = data[0]; 74 } 75 76 *result2 = velocities.count; 77 78 //PRINT_ARRAY(heights, int) 79 // mutiny! ignoring feof/ferror. 80 fclose(infile); 81 } 82 83 bool probe(struct vec2_t velocity, struct vec2_t (*target)[2], int *max_y) { 84 struct vec2_t pos = {0}; 85 *max_y = 0; 86 while (pos.y > (*target)[1].y) { //&& pos.y < (*target)[1].y) { 87 pos.x += velocity.x; 88 pos.y += velocity.y; 89 if (velocity.x > 0) { 90 velocity.x -= 1; 91 } else if (velocity.x < 0) { 92 velocity.x += 1; 93 } 94 velocity.y -= 1; 95 //printf("vx:%d, vy:%d x:%d, y:%d\n", velocity.x, velocity.y, pos.x, pos.y); 96 *max_y = pos.y > *max_y ? pos.y : *max_y; 97 98 if (pos.x >= (*target)[0].x && pos.x <= (*target)[1].x && 99 pos.y <= (*target)[0].y && pos.y >= (*target)[1].y) { 100 return true; 101 } 102 } 103 104 return false; 105 } 106 107 void array_push(struct array_t *array, int val) { 108 if (array->count >= array->cap) { 109 array_expand(array); 110 } 111 int *data = array->data; 112 data[array->count++] = val; 113 } 114 115 void add_velocity(struct array_t *array, struct vec2_t *velocity) { 116 for (size_t i = 0; i < array->count; ++i) { 117 struct vec2_t *data = array->data; 118 if (data[i].x == velocity->x && data[i].y == velocity->y) { 119 return; // only distinct values 120 } 121 } 122 123 if (array->count >= array->cap) { 124 array_expand(array); 125 } 126 struct vec2_t *data = array->data; 127 data[array->count++] = *velocity; 128 } 129 130 int compare(const void *l, const void *r) { 131 return *(int *)r - *(int *)l; 132 }