# Encoding Error

`2020-12-09`

Original Prompt ## Part 1

Once again, we don’t have to do anything too fancy here. Summing numbers is fast, so it’s ok if we do it a lot. Combining that with a `set`

for fast lookup and we can safely repeat a lot of work.

On each step of our loop, we want an element and all of the sums for the 25 previous elements. I use a `PREAMBLE_SIZE`

variable so I could easily set it to `5`

and `25`

for testing as needed, but it’s not super necessary.

We’ll look at each index starting at `PREAMBLE_SIZE`

:

`for i in range(PREAMBLE_SIZE, len(self.input)):`

Next, the sums. Just like day 1, we’ll reach for `itertools.combinations`

:

`sums = { sum(pair) for pair in combinations(self.input[i - PREAMBLE_SIZE : i], 2)}`

This strikes me as a great example of Python code being both readable and concise (not to toot my own horn). Each piece should be familiar:

`self.input[i - PREAMBLE_SIZE : i]`

gets the 25 elements directly before our index`combinations(X, 2)`

gets us all of our pairs (like`[(1, 2), (2, 3), (1, 3)]`

)`{sum(pair) for pair in X}`

gives us a set of each of those sums

Lastly, we run through our loop and return the number that isn’t in the set:

`if self.input[i] not in sums: return self.input[i]`

## Part 2

This is another day where my `solve`

function comes into play (running both parts at once instead of doing it separately). The answer from `part_1`

is stored as `bad_num`

.

This will be another brute-force approach. We have to step very slowly through the input, taking an increasingly large range until we meet or exceed the `bad_num`

.

We start at the very beginning and initialize a running sum:

`for range_start in range(len(self.input)): running_sum = self.input[range_start] = self.input[range_start]`

Then, we iterate again (which feels unavoidable at this point), incrementally summing the ongoing range until either:

`running_sum == bad_num`

, in which case we can finish`running_sum > bad num`

, so we have to start a new range

`for range_end in range(range_start + 1, len(self.input)): running_sum += self.input[range_end] if running_sum == bad_num: continuous_range = self.input[range_start : range_end + 1] return bad_num, min(continuous_range) + max(continuous_range) if running_sum > bad_num: break`

This is another example where we can get away with returning from deep in a loop because we *know* we’ll get there sometime. Otherwise we’d need a plan for if we fail-to-find.