Skip to content

Instantly share code, notes, and snippets.

@tdlm
Last active December 9, 2016 21:24
Show Gist options
  • Save tdlm/267d93ba077946e17f7b60b03831fc71 to your computer and use it in GitHub Desktop.
Save tdlm/267d93ba077946e17f7b60b03831fc71 to your computer and use it in GitHub Desktop.
Advent of Code
#!/bin/ruby
require "test/unit"
class GridMap
CARDINAL="NESW"
def initialize(directions)
@face = 'N'
@pointing = 0
@x = 0
@y = 0
@directions = directions.split(', ')
end
def get_distance_from_origin
@directions.each do |move|
direction, steps = move.match(/([RL])(\d+)/i).captures
steps = steps.to_i
turn(direction)
step(steps)
end
return (@x).abs + (@y).abs
end
def turn(direction)
@pointing += 1 if direction == 'R'
@pointing -= 1 if direction == 'L'
@pointing = 0 if @pointing > 3
@pointing = 3 if @pointing < 0
@face = CARDINAL[@pointing]
end
def step(steps)
case @face
when 'N'
@y += steps
when 'S'
@y -= steps
when 'E'
@x += steps
when 'W'
@x -= steps
end
end
end
class TestGridMap < Test::Unit::TestCase
def test_one
mapper = GridMap.new('R2, L3')
assert_equal(5, mapper.get_distance_from_origin)
end
def test_two
mapper = GridMap.new('R2, R2, R2')
assert_equal(2, mapper.get_distance_from_origin)
end
def test_three
mapper = GridMap.new('R5, L5, R5, R3')
assert_equal(12, mapper.get_distance_from_origin)
end
def test_four
mapper = GridMap.new('R4, R5, L5, L5, L3, R2, R1, R1, L5, R5, R2, L1, L3, L4, R3, L1, L1, R2, R3, R3, R1, L3, L5, R3, R1, L1, R1, R2, L1, L4, L5, R4, R2, L192, R5, L2, R53, R1, L5, R73, R5, L5, R186, L3, L2, R1, R3, L3, L3, R1, L4, L2, R3, L5, R4, R3, R1, L1, R5, R2, R1, R1, R1, R3, R2, L1, R5, R1, L5, R2, L2, L4, R3, L1, R4, L5, R4, R3, L5, L3, R4, R2, L5, L5, R2, R3, R5, R4, R2, R1, L1, L5, L2, L3, L4, L5, L4, L5, L1, R3, R4, R5, R3, L5, L4, L3, L1, L4, R2, R5, R5, R4, L2, L4, R3, R1, L2, R5, L5, R1, R1, L1, L5, L5, L2, L1, R5, R2, L4, L1, R4, R3, L3, R1, R5, L1, L4, R2, L3, R5, R3, R1, L3')
assert_equal(250, mapper.get_distance_from_origin)
end
end
#!/bin/ruby
require "test/unit"
class KeypadLock
PADLOCK=[ '123',
'456',
'789' ]
def initialize(instructions)
@instructions = instructions.split("\n")
@pointer = 5
@code = ''
end
def determine_code
@instructions.each do |instruction|
instruction.split('').each do |move|
move(move)
end
@code << @pointer.to_s
end
@code.to_i
end
def move(direction)
case direction
when 'U'
@pointer -= 3 if ![1, 2, 3].include?(@pointer)
when 'D'
@pointer += 3 if ![7, 8, 9].include?(@pointer)
when 'L'
@pointer -= 1 if ![1, 4, 7].include?(@pointer)
when 'R'
@pointer += 1 if ![3, 6, 9].include?(@pointer)
end
end
end
class TestPadLock < Test::Unit::TestCase
def test_one
instructions = "ULL\nRRDDD\nLURDL\nUUUUD"
padlock = KeypadLock.new(instructions)
code = padlock.determine_code
assert_equal(1985, code)
end
def test_two
instructions = "LLLUDRDLLULDUDLLRLUDURULDURRRRLLURLDLDDDULLDDUDLRDLRDUURRDUUDLLRUUDDLULURDLRDUUDUDRURULLLLDRULDDLRDDRDLRDDLURLDDUDLLUUDLRDDDDLULUUURRDLUUDDLULLURRRDULLUDUDRDRDDRLDLLRLRDDDRDLULLUULDLLLRRDDUURUURDLLDRRDDLRULDLLDRLLUDRRDLUUULDLURLLDDURRUULLLLLRLUDLDDLLLURRRDUDULRULULDDLLDLRDDDUULRLRDUURLURRUDDURRUUDUDLDDLDULDDDDDULRULRDLRLDLRDLDDLUDRDUUDLDUDUDLLLRLUUDRUDDDRDRURRLLLDLUULDUULRDLULLUURLDRRRLDRLUDRRURLDULULDRUDDULLLDRDLLULUDDDDRDRULDULRRRRDDRULDLRDU\nDLDDRRDLLDUURRLULLLLRDRLUDURLDRRDURRRRUUDDUDRRDDDRRLDDLDDLURDLDRLUDULDUDUUDDDLLULRRLLUDULLLUULDDRDDUDUUDULURULULLDRLRUURDRDDLRRUDRUULLLLURRUDRDULDDRURRURLLLLLRLLLRLLUDUDLRDLULDUDLULLLUUDLLDDDUDUDLLRRDLRDLLLRRLRUDRDUDRURLUUURULLDDDDLLURDULURRLLLRLRRULLRRRLUUULLLLRLRDUURRDUURLLLDRDURRRULDDUDRRDLRLDLLRUDDLLUDRLLUUDRLLLLLLUDLURLLRUDRUUUULDLUDULLDDDDRLURUURDDDURRRLRLUDUUDURDDDDRRLRDLURDDLLULDRDDURLLURULUUUUURDUUULDRRLLURRRRRLDDUULLRULLDLDLDLRRRDRLDRUUD\nRLDRRRURULDLUDLDUDLLDUUURRDUDDURULLRRDDULUUDRRRULRUURRRLUUULRDRUDRRLLRLURDLDRDRDLLUDRUULRUDRUDDRURLRLURRDDRRURUUDRRDDRURURUDUUUDUDRRLRDRUUURLLUUUDLRUUDDRDDDDLDRLRDUDDULDDLRLLRURLLURLDDLDLDDULLDDUUURDLRUDUUDLDURDDRUULDRDDRDDDUUUDRDRDDRRDRRDLRDRURDUDDLUUUDULLUULULULRDRUUDDURURDRRRRLUDLDUDURLDRURDLLUUUDLRRDRRURDDULULURLDUDDLUDLDDLLRLDULLULULURUURLDULUDLLUUDLDDULDRRDDUULLUDLDLLRDRDURDDURDDURLDDURUURLLRURURUDDURRDRLRLDDUUDUULRDLLURRRRULURULDUDUDDUDDRLLLDLURDUURUURLUULRRLDLULDDRLDDUURULURUDRD\nURLDDRLLRRLDRLLRRURURURDDLRRRUUUURULRRUUDLUDRULLDLRUDDLULRUULDULURLLRLLUDDUDLURDRRRRLURULRURRURRULRRRULDLLDDLRLUDULUUUDDUDDRRDDDDUULRRLDRRULULRDUURRLDDRDULDURUDUDDLDLLURDDLDDRUDUUUDUUURDLDUDUUULLDLRDULRRRDLLURLDLLULRDDULULURLRLUULRLLLDDDUDLLDLURRRULRDUDDLULUDRUDDURULRLRUDDURLLURULLURDRULDUDLDULRRDLDURLUURRDDUDDUDRURUDDURRUUDURUULLLLDDRDDDDDULUUDDURRULLDRRLRRRRRDDRUUDDDURDRDRUDDUULDUDRRDRULUURLURLUDUDULDDRDULDLRUUDLLLRRLRDRDDUUULRDUDLUDLURRDUURDULDRLLDRDULDUDUULRLLDLRLDLUUDLRUULDUUULDLRLRLUULLLLRLRDUDRUUDURLDUDRRURLRUDRRLRDDLRDDLDDUDDDRLRLLRLUUURLURRRLULRLLDRLRDDRRDRL\nDLLLLLLRLRDRUDLRLLRLDLRURRUURLDLDDDDDUDUULLLLRRLRRDUUDUDLULLRRDULUDLLULURLRULURUULRLURDUDLUDULULUUURLRUDULURULRURULURLRLDRRRRLUDLLDULLDDLLULUURRULRDURDUUDDDURRUDLLLLRLDLUDDULLDUDDURURURRRRULDULULUDDUUDRLRLLLDLLLUUUURUDUUDLDLLRLRDDUULLUURLDDLRRDRLULDLULRULDLDURLULUURRRUDLLRDLUDDULRULULUDDURDLUUURDUUURDUDURLUUDRLUDRULUDDRRDLUUDLLLRDDDDDDLDURDDLDRDLUUDRULLUDRDLDULLULDDRUUDRRLRURRUULLRLRDUUURRDRRDULDDULUUDDURLULRLRURLLRRR"
padlock = KeypadLock.new(instructions)
code = padlock.determine_code
assert_equal(56983, code)
end
end
#!/bin/ruby
require "test/unit"
class Triangler
attr_accessor :triangles
def initialize()
@triangles = []
@possible = 0
@column_a = []
@column_b = []
@column_c = []
end
def read_triangles_from_file(file)
begin
@triangles = IO.readlines(file)
rescue Errno::ENOENT => e
return false
end
end
def read_triangles_vertically_from_file(file)
begin
lines = IO.readlines(file)
lines.each do |line|
a, b, c = line.strip.split(' ').map(&:to_i)
@column_a.push(a)
@column_b.push(b)
@column_c.push(c)
end
rescue Errno::ENOENT => e
return false
end
end
def determine_possible_triangles
@triangles.each do |triangle|
triangle_array = triangle.split(' ').map(&:to_i)
@possible += 1 if is_triangles_array_possible(triangle_array)
end
@possible
end
def determine_possible_vertical_triangles
@column_a.each_slice(3) { |triangle_array| @possible += 1 if is_triangles_array_possible(triangle_array) }
@column_b.each_slice(3) { |triangle_array| @possible += 1 if is_triangles_array_possible(triangle_array) }
@column_c.each_slice(3) { |triangle_array| @possible += 1 if is_triangles_array_possible(triangle_array) }
@possible
end
def is_triangles_array_possible(triangle_array)
z = triangle_array.delete_at(triangle_array.index(triangle_array.max))
y = triangle_array.delete_at(triangle_array.index(triangle_array.max))
x = triangle_array.pop
is_possible_triangle(x, y, z)
end
def is_possible_triangle(x, y, z)
z < (x + y)
end
end
class TestTriangles < Test::Unit::TestCase
def test_bad_file
triangler = Triangler.new
result = triangler.read_triangles_from_file('bad_file.txt')
assert_equal(false, result)
end
def test_good_file
triangler = Triangler.new
possible_triangles = 0
if triangler.read_triangles_from_file('day3.input.txt')
possible_triangles = triangler.determine_possible_triangles
end
assert_equal(982, possible_triangles)
end
def test_good_vertical_file
triangler = Triangler.new
possible_triangles = 0
if triangler.read_triangles_vertically_from_file('day3.input.txt')
possible_triangles = triangler.determine_possible_vertical_triangles
end
assert_equal(1826, possible_triangles)
end
def test_bad_triangle
triangler = Triangler.new
triangler.triangles = ['5 10 25']
possible_triangles = triangler.determine_possible_triangles
assert_equal(0, possible_triangles)
end
def test_good_triangle
triangler = Triangler.new
triangler.triangles = ['5 10 11']
possible_triangles = triangler.determine_possible_triangles
assert_equal(1, possible_triangles)
end
end
#!/bin/ruby
require "test/unit"
class Room
attr_accessor :sector_id
def initialize(room_key)
@name_encrypted, @sector_id, @checksum = Room.parse_room_key(room_key)
@sector_id = @sector_id.to_i
@alpha = "abcdefghijklmnopqrstuvwxyz"
end
def self.parse_room_key(room_key)
room_key.match(/([a-z-]+)-([0-9]+)\[([a-z]+)\]/).captures
end
def is_real_room
name_array = @name_encrypted.tr('-', '').split('').to_a.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 ; h }
name_common = name_array.sort_by { |k,v| [-v,k] }.first(5).map { |k,v| k }.join('')
name_common == @checksum
end
def get_decrypted_name
decrypted_name = @name_encrypted.tr('-', ' ').split('').to_a
for i in 0..@sector_id-1
decrypted_name.each_with_index do |char, idx|
next if char == ' '
decrypted_name[idx] = @alpha[ ( @alpha.index(char) + 1) % 26 ]
end
end
decrypted_name.join('')
end
end
class RoomList
def initialize
@rooms = []
end
def read_room_list_from_file(file)
begin
room_list = IO.readlines(file)
rescue Errno::ENOENT => e
return false
end
room_list.each do |room_key|
room = Room.new(room_key)
@rooms.push(room)
end
end
def add_room_from_room_key(room_key)
room = Room.new(room_key)
@rooms.push(room)
end
def get_sum_of_sector_ids
sector_id_sum = 0
@rooms.each { |room| sector_id_sum += room.sector_id if room.is_real_room }
sector_id_sum
end
def get_sector_id_matching_name(name)
@rooms.each do |room|
return room.sector_id if name == room.get_decrypted_name
end
nil
end
end
class TestRoomList < Test::Unit::TestCase
def test_real_room
room = Room.new('aaaaa-bbb-z-y-x-123[abxyz]')
assert_equal(room.is_real_room, true)
end
def test_real_room_two
room = Room.new('a-b-c-d-e-f-g-h-987[abcde]')
assert_equal(room.is_real_room, true)
end
def test_real_room_three
room = Room.new('not-a-real-room-404[oarel]')
assert_equal(room.is_real_room, true)
end
def test_decoy_room
room = Room.new('totally-real-room-200[decoy]')
assert_equal(room.is_real_room, false)
end
def test_day4_input_sum_sector_ids
room_list = RoomList.new
room_list.read_room_list_from_file("day4.input.txt")
assert_equal(278221, room_list.get_sum_of_sector_ids)
end
def test_decrypt_name
room = Room.new('qzmt-zixmtkozy-ivhz-343[nonsense]')
assert_equal("very encrypted name", room.get_decrypted_name)
end
def test_bad_file
room_list = RoomList.new
result = room_list.read_room_list_from_file("bad_input.txt")
assert_equal(false, result)
end
def test_day4_decrypt_names
room_list = RoomList.new
room_list.read_room_list_from_file("day4.input.txt")
sector_id = room_list.get_sector_id_matching_name("northpole object storage")
assert_equal(267, sector_id)
end
end
#!/bin/ruby
require "digest"
require "test/unit"
class HexCracker
def initialize(input)
@key = input
@cracked_key = ''
end
def get_cracked_password
x = 0
for i in 1..8
while true
x += 1
test_key = @key + x.to_s
hex_key = Digest::MD5.hexdigest test_key
if hex_key[0..4].to_s == '00000'
@cracked_key << hex_key[5].to_s
break
end
end
end
@cracked_key
end
def get_alternate_cracked_password
@cracked_key = ' '
x = 0
for i in 1..8
while true
test_key = @key + x.to_s
hex_key = Digest::MD5.hexdigest test_key
idx = hex_key[5].to_i(16)
if hex_key[0..4].to_s == '00000' and idx < 8 and @cracked_key[idx] == ' '
@cracked_key[idx] = hex_key[6].to_s
x += 1
break
end
x += 1
end
end
@cracked_key
end
end
class TestHexCracker < Test::Unit::TestCase
def test_known_password
hex_cracker = HexCracker.new('abc')
assert_equal('18f47a30', hex_cracker.get_cracked_password)
end
def test_puzzle_input
hex_cracker = HexCracker.new('ojvtpuvg')
assert_equal('4543c154', hex_cracker.get_cracked_password)
end
def test_known_password_two
hex_cracker = HexCracker.new('abc')
assert_equal('05ace8e3', hex_cracker.get_alternate_cracked_password)
end
def test_puzzle_input_two
hex_cracker = HexCracker.new('ojvtpuvg')
assert_equal('1050cbbd', hex_cracker.get_alternate_cracked_password)
end
end
#!/bin/ruby
require "test/unit"
class SignalUnjammer
def initialize(signal_pieces = nil)
@columns = []
if !signal_pieces.nil?
parse_signal_pieces(signal_pieces.split("\n").to_a)
end
end
def read_signal_pieces_from_file(file)
begin
signal_pieces = IO.readlines(file).map(&:chomp)
parse_signal_pieces(signal_pieces)
rescue Errno::ENOENT => e
return false
end
@signals = signal_pieces
end
def parse_signal_pieces(signal_pieces)
signal_pieces.each_with_index do |line|
line.split('').each_with_index { |char, idx| @columns[idx] ||= [] ; @columns[idx].push(char) }
end
end
def unjam_repeat_signal
words = []
@columns.each do |row|
tally_frequency = row.inject(Hash.new(0)) { |h, v| h[v] += 1 ; h }
words.push(row.max_by { |v| tally_frequency[v] })
end
words.join('')
end
def unjam_repeat_signal_unlikely
words = []
@columns.each do |row|
tally_frequency = row.inject(Hash.new(0)) { |h, v| h[v] += 1 ; h }
words.push(row.min_by { |v| tally_frequency[v] })
end
words.join('')
end
end
class TestUnjammer < Test::Unit::TestCase
def test_one
signal_unjammer = SignalUnjammer.new("eedadn\ndrvtee\neandsr\nraavrd\natevrs\ntsrnev\nsdttsa\nrasrtv\nnssdts\nntnada\nsvetve\ntesnvt\nvntsnd\nvrdear\ndvrsen\nenarar")
assert_equal('easter', signal_unjammer.unjam_repeat_signal)
end
def test_two
signal_unjammer = SignalUnjammer.new
signal_unjammer.read_signal_pieces_from_file('day6.input.txt')
assert_equal('xdkzukcf', signal_unjammer.unjam_repeat_signal)
end
def test_three
signal_unjammer = SignalUnjammer.new("eedadn\ndrvtee\neandsr\nraavrd\natevrs\ntsrnev\nsdttsa\nrasrtv\nnssdts\nntnada\nsvetve\ntesnvt\nvntsnd\nvrdear\ndvrsen\nenarar")
assert_equal('advent', signal_unjammer.unjam_repeat_signal_unlikely)
end
def test_four
signal_unjammer = SignalUnjammer.new
signal_unjammer.read_signal_pieces_from_file('day6.input.txt')
assert_equal('cevsgyvd', signal_unjammer.unjam_repeat_signal_unlikely)
end
end
#!/bin/ruby
require "test/unit"
class String
def contains_abba
for i in 0..self.length-4
return true if self[i] + self[i+1] == self[i+3] + self[i+2] and self[i+1] != self[i+3]
end
return false
end
def contains_bab
for i in 0..self.length-3
return true if self[i] == self[i+2] and self[i] != self[i+1]
end
return false
end
def get_babs
babs = []
for i in 0..self.length-3
babs.push(self[i] + self[i+1] + self[i+2]) if self[i] == self[i+2] and self[i] != self[i+1]
end
babs
end
def flip_bab
self[1] + self[0] + self[1]
end
end
class IP
attr_accessor :address
def initialize(ip_address)
@address = ip_address
end
def get_hypernets
@address.scan(/\[([a-z]+)\]/).flatten
end
def get_supernets
@address.gsub(/\[([a-z]+)\]/, ' ').scan(/([a-z]+)/).flatten
end
def get_supernets_babs
babs = []
get_supernets.each do |supernet|
supernet.get_babs.each do |bab|
babs.push(bab)
end
end
babs
end
def get_hypernets_babs
babs = []
get_hypernets.each do |supernet|
supernet.get_babs.each do |bab|
babs.push(bab)
end
end
babs
end
def supports_tls
hypernets = get_hypernets
supernets = get_supernets
hypernets.each { |hypernet| return false if hypernet.contains_abba }
supernets.each { |supernet| return true if supernet.contains_abba }
return false
end
def supports_ssl
get_supernets_babs.each do |supernet|
return true if get_hypernets_babs.include?(supernet.flip_bab)
end
return false
end
end
class IPSet
def read_ip_set_from_file(file)
begin
@ip_set = IO.readlines(file).map(&:chomp)
count_valid_ips
rescue Errno::ENOENT => e
return false
end
end
def count_valid_ips
count = 0
@ip_set.each do |ip_address|
ip = IP.new(ip_address)
count += 1 if ip.supports_tls
end
return count
end
def count_ssl_ips
count = 0
@ip_set.each do |ip_address|
ip = IP.new(ip_address)
count += 1 if ip.supports_ssl
end
return count
end
end
class AbbaTest < Test::Unit::TestCase
def test_one
ip = IP.new('abba[mnop]qrst')
assert_equal(ip.supports_tls, true)
end
def test_two
ip = IP.new('abcd[bddb]xyyx')
assert_equal(ip.supports_tls, false)
end
def test_three
ip = IP.new('aaaa[qwer]tyui')
assert_equal(ip.supports_tls, false)
end
def test_four
ip = IP.new('ioxxoj[asdfgh]zxcvbn')
assert_equal(ip.supports_tls, true)
end
def test_variable_length
ip = IP.new('okcmoevreebuujjdl[nzonouoydhqlmxbyb]kzleqfmoglkipweur[rrtypikbmtkzegy]cmehcxntlavmojfw[tvvcithufoahlxby]')
assert_equal(ip.supports_tls, false)
end
def test_count_valid_ips
ip_set = IPSet.new
ip_set.read_ip_set_from_file('day7.input.txt')
assert_equal(ip_set.count_valid_ips, 110)
end
def test_bab_one
ip = IP.new('aba[bab]xyz')
assert_equal(ip.supports_ssl, true)
end
def test_bab_two
ip = IP.new('xyx[xyx]xyx')
assert_equal(ip.supports_ssl, false)
end
def test_bab_three
ip = IP.new('aaa[kek]eke')
assert_equal(ip.supports_ssl, true)
end
def test_bab_four
ip = IP.new('zazbz[bzb]cdb')
assert_equal(ip.supports_ssl, true)
end
def test_count_valid_ips
ip_set = IPSet.new
ip_set.read_ip_set_from_file('day7.input.txt')
assert_equal(ip_set.count_ssl_ips, 242)
end
end
#!/bin/ruby
require "test/unit"
class Grid
attr_accessor :grid, :width, :height
def initialize(width, height)
@grid = Array.new(height) { Array.new(width, 0) }
@width = width
@height = height
end
def print_grid
@grid.each do |row|
row.each do |cell|
print cell == 0 ? '.' : '#'
end
print "\n"
end
print "\n"
end
def draw_rectangle(x1, y1, x2, y2)
@grid.each_with_index do |row, y|
row.each_with_index do |cell, x|
@grid[y][x] = 1 if x >= x1 and x <= x2 and y >= y1 and y <= y2
end
end
end
end
class Screen < Grid
def read_sequence_set_from_file(file)
begin
@sequence = IO.readlines(file).map(&:chomp)
parse_sequence_commands
rescue Errno::ENOENT => e
return false
end
end
def parse_sequence_commands
@sequence.each do |command|
if m = command.match(/^(rect) ([\d]+)x([\d]+)/)
action, width, height = m.captures
end
if m = command.match(/^(rotate row) y\=([\d]+) by ([\d]+)/)
action, y, distance = m.captures
end
if m = command.match(/^(rotate column) x\=([\d]+) by ([\d]+)/)
action, x, distance = m.captures
end
case action
when "rect"
draw_rect(width.to_i, height.to_i)
when "rotate row"
rotate_row_y(y.to_i, distance.to_i)
when "rotate column"
rotate_column_x(x.to_i, distance.to_i)
end
end
end
def draw_rect(width, height)
draw_rectangle(0, 0, width - 1, height - 1)
end
def rotate_column_x(x, distance)
for i in 1..distance
temp_column_x = []
temp_column_x2 = []
for y in 0..@height - 1
temp_column_x.push(@grid[y][x])
end
temp_column_x.each_with_index do |yoink, idx|
temp_column_x2.push(temp_column_x[idx - 1])
end
temp_column_x2.each_with_index do |val, idx|
@grid[idx][x] = val
end
end
end
def rotate_row_y(y, distance)
for i in 1..distance
temp_row_y = []
temp_row_y2 = []
for x in 0..@width-1
temp_row_y.push(@grid[y][x])
end
temp_row_y.each_with_index do |val, idx|
temp_row_y2.push(temp_row_y[idx - 1])
end
temp_row_y2.each_with_index do |val, idx|
@grid[y][idx] = val
end
end
end
def get_lit_pixels
count = 0
@grid.each_with_index do |row, y|
row.each_with_index do |cell, x|
count += 1 if @grid[y][x] == 1
end
end
count
end
end
class PixelTest < Test::Unit::TestCase
def test_one
screen = Screen.new(7, 3)
screen.draw_rect(3, 2)
screen.rotate_column_x(1, 1)
screen.rotate_row_y(0, 4)
screen.rotate_column_x(1, 1)
assert_equal(screen.get_lit_pixels, 6)
end
def test_two
screen = Screen.new(50, 6)
screen.read_sequence_set_from_file('day8.input.txt')
screen.print_grid
assert_equal(screen.get_lit_pixels, 106)
end
end
#!/bin/ruby
require "test/unit"
class Decompressor
attr_accessor :compressed
def initialize(compressed_string)
@compressed = compressed_string
@decompressed = ""
end
def decompress
pointer = 0
while @compressed[pointer] != nil
instruction = ''
if @compressed[pointer] == '('
while @compressed[pointer + 1] != ')'
pointer += 1
instruction << @compressed[pointer]
end
# Move pointer beyond bracket
pointer += 2
c, n = instruction.split('x').map(&:to_i)
copy_block = @compressed[pointer..pointer+(c-1)]
for x in pointer..pointer+(n-1)
@decompressed << copy_block
end
# Move pointer beyond copy point
pointer += c-1
else
@decompressed << @compressed[pointer]
end
pointer += 1
end
@decompressed
end
def unzip(s)
bracket = s.match(/\((\d+)x(\d+)\)/)
return s.length if bracket == nil
uz_position = s.index(bracket.to_s)
uz_size, uz_mult = bracket.captures.map(&:to_i)
i = uz_position + bracket.to_s.length
chunk = uz_position > 0 ? s[0 .. uz_position - 1] : ''
return chunk.length + unzip(s[i..i+(uz_size-1)]) * uz_mult + unzip(s[i+uz_size..-1])
end
end
class DecompressorRun
def read_compressed_set_from_file(file)
begin
@compressed_set = IO.readlines(file).map(&:chomp)
rescue Errno::ENOENT => e
return false
end
end
def parse_compressed_set_and_return_length
length = 0
@compressed_set.each do |compressed|
decompressor = Decompressor.new(compressed)
length += decompressor.decompress.length
end
length
end
def unzip_compressed_set_and_return_length
length = 0
@compressed_set.each do |compressed|
decompressor = Decompressor.new(compressed)
length += decompressor.unzip(compressed)
end
length
end
end
class TestDecompressor < Test::Unit::TestCase
def test_one
decompressor = Decompressor.new('ADVENT')
assert_equal('ADVENT', decompressor.decompress)
end
def test_two
decompressor = Decompressor.new('A(1x5)BC')
assert_equal('ABBBBBC', decompressor.decompress)
end
def test_three
decompressor = Decompressor.new('(3x3)XYZ')
assert_equal('XYZXYZXYZ', decompressor.decompress)
end
def test_four
decompressor = Decompressor.new('A(2x2)BCD(2x2)EFG')
assert_equal('ABCBCDEFEFG', decompressor.decompress)
end
def test_five
decompressor = Decompressor.new('(6x1)(1x3)A')
assert_equal('(1x3)A', decompressor.decompress)
end
def test_six
decompressor = Decompressor.new('X(8x2)(3x3)ABCY')
assert_equal('X(3x3)ABC(3x3)ABCY', decompressor.decompress)
end
def test_seven
run = DecompressorRun.new
run.read_compressed_set_from_file('day9.input.txt')
assert_equal(183269, run.parse_compressed_set_and_return_length)
end
def test_eight
decompressor = Decompressor.new('(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN')
assert_equal(445, decompressor.unzip(decompressor.compressed))
end
def test_nine
run = DecompressorRun.new
run.read_compressed_set_from_file('day9.input.txt')
assert_equal(11317278863, run.unzip_compressed_set_and_return_length)
end
def test_one_alternate
decompressor = Decompressor.new('ADVENT')
assert_equal(6, decompressor.unzip(decompressor.compressed))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment