#include #include #include #include #include "input.h" #define INPUT "input/03.txt" #define INPUT_SIZE 12 unsigned long parse_line(char* binary_line, char expected_end) { char* endp = NULL; unsigned long result = strtoul(binary_line, &endp, 2); if(*endp != expected_end) err(1, "cannot parse line: %s\n", binary_line); return result; } unsigned long compute_gamma(struct input_str* input) { int oneCount[INPUT_SIZE]; // TODO is that necessary ? for(int k = 0; k < INPUT_SIZE; k++) { oneCount[k] = 0; } for(size_t i = 0; i < input->line_count; i++) { char* line = input->lines[i]; for(int j = 0; j < INPUT_SIZE; j++) { if(line[j] == '1') oneCount[j]++; } } // null terminated string char binary[INPUT_SIZE + 1]; for(int h = 0; h < INPUT_SIZE; h++) { binary[h] = oneCount[h] >= input->line_count / 2.0f ? '1' : '0'; } binary[INPUT_SIZE] = '\0'; unsigned long gamma = parse_line(binary, '\0'); return gamma; } unsigned long compute_epsilon(unsigned long gamma) { unsigned long epsilon = gamma ^ 0xFFF; return epsilon; } void part1(struct input_str* input) { unsigned long gamma = compute_gamma(input); unsigned long epsilon = compute_epsilon(gamma); printf("%ld\n", gamma * epsilon); } unsigned long search_criteria(struct input_str* input, unsigned long criteria) { unsigned long match; bool foundLine = false; unsigned long mask = 1 << (INPUT_SIZE - 1); // we start by checking only the first bit for(int linePos = 0; linePos < INPUT_SIZE; linePos++) { for(size_t is = 0; is < input->line_count; is++) { // TODO this parsing step could be outside of this loop unsigned long parsedLine = parse_line(input->lines[is], '\n'); if((parsedLine & mask) == (criteria & mask)) { // this line fits the criteria if(foundLine) { // more than one line fits, we need to consider another bit foundLine = false; mask = (mask >> 1) | (1 << (INPUT_SIZE - 1)); break; } else { // save it for later foundLine = true; match = parsedLine; } } } // checked all lines, if we found one matching then it is the one we want if(foundLine) break; } if(!foundLine) err(1, "cannot find line matching mask %ld\n", mask); return match; } void part2(struct input_str* input) { unsigned long o2_criteria = compute_gamma(input); unsigned long o2_rate = search_criteria(input, o2_criteria); unsigned long co2_criteria = compute_epsilon(o2_criteria); unsigned long co2_scrub = search_criteria(input, co2_criteria); printf("%ld\n", o2_rate * co2_scrub); } int main() { // read input data struct input_str input; input_str_read(&input, INPUT); // do stuff part1(&input); part2(&input); // cleanup & exit input_str_free(&input); return 0; }