|
|
|
#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;
|
|
|
|
}
|