You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
6.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#define ARR_LEN (1000)
#define BIT_AMOUNT (12)
#define INPUT_FILE ("input.txt")
#define BIT_MASK (0xFFF)
// read file, dump into diagnostics and count bits
void d3_init(int* diagnostics, size_t diag_len,
int* bit_ct, size_t bit_ct_len);
// return answer for part one
int d3_part_one(int* diagnostics, size_t diag_len,
int* bit_ct, size_t bit_ct_len);
// returns answer for part two
int d3_part_two(const int* const diagnostics, size_t diag_len);
// if binary we're assuming bit size is 12 because this project is specific to 12 bit numbers
static void print_arr(const int* const arr, size_t len, bool binary)
{
if(binary)
{
printf("\n");
for(int ind = 0; ind < len; ind++)
{
printf("[%d]: ", ind);
for(int bit = BIT_AMOUNT - 1; bit >= 0; bit--)
{
printf("%d", ((arr[ind] & (1 << bit))>>bit));
}
printf("\n");
}
}
else
{
for(int ind = 0; ind < len; ind++)
{
printf("[%d]: %d\n", ind, arr[ind]);
}
}
}
int main(int argc, char** argv)
{
int diagnostic_arr[ARR_LEN];
int bit_ct[BIT_AMOUNT];
memset(diagnostic_arr, 0, ARR_LEN * sizeof(int));
memset(bit_ct, 0, BIT_AMOUNT * sizeof(int));
d3_init(diagnostic_arr, ARR_LEN, bit_ct, BIT_AMOUNT);
int power_consumption = d3_part_one(diagnostic_arr, ARR_LEN, bit_ct, BIT_AMOUNT);
printf("(Part 1 Answer) Power Consumption: %d\n", power_consumption);
int life_support_rating = d3_part_two(diagnostic_arr, ARR_LEN);
printf("(Part 2 Answer) Life support rating: %d\n", life_support_rating);
return 0;
}
// read file, dump into diagnostics and count bits
void d3_init(int* diagnostics, size_t diag_len,
int* bit_ct, size_t bit_ct_len)
{
FILE* fp = fopen(INPUT_FILE, "r");
if(!fp)
{
printf("Failed to open file for reading...\n");
exit(-1);
}
char* line = NULL;
size_t len = 0;
for(int ind = 0; ind < ARR_LEN; ind++)
{
ssize_t rc = getline(&line, &len, fp);
if(rc == -1)
{
printf("EXITING ABNORMALLY\n");
exit(-1);
}
diagnostics[ind] = strtol(line, NULL, 2);
for(int bit = 0; bit < BIT_AMOUNT; bit++)
{
printf("%d", (diagnostics[ind] & (1<<bit))>>bit);
bit_ct[bit] += ((diagnostics[ind] & (1 << bit))>>bit);
}
printf("\n");
}
fclose(fp);
}
// returns status of init
int d3_part_one(int* diagnostics, size_t diag_len,
int* bit_ct, size_t bit_ct_len)
{
int gamma = 0;
int epsilon = 0;
for(int bit = 0; bit < bit_ct_len; bit++)
{
gamma += ((bit_ct[bit] > (ARR_LEN >> 1))<<bit);
}
epsilon = (~gamma) & BIT_MASK;
printf("Epsilon: %d\t gamma: %d\n", epsilon, gamma);
return gamma * epsilon;
}
// returns answer for part two
// we can use the answer from part 1 to cut out a lot of unnecessary instructions
int d3_part_two(const int* const diagnostics, size_t diag_len)
{
int o2_gen_rating = 0;
int co2_scrubber_rating = 0;
int ans = 0;
// alternating active buffers
int diag_copy[2][ARR_LEN + 1];
// we copy diagnostics into our second diag_copy arr
// this way we start with diag_copy[0] being zeroed
// and diag_copy[1] having our original data.
// from there we will go back and forth, filtering data
// from eachother
memcpy(&diag_copy[(~(BIT_AMOUNT - 1)%2) & 0x01], diagnostics, diag_len * sizeof(int));
// last value will be active count, i.e. how many vars are actually in the array
diag_copy[(BIT_AMOUNT - 1)%2][ARR_LEN] = 0;
diag_copy[(~(BIT_AMOUNT - 1)%2) & 0x01][ARR_LEN] = ARR_LEN;
// finding oxygen generator rating
for(int bit = BIT_AMOUNT - 1; bit >= 0; bit--)
{
int* ctr_write = &diag_copy[bit%2][ARR_LEN];
int* ctr_read = &diag_copy[~(bit%2) & 0x01][ARR_LEN];
int* diag_write = diag_copy[bit%2];
const int* diag_read = diag_copy[~(bit%2) & 0x01];
memset(diag_write, 0, (sizeof(int) * ARR_LEN) + sizeof(int));
volatile int bit_ct = 0;
for(int ind = 0; ind < *ctr_read; ind++)
{
if((diag_read[ind] >> bit) & 0x01)
{
bit_ct++;
}
}
for(int ind = 0; ind < *ctr_read; ind++)
{
if(bit_ct >= (*ctr_read - bit_ct))
{
if((diag_read[ind] >> bit) & 0x01)
diag_write[(*ctr_write)++] = diag_read[ind];
}
else
{
if(!((diag_read[ind] >> bit) & 0x01))
{
diag_write[(*ctr_write)++] = diag_read[ind];
}
}
}
if(*ctr_write <= 1)
{
printf("found o2 rating\n");
o2_gen_rating = diag_write[*ctr_write-1];
break;
}
}
printf("o2 rating: %d\n", o2_gen_rating);
// now we need to do a similar thing for co2 scubber rating
// this time we want to find the least common bit instead of most common bit
// we copy diagnostics into our second diag_copy arr
// this way we start with diag_copy[0] being zeroed
// and diag_copy[1] having our original data.
// from there we will go back and forth, filtering data
// from eachother
memcpy(&diag_copy[(~(BIT_AMOUNT - 1)%2) & 0x01], diagnostics, diag_len * sizeof(int));
// last value will be active count, i.e. how many vars are actually in the array
diag_copy[(BIT_AMOUNT - 1)%2][ARR_LEN] = 0;
diag_copy[(~(BIT_AMOUNT - 1)%2) & 0x01][ARR_LEN] = ARR_LEN;
// finding oxygen generator rating
for(int bit = BIT_AMOUNT - 1; bit >= 0; bit--)
{
int* ctr_write = &diag_copy[bit%2][ARR_LEN];
int* ctr_read = &diag_copy[~(bit%2) & 0x01][ARR_LEN];
int* diag_write = diag_copy[bit%2];
const int* diag_read = diag_copy[~(bit%2) & 0x01];
memset(diag_write, 0, (sizeof(int) * ARR_LEN) + sizeof(int));
int bit_ct = 0;
for(int ind = 0; ind < *ctr_read; ind++)
{
if((diag_read[ind] >> bit) & 0x01)
{
bit_ct++;
}
}
for(int ind = 0; ind < *ctr_read; ind++)
{
if(bit_ct < (*ctr_read - bit_ct))
{
if((diag_read[ind] >> bit) & 0x01)
diag_write[(*ctr_write)++] = diag_read[ind];
}
else
{
if(!((diag_read[ind] >> bit) & 0x01))
{
diag_write[(*ctr_write)++] = diag_read[ind];
}
}
}
if(*ctr_write <= 1)
{
printf("found co2 \n");
co2_scrubber_rating = diag_write[*ctr_write-1];
break;
}
}
printf("o2 gen rating: %d\nco2 scrubber rating: %d\n", o2_gen_rating, co2_scrubber_rating);
return co2_scrubber_rating * o2_gen_rating;
}