aoc-2021/src/day_3.c

136 lines
3.5 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "puzzle_input.h"
#include "day.h"
#define DIAGNOSTIC_LEN 2000
#define MAX_WORD_LEN 50
typedef struct {
char word[MAX_WORD_LEN];
uint32_t len;
} diagnostic_word_t;
typedef enum {
OXYGEN = 1,
CO2 = 0
} life_support_rating_t;
parse_ret_t parse_diagnostic_data(char * buffer, void * data, uint16_t index) {
diagnostic_word_t * diagnostic_data = (diagnostic_word_t *)data;
diagnostic_data[index].len = strlen(buffer);
strncpy(diagnostic_data[index].word, buffer, MAX_WORD_LEN);
return PARSER_OK;
}
static void part_1(diagnostic_word_t * diagnostic_data, uint16_t len) {
uint64_t gamma_rate = 0;
uint64_t epsilon_rate = 0;
uint16_t bit_len = diagnostic_data[0].len;
for (int bit_ndx = 0; bit_ndx < bit_len; bit_ndx++) {
int32_t one_count = 0;
for (int word_ndx = 0; word_ndx < len; word_ndx++) {
if (diagnostic_data[word_ndx].word[bit_ndx] == '1') {
one_count++;
}
}
if (one_count < len/2) {
epsilon_rate |= 1 << (bit_len - bit_ndx - 1);
}
else {
gamma_rate |= 1 << (bit_len - bit_ndx - 1);
}
}
printf("PART 1: The power consumption is %lu * %lu = %lu\n", gamma_rate, epsilon_rate, gamma_rate*epsilon_rate);
}
int64_t get_rating(diagnostic_word_t * diagnostic_data, uint16_t len, life_support_rating_t mode) {
uint16_t bit_len = diagnostic_data[0].len;
uint8_t keep[DIAGNOSTIC_LEN];
memset(keep, 1, len);
for (int bit_ndx = 0; bit_ndx < bit_len; bit_ndx++) {
int32_t one_count = 0;
int32_t total = 0;
int32_t keep_1 = 0;
for (int word_ndx = 0; word_ndx < len; word_ndx++) {
if (keep[word_ndx]) {
if (diagnostic_data[word_ndx].word[bit_ndx] == '1') {
one_count++;
}
total++;
}
}
if (total == 1) {
break;
}
if ((float)one_count >= ceil(total/2.0)) {
keep_1 = mode;
}
else {
keep_1 = !mode;
}
for (int word_ndx = 0; word_ndx < len; word_ndx++) {
if (keep[word_ndx]) {
if (diagnostic_data[word_ndx].word[bit_ndx] == '1') {
keep[word_ndx] = keep_1;
}
else {
keep[word_ndx] = !keep_1;
}
}
}
}
for (int word_ndx = 0; word_ndx < len; word_ndx++) {
if (keep[word_ndx]) {
return strtol(diagnostic_data[word_ndx].word, NULL, 2);
}
}
return -1;
}
void part_2(diagnostic_word_t * diagnostic_data, uint16_t len) {
int64_t oxygen_rating = get_rating(diagnostic_data, len, OXYGEN);
int64_t co2_rating = get_rating(diagnostic_data, len, CO2);
printf("PART 2: The life support rating is %ld * %ld = %ld", oxygen_rating, co2_rating, oxygen_rating*co2_rating);
}
static diagnostic_word_t diagnostic_data_g[DIAGNOSTIC_LEN];
int day_3() {
uint16_t len;
parse_ret_t parse_ret;
parse_ret = read_input_single_line("../inputs/day_3.txt", (void *) diagnostic_data_g, DIAGNOSTIC_LEN,
parse_diagnostic_data, &len);
if (parse_ret != PARSER_OK) {
printf("Unable to parse input data: %d", parse_ret);
return -1;
}
part_1(diagnostic_data_g, len);
part_2(diagnostic_data_g, len);
return 0;
}