diff options
author | Vincent Douillet <vincent@vdouillet.fr> | 2021-12-04 15:14:26 +0100 |
---|---|---|
committer | Vincent Douillet <vincent@vdouillet.fr> | 2021-12-04 15:14:26 +0100 |
commit | 368f3bf67f03c308994b18bcdb60ac3bb2ec7477 (patch) | |
tree | ab58411c6f6d7c2ec198754a33488537dfa13f87 | |
parent | 736823f313bd2e00e49a1b52aaf0ea68a79db438 (diff) |
day 3
-rw-r--r-- | 03.c | 71 |
1 files changed, 65 insertions, 6 deletions
@@ -1,12 +1,21 @@ #include <stdlib.h> #include <stdio.h> #include <err.h> +#include <stdbool.h> #include "input.h" #define INPUT "input/03.txt" #define INPUT_SIZE 12 -void part1(struct input_str* input) { +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++) { @@ -24,18 +33,67 @@ void part1(struct input_str* input) { // 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[h] = oneCount[h] >= input->line_count / 2.0f ? '1' : '0'; } binary[INPUT_SIZE] = '\0'; - char* endp = NULL; - unsigned long gamma = strtoul(binary, &endp, 2); + unsigned long gamma = parse_line(binary, '\0'); + return gamma; +} + +unsigned long compute_epsilon(unsigned long gamma) { unsigned long epsilon = gamma ^ 0xFFF; - if(*endp != '\0') - err(1, "erreur de parsing du gammaat"); + 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; @@ -43,6 +101,7 @@ int main() { // do stuff part1(&input); + part2(&input); // cleanup & exit input_str_free(&input); |