Phew… This took a lot of googling to get right. Working with unstructured data in Go wasn’t as simple as I’m used to from JS. Having said that, I think the outcome is quite alright.
The communication device is still acting up… We receive a distress signal but it seems like the packets are arriving out of order (our puzzle input).
Packet pairs are separated by an empty line and the packet data is represented as integers and a list of integers.
Example
|
|
Parsing
Splitting parsing into two parts:
- Parse the raw input into pairs of packets
- Deserialize each packet
Parse the raw data into packets pairs
From the question description, we know that packets are separated into pairs that and each pair is separated by an empty line Within a pair, each packet is on its on line.
|
|
At this stage, our data looks something like this
|
|
Deserialize each packet
Let’s take that string and construct something meaningful from that, in our case, it’s going to be an array of integers and arrays.
Luckily for us, the packets are a valid JSON string, we can use Go built-in json.Unmarshal function.
The json.Unmarshal
accepts our JSON string in byte formats and some variables to assign the results to.
Ideally, we would like the variable we assign the results to have a type that reflects that recursive nature but as far as I can tell it’s not possible in go.
|
|
Instead, we will assign the results to variables of type any
and handle the different types in our logic using type assertion.
Our parse
function now looks like this
|
|
Part 1
We are asked to find valid pairs of packets and sum up their indexes.
But what exactly is an invalid pair of packets you ask?!
For each index i
in our pair of packets, we need to make sure that the following holds
There is some index i
such that left[i] < right[i]
, if at any index j
where j < i
we find that left[j] > right[j]
or we run out of items in our right
packet before our left
we say that that packet pair as invalid!
Example
|
|
Now we need to write the actual logic that enforces those rules.
The first thing we notice is that on equal numbers we keep going until we find a violation or we succeed, this means that a simple true
/false
return value is not sufficient. We need a way to say lower
, equal
, and greater
, we can do just that using simple subtraction and setting 0
as our equal
point, and greater
marks an invalid packet pair
We will start by writing a compare
function that takes left
and right
as arguments and using type assertion validate that they are of type array
.
|
|
We will build our logic based on isLeftArray
and isRightArray
, they represent the success or failure of the assertion, basically answering the question “Is it an array of any type?”
We now have 5 cases to deal with
- Both are not arrays -> return
left
-right
- Only
left
is not an array -> wrapleft
in an array and callcompare
- Only
right
is not an array -> wrapright
in an array and callcompare
- Both are not arrays -> call
compare
for each element in range - We run out of items -> subtract the
len
of each side
|
|
When both left
and right
are not arrays we cast them to float64
since that’s the actual type the deserialization gave us back and not an int
We have a working compare
function, let’s utilize it in our solution
|
|
Adding 2 to each index to compensate for the fact that we start from zero and then divide by 2 to account for
i
jumping 2 steps on each iteration
Part 2
Now, you just need to put all of the packets in the right order. Disregard the blank lines in your list of received packets.
We are asked to add two divider packets [[2]]
and [[6]]
to our received packets, then sort our packets in the right order according to the rules described in part 1.
After we sort our packets we need to find the divider packets indexes and multiply them together to get our answer for part 2. easy peasy!
Luckily for us, we created our compare function in a way we can easily reuse to sort our packets.
|
|
The only other thing to note here is how we find the divider packets, what I did is pretty shitty but all of those types gave me a major headache and I ended up stratifying the packets and comparing the actual strings.
A better solution will be to maybe pack them in a struct and assign IDs, pass pointers instead of values so we can compare the memory addresses or assert the length is one and the values are either 2 or 6.
That’s it for today, see you tomorrow ⭐️
You can find the complete code here Thanks for reading!
This post is number 13 of a 13 posts series > Learning Go.