--- Day 3: Diagnostic ---

December 3

Listening to: Synthwave


This was just posted about 15 minutes ago, and yet the leaderboards are already packed. I guess the last slot, #100, took 10 minutes from posting. I better get on the ball tomorrow if I want to try for the leaderboards, but I'm just having fun with it as is.

Anyway, the problem. Reading a not-user-friendly self-diagnostic report. Lovely. It even has to do with bit manipulation. Sort of. It's... kinda counting bits? It'll be a bit of a headache.

Also a headache? Initializing arrays. It didn't initialize like I thought, so I got weird results the first few runs. And I did bitshifting out of order a bit. But it works now.

string line;
int lines = 0;
int sums[12] = {};

// Read in counts of inputs
while (input >> line) {
    lines++;
    for (int i = 0; i < 12; i++)
        if (line.at(i) == '1') sums[i]++;
}
int hline = lines / 2;

// Calculate Gamma and Epsilon
int gamma = 0, epsilon = 0;
for (int j = 0; j < 12; j++) {
    gamma <<= 1; epsilon <<= 1;
    sums[j] > hline ? gamma += 1 : epsilon += 1;
}

That was fun, and even made a nice little readout for it all!


Oh god, this is a long read. It looks like it's STILL using the same input file, so I can reuse some of the code most likely, but it's still a lot of text...

Okay, it seems pretty simple. It looks like for each of the two values that it's looking for, it wants the one with the MOST common bits in each position, and the LEAST common bits. This builds off of the code I wrote for the previous one, with a few modifications, but is basically the same. The filtering may be a bit of a PITA though.

~

Especially fun, this time, I decided to look at lambdas. I've used them in other languages, but with the heavier scoping and pointer fun of C++, I have never checked them out before. Looks super weird, but I managed to get it working. Somewhat.

// Calculate Oxygen rating
vector<string> oxygen (lines);
int i = 0;
while (oxygen.size() > 1  && i < 12)
{
    vector<string> candidates;
    char target = sums[i] > hline ? '1' : '0';

    std::copy_if(oxygen.begin(), oxygen.end(), std::back_inserter(candidates),
        [&i, &target](string s){ return s.at(i) == target; });

    oxygen = candidates;
    i++;
}

~

Okay I got oxygen working fine, but when I adapted it for the co2, it was just... not working. It turns out it was an off by one error, than I only got when I re-read this line in the text VERY carefully:

If 0 and 1 are equally common, keep values with a 0 in the position being considered.

Yep. An off-by-one error in my original counting code, that somehow didn't matter in the first part, or in the oxygen counting. Ah well. an easy fix, and I'm basically done.

~

UGH. I got it wrong. It's the most common bit IN THE REMAINING SET. Ugh. I feel dumb.

At least I still can use some of this code. I just need to be a bit more clever about it.

~

Well THAT took a long time. Even afterwards, I had to poke around with some off-by-one errors. I had to pull out my summing code and rework things quite a bit.

void getSums(vector<string> input, int* sums) 
{
    sums[width] = {};

    for (auto line : input)
        for (int i = 0; i < width; i++)
            if (line.at(i) == '1') sums[i]++;
}
vector<string> oxygen (lines);
int i = 0;
while (oxygen.size() > 1  && i < width)
{
    vector<string> candidates;
    int sums[width] = {};
    getSums(oxygen, sums);
    char target = sums[i] >= ((oxygen.size()+1)/2) ? '1' : '0';

    std::copy_if(oxygen.begin(), oxygen.end(), std::back_inserter(candidates),
        [&i, &target](string s){ return s.at(i) == target; });

    oxygen = candidates;
    i++;
}

I have an ache in my neck now. But I did it.


My solutions for today's puzzles