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
def decompress(input)
output = ''
ss = StringScanner.new(input)
until ss.eos?
if ss.scan(/(.*?)\((\d+)x(\d+)\)/)
output << ss[1]
times = ss[3].to_i
seq = ss.scan(/.{#{ss[2].to_i}}/)
output << (seq * times)
else
output << ss.scan(/.*/)
end
end
output
end
def decompressed_length(input)
length = 0
ss = StringScanner.new(input)
until ss.eos?
case
when ss.scan(/\((\d+)x(\d+)\)/)
times = ss[2].to_i
seq = ss.scan(/.{#{ss[1].to_i}}/)
length += times * decompressed_length(seq)
when ss.scan(/[^(]+/)
length += ss.matched.length
else
raise 'omg!'
end
end
length
end
if __FILE__ == $0
puts decompressed_length(DATA.read.chomp)
end
require 'minitest'
# require 'minitest/autorun'
class TestDecompress < Minitest::Test
def test_decompress
assert_equal 'ADVENT', decompress('ADVENT')
assert_equal 'ABBBBBC', decompress('A(1x5)BC')
assert_equal 'XYZXYZXYZ', decompress('(3x3)XYZ')
assert_equal 'ABCBCDEFEFG', decompress('A(2x2)BCD(2x2)EFG')
assert_equal '(1x3)A', decompress('(6x1)(1x3)A')
assert_equal 'X(3x3)ABC(3x3)ABCY', decompress('X(8x2)(3x3)ABCY')
end
def test_decompressed_length
assert_equal 9, decompressed_length('(3x3)XYZ')
assert_equal 20, decompressed_length('X(8x2)(3x3)ABCY')
assert_equal 241920, decompressed_length('(27x12)(20x12)(13x14)(7x10)(1x12)A')
input = '(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN'
assert_equal 445, decompressed_length(input)
end
end
__END__