Something is jamming your communications with Santa. Fortunately, your signal is only partially jammed, and protocol in situations like this is to switch to a simple repetition code to get the message through.
In this model, the same message is sent repeatedly. You've recorded the repeating message signal (your puzzle input), but the data seems quite corrupted - almost too badly to recover. Almost.
All you need to do is figure out which character is most frequent for each position. For example, suppose you had recorded the following messages:
eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar
The most common character in the first column is e
; in the second, a
; in the third, s
, and so on. Combining these characters returns the error-corrected message, easter
.
Given the recording in your puzzle input, what is the error-corrected version of the message being sent?
So all we need to do here is to keep track of which characters are the most frequent at the given position? Hah! Easy-peasy. We'll simply use the Counter
from collections
, which I've described in a previous puzzle. We need counters for each position in the input. We're making a few assumptions here:
- all input lines are of the same length
- what happens in case of ties is not specified, so we will not deal with it
To create the appropriate number of counters, we inspect the first line and then create as many counters as its length, and store them in a list. This way, we can match the specific index of the counter with the index in the string. To get the most common element from the counter, we use the most_common(n)
method, which returns n
most common elements (we want only 1).
- Read input
- Create a list of counters of length as the first line of input
- For each line in input:
- For each character in input, add character to counter
- For each counter, get the most common character
In [1]:
with open('../inputs/day06.txt', 'r') as f:
data = [line.strip() for line in f.readlines()]
Creating counters
In [2]:
from collections import Counter
counters = [Counter() for i in range(0, len(data[0]))]
Reading characters from input, and counting them. To add an item to the counter, simply increment its value.
In [3]:
for line in data:
for index, char in enumerate(line):
counters[index][char] += 1
Get the most common element from each counter. Since the most_common
method returns a list of tuples (key-value), we need to access the first element from each of them respectively. And finally join them together into a string to get the string.
In [4]:
answer = ''.join([counter.most_common(1)[0][0] for counter in counters])
Of course, that would be the message - if you hadn't agreed to use a modified repetition code instead.
In this modified code, the sender instead transmits what looks like random data, but for each character, the character they actually want to send is slightly less likely than the others. Even after signal-jamming noise, you can look at the letter distributions in each column and choose the least common letter to reconstruct the original message.
In the above example, the least common character in the first column is a
; in the second, d
, and so on. Repeating this process for the remaining characters produces the original message, advent
.
Given the recording in your puzzle input and this new decoding methodology, what is the original message that Santa is trying to send?
Small change - instead of most common, we now need the least common characters from the counters. Thankfully, since the counter returns a nice sorted list in most_common
, we can use that to get the least common element - it's the one that is last!!!
characters = counter.most_common()[-1]
That being done, we combine the characters back into a string to get the answer.
In [5]:
answer = ''.join([counter.most_common()[-1][0] for counter in counters])
== END ==