-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday04.rb
More file actions
81 lines (74 loc) · 2.84 KB
/
day04.rb
File metadata and controls
81 lines (74 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# --- Day 4: Security Through Obscurity ---
#
# Finally, you come across an information kiosk with a list of rooms. Of course, the list is
# encrypted and full of decoy data, but the instructions to decode the list are barely hidden
# nearby. Better remove the decoy data first.
#
# Each room consists of an encrypted name (lowercase letters separated by dashes) followed by a
# dash, a sector ID, and a checksum in square brackets.
#
# A room is real (not a decoy) if the checksum is the five most common letters in the encrypted
# name, in order, with ties broken by alphabetization. For example:
#
# aaaaa-bbb-z-y-x-123[abxyz] is a real room because the most common letters are a (5), b (3), and
# then a tie between x, y, and z, which are listed alphabetically.
#
# a-b-c-d-e-f-g-h-987[abcde] is a real room because although the letters are all tied (1 of each),
# the first five are listed alphabetically.
#
# not-a-real-room-404[oarel] is a real room.
#
# totally-real-room-200[decoy] is not.
#
# Of the real rooms from the list above, the sum of their sector IDs is 1514.
#
# What is the sum of the sector IDs of the real rooms?
# --- Part Two ---
#
# With all the decoy data out of the way, it's time to decrypt this list and get moving.
#
# The room names are encrypted by a state-of-the-art shift cipher, which is nearly unbreakable
# without the right software. However, the information kiosk designers at Easter Bunny HQ were not
# expecting to deal with a master cryptographer like yourself.
#
# To decrypt a room name, rotate each letter forward through the alphabet a number of times equal
# to the room's sector ID. A becomes B, B becomes C, Z becomes A, and so on. Dashes become spaces.
#
# For example, the real name for qzmt-zixmtkozy-ivhz-343 is very encrypted name.
#
# What is the sector ID of the room where North Pole objects are stored?
#
require_relative 'input'
day = __FILE__[/\d+/].to_i(10)
input = Input.for_day(day)
# input = <<-EOF
# 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]
# EOF
# puts "solving day #{day} from input\n#{input.inspect}"
module Enumerable
def count_by
counts = Hash.new(0)
each {|e| counts[block_given? ? yield(e) : e] += 1}
counts
end
end
def checksum(string)
string.scan(/[a-z]/).count_by.sort_by {|l,c| [-c,l]}.map{|k,v|k}.first(5).join
end
parts = /\A([-a-z]+)-(\d+)[\[]([a-z]+)[\]]$/
total = 0
input.each_line do |room|
code, id, check = room.match(parts).captures
# puts({room: room, code: code, id: id, check: check, checksum: checksum(code)}.inspect)
if check == checksum(code)
total += id.to_i
plain = code.tr('-',' ')
(id.to_i % 26).times { plain = plain.tr(('a'..'z').to_a.join, [*('b'..'z').to_a, 'a'].join) }
puts({id: id, name: plain}.inspect) if plain == "northpole object storage"
end
end
puts total
# puts "should be 1514"