--- Day 13: Packet sort ---

December 13

Listening to: N64 Jungle Mix


Okay, the second one today. I took a break to go shopping for a white elephant gift, and it's... obnoxious and I love it. Whoever gets this gift is going to enjoy it. Or hate it. I'm not sure.

Either way, I'm going to do another AoC before I head over to that party.


This looks familiar... not quite the same, but the input has a similar format. I'll do something similar to what I did last year and make a nested class for it. It'll either be just a number, or a list of other itself.

For the sample code, they have a decent order of simple-to-complex rules and examples. I'll just keep building this out until all of the samples work, one-at-a-time. Annoyingly, the input data has digits 0-10, which means because of 10 existing, I can't just look at the characters. I have to actually be a little smart about parsing.

class PacketList {
    public:    
        enum Type { Number, List } type;
        int num;
        vector<PacketList> items;

        PacketList(int n) { type = Number; num = n; }
        PacketList(string s)
        {
            type = List;

            // Strip outermost brackets
            s = s.substr(1, s.size()-2);
            int i = 0;

            while (i < s.size())
            {
                switch(s[i])
                {                    
                    // Somehow a comma, just move on
                    case ',': i++; break;

                    // If list, find matching close bracket and call recursively
                    case '[': 
                    {
                        int bracketCount = 1, j = i + 1;
                        while (bracketCount > 0)
                        {
                            switch (s[j++])
                            {
                                case '[': bracketCount++; continue;
                                case ']': bracketCount--; continue;
                            }
                        }
                        items.push_back(PacketList(s.substr(i, j-i)));
                        i = j+1;
                        break;
                    }

                    // Assumed digit
                    default:
                        {
                            int t = 0;
                            while (i < s.size() && s[i] != ',')
                            {
                                t *= 10;
                                t += s[i] - '0';
                                i++;
                            }
                            items.push_back(PacketList(t));
                            i++;
                            break;
                        }
                }
            }
        }
};

Maybe not the cleanest code, but it works. There was probably an easier way, but this runs efficiently enough. Now to tackle the actual comparison logic.

// -1 == false, 1 == true, 0 == continue
int Compare (PacketList left, PacketList right)
{
    int i = 0;
    while(i < left.items.size())
    {
        if (right.items.size() <= i) return -1;

        PacketList l = left.items[i];
        PacketList r = right.items[i];

        // Convert number to list, if necessary
        if (l.type != r.type) { l.convert(); r.convert(); }

        switch (l.type)
        {
            case PacketList::Type::Number:
                if (l.num < r.num) return 1;
                if (l.num > r.num) return -1;
                i++;
                continue;

            case PacketList::Type::List:
                {
                    int result = Compare(l, r);
                    if (result > 0) return 1;
                    if (result < 0) return -1;
                    i++;
                    continue;
                }
        }
    }

    if (left.items.size() < right.items.size()) return 1;
    return 0;
}

Shockingly easy to do once I had the data structure down!


Oookay, now it's time to order packets? Hmm. I made a comparitor already, so I just need to put everything into a list and compare everything together using sort(). Will that work though?

It did. It was that simple. I just needed to add a wrapper function to convert it to a bool.

bool CompareSort(PacketList left, PacketList right)
{    
    return Compare(left, right) == 1;
}

//...

sort(packets.begin(), packets.end(), CompareSort);

Amazingly easy. It taught me to make a comparitor function just to compare two, then had me do it for a sort function. Awesome that it just worked immediately.


Time taken: 1 hour 20 minutes

My solutions for today's puzzles