229 lines
5.9 KiB
C
229 lines
5.9 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "puzzle_input.h"
|
|
#include "day.h"
|
|
|
|
#define SIGNAL_PATTERN_DIGITS 10
|
|
#define OUTPUT_DIGITS 4
|
|
#define MAX_ENTRIES 1000
|
|
|
|
typedef struct {
|
|
uint8_t signal_patterns[SIGNAL_PATTERN_DIGITS];
|
|
uint8_t outputs[OUTPUT_DIGITS];
|
|
} display_entry_t;
|
|
|
|
parse_ret_t parse_display(char * display_str, uint8_t * display_state) {
|
|
while (*display_str != '\0') {
|
|
uint8_t bit_to_set;
|
|
if (*display_str < 'a' || *display_str > 'g') {
|
|
return PARSER_INVALID;
|
|
}
|
|
|
|
bit_to_set = *display_str - 'a';
|
|
|
|
*display_state |= 1 << bit_to_set;
|
|
|
|
display_str++;
|
|
}
|
|
|
|
return PARSER_OK;
|
|
}
|
|
|
|
parse_ret_t parse_display_group(char * display_group_str, uint8_t * display_group, uint16_t display_group_max_len) {
|
|
char * tok = strtok(display_group_str, " ");
|
|
uint16_t display_index = 0;
|
|
|
|
if (display_group_str == NULL) {
|
|
return PARSE_NULL;
|
|
}
|
|
|
|
while (tok != NULL) {
|
|
parse_ret_t ret = parse_display(tok, &display_group[display_index]);
|
|
|
|
if (ret != PARSER_OK) {
|
|
return ret;
|
|
}
|
|
tok = strtok(NULL, " ");
|
|
display_index++;
|
|
|
|
if (display_index > display_group_max_len) {
|
|
return PARSER_RANGE_OVERFLOW;
|
|
}
|
|
}
|
|
|
|
if (display_index != display_group_max_len) {
|
|
return PARSER_INVALID;
|
|
}
|
|
|
|
return PARSER_OK;
|
|
}
|
|
|
|
parse_ret_t parse_display_entry(char * buffer, void * data, uint16_t index) {
|
|
display_entry_t * display_entries = (display_entry_t *)data;
|
|
char * signal_patterns = strtok(buffer, "|");
|
|
char * outputs = strtok(NULL, "|");
|
|
display_entry_t * entry = &display_entries[index];
|
|
parse_ret_t res;
|
|
|
|
res = parse_display_group(signal_patterns, entry->signal_patterns, SIGNAL_PATTERN_DIGITS);
|
|
|
|
if (res != PARSER_OK) {
|
|
return res;
|
|
}
|
|
|
|
res = parse_display_group(outputs, entry->outputs, OUTPUT_DIGITS);
|
|
if (res != PARSER_OK) {
|
|
return res;
|
|
}
|
|
|
|
return PARSER_OK;
|
|
}
|
|
|
|
uint8_t count_bits(uint8_t val) {
|
|
uint8_t on_count = 0;
|
|
for (int bit_ndx = 0; bit_ndx < 7; bit_ndx++) {
|
|
if ((val >> bit_ndx) & 0b1) {
|
|
on_count++;
|
|
}
|
|
}
|
|
|
|
return on_count;
|
|
}
|
|
|
|
static void part_1(display_entry_t * entries, uint16_t entry_len) {
|
|
uint32_t easy_digit_count = 0;
|
|
for (int entry_ndx = 0; entry_ndx < entry_len; entry_ndx++) {
|
|
display_entry_t * entry = &entries[entry_ndx];
|
|
uint32_t count_per_row = 0;
|
|
for (int disp_ndx = 0; disp_ndx < OUTPUT_DIGITS; disp_ndx++) {
|
|
uint8_t on_count = count_bits(entry->outputs[disp_ndx]);
|
|
|
|
switch (on_count) {
|
|
case 2: // 1
|
|
case 4: // 4
|
|
case 3: // 7
|
|
case 7: // 8
|
|
count_per_row++;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
easy_digit_count += count_per_row;
|
|
}
|
|
|
|
printf("PART 1: Easy digit count is: %u\n", easy_digit_count);
|
|
}
|
|
|
|
static uint8_t fix_wire_crossing(uint8_t state, uint8_t crossed_four, uint8_t crossed_7) {
|
|
uint8_t new_state;
|
|
|
|
uint8_t on_count = count_bits(state);
|
|
|
|
switch (on_count) {
|
|
case 2: // 1
|
|
new_state = 1;
|
|
break;
|
|
case 3: // 7
|
|
new_state = 7;
|
|
break;
|
|
case 4: // 4
|
|
new_state = 4;
|
|
break;
|
|
case 5: // 2, 3, 5
|
|
if ((state & crossed_7) == crossed_7) {
|
|
new_state = 3;
|
|
}
|
|
else if (count_bits(state & crossed_four) == 3) {
|
|
new_state = 5;
|
|
}
|
|
else {
|
|
new_state = 2;
|
|
}
|
|
break;
|
|
case 6: // 0, 6, 9
|
|
if ((state & crossed_four) == crossed_four) {
|
|
new_state = 9;
|
|
}
|
|
else if ((state & crossed_7) == crossed_7) {
|
|
new_state = 0;
|
|
}
|
|
else {
|
|
new_state = 6;
|
|
}
|
|
break;
|
|
case 7: // 8
|
|
new_state = 8;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return new_state;
|
|
}
|
|
|
|
static void part_2(display_entry_t * entries, uint16_t entry_len) {
|
|
uint32_t sum = 0;
|
|
for (int entry_ndx = 0; entry_ndx < entry_len; entry_ndx++) {
|
|
display_entry_t * entry = &entries[entry_ndx];
|
|
uint8_t crossed_4 = 0;
|
|
uint8_t crossed_7 = 0;
|
|
for (int disp_ndx = 0; disp_ndx < OUTPUT_DIGITS + SIGNAL_PATTERN_DIGITS; disp_ndx++) {
|
|
uint8_t display_state;
|
|
|
|
if (disp_ndx < SIGNAL_PATTERN_DIGITS) {
|
|
display_state = entry->signal_patterns[disp_ndx];
|
|
}
|
|
else {
|
|
display_state = entry->outputs[disp_ndx-OUTPUT_DIGITS];
|
|
}
|
|
|
|
uint8_t bit_count = count_bits(display_state);
|
|
if (bit_count == 4) {
|
|
crossed_4 = display_state;
|
|
}
|
|
else if (bit_count == 3) {
|
|
crossed_7 = display_state;
|
|
}
|
|
}
|
|
|
|
if (crossed_7 == 0 || crossed_4 == 0) {
|
|
printf("oopsie woopise, a lil fucky wucky\n");
|
|
return;
|
|
}
|
|
|
|
for (int disp_ndx = 0; disp_ndx < OUTPUT_DIGITS; disp_ndx++) {
|
|
uint8_t display_state = entry->outputs[disp_ndx];
|
|
uint8_t val = fix_wire_crossing(display_state, crossed_4, crossed_7);
|
|
sum += (val * (int32_t)pow(10, (OUTPUT_DIGITS-disp_ndx-1)));
|
|
}
|
|
|
|
}
|
|
|
|
printf("PART 2: Output sum: %d\n", sum);
|
|
}
|
|
|
|
|
|
display_entry_t entries_g[MAX_ENTRIES] = {0};
|
|
|
|
int day_8() {
|
|
parse_ret_t res;
|
|
uint16_t display_len;
|
|
|
|
res = read_input_single_line("../inputs/day_8.txt", (void *)entries_g, MAX_ENTRIES, parse_display_entry, &display_len);
|
|
|
|
if (res != PARSER_OK) {
|
|
printf("Unable to parse input: %d\n", res);
|
|
return -1;
|
|
}
|
|
|
|
part_1(entries_g, display_len);
|
|
part_2(entries_g, display_len);
|
|
|
|
|
|
return 0;
|
|
}
|