# Advent of Code 2016, Day 4: Security Through Obscurity

## Part A

On Day 4 we are dealing with checksums. We are given strings describing rooms. Each string containts multiple parts: name, sector id and checksum. Our task is to verify which strings are valid by calculating checksum and comparing it with the checksum in the string.

Our input looks like this:

``````aaaaa-bbb-z-y-x-123[abxyz]
a-b-c-d-e-f-g-h-987[abcde]
not-a-real-room-404[oarel]
totally-real-room-200[decoy]
``````

To calculate checksum we need to count occurences of characters and then sort them in the descending order. In case of ties we need to sort alphabetically. For first example string we have 5 times ‘a’, 3 times ‘b’, 1 time ‘x’, 1 time ‘y’ and 1 time ‘z’. The checksum should be abxyz and it is so the string is valid.

Here is my solution:

``````data = File.readlines("4.txt").map(&:strip)
sum = 0

data.each do |room|
name, sector, checksum = room.match(/([a-z\-]+)-(\d+)\[(.+)\]/).captures
name.gsub!("-", "")

chars = Hash.new { |hash, key| hash[key] = 0 }
name.chars.each { |char| chars[char] += 1 }

sorted = chars.to_a.sort do |a, b|
res = b[1] <=> a[1]

if res == 0
a[0] <=> b[0]
else
res
end
end

calculated = sorted[0..4].map { |elem| elem[0] }.join

if calculated == checksum
sum += sector.to_i
end
end

puts sum
``````

In the `sort` block we are first trying to compare both items by their occurence count. We use Ruby spaceship <=> operator and it case of equal values it will return 0. So if we get a 0 we need to them compare them alphabetically.

## Part B

In second part we need to decrypt the names of rooms, so we are interested in the first part of the string and the sector id. Strings are encrypted with kind of Caesar cipher with sector id being an offset. We just need to iterate over each char and shift it given amount of times. Here is my solution:

``````data = File.readlines("4.txt", chomp: true)

data.each do |room|
name, sector, checksum = room.match(/([a-z\-]+)-(\d+)\[(.+)\]/).captures

decrypted = name.chars.map do |char|
if char == "-"
" "
else
value = char.ord - 'a'.ord
value = ((value + sector.to_i) % 26) + 'a'.ord

value.chr
end
end.join

if decrypted =~ /north/
puts sector
end
end
``````

This part `value = char.ord - 'a'.ord` converts any char into alphabet index starting from 0. ‘a’ is 0, ‘b’ is 1, ‘c’ is 2 and so on. It is easier to shift integers as we can just add to it. Them we can convert it back into character by adding `'a'.ord` and calling `value.chr`.