Advent of code 2015 - part 1
I recently found out about Advent of Code, and as part of my preparation for this year’s event I’m solving the puzzles of the previous event (AdventofCode.com/2015), in this short series I’ll publish my solutions with a brief explanation.
A brief explanation about how Advent of Code works, there’s one puzzle every day from December 1st to the 25th, each puzzle has two versions so you can earn up to two stars for every puzzle.
Day 1: Not Quite Lisp
Problem description: day/1.
Solution
For v1: Just use a variable for the current floor, increase by one when we find a (
, decrease by 1 when we find a )
.
#!/usr/bin/env ruby
File.read('input.txt')
input = //)
sequence = input.split(0
floor = do |s|
sequence.each if s == '('
1
floor += else
1
floor -= end
end
puts floor
For v2: Similar to v1, we just need to keep track of the positions.
#!/usr/bin/env ruby
File.read('input.txt')
input = //)
sequence = input.split(0
floor = do |s, i|
sequence.each_with_index if s == '('
1
floor += else
1
floor -= end
if floor == -1
1
puts i + break
end
end
Day 2: I Was Told There Would Be No Math
Problem description: day/2.
Solution
For v1: Read all lines, parse the three integers and just apply the formula from the problem description.
0
paper = File.readlines('input.txt').each do |line|
next if line.length == ''
'x').map(&:to_i).sort
dimensions = line.split(
l, w, h = dimensions2 * l * w) + (2 * l * h) + (2 * w * h) + (l * w)
paper += (end
puts paper
For v2: Take the lowest 2 values (out of 3) and compute the perimeter, plus the product of all of them.
0
ribbon = File.readlines('input.txt').each do |line|
'x').map(&:to_i).sort
dimensions = line.split(
l, w, h = dimensions2 * l + 2 * w) + (l * w * h)
ribbon += (end
puts ribbon
Day 3: Perfectly Spherical Houses in a Vacuum
Problem description: day/3.
Solution
For v1: A simulation problem, update your position in a 2-dimensional grid with every command, use a table to keep track of the unique positions you’ve been in.
0, 0] => true}
grid = {[0
r = 0
c = File.read('input.txt').split(//).each do |i|
1 if i == 'v'
r += 1 if i == '^'
r -= 1 if i == '>'
c += 1 if i == '<'
c -= /r, c) = true
grid[r, c](end
puts grid.length
For v2: Likewise, except that you have to alternate commands with Robo-Santa, the first command is for Santa, the second one is for Robo-Santa, etc.
0, 0] => true}
grid = {[
def move(r, c, d)
1 if d == 'v'
r += 1 if d == '^'
r -= 1 if d == '>'
c += 1 if d == '<'
c -= return r, c
end
0
sr = 0
sc = 0
rr = 0
rc = File.read('input.txt').split(//).each_with_index do |d, i|
if i % 2 == 0
sr, sc = move(sr, sc, d)/sr, sc) = true
grid[sr, sc]( else
rr, rc = move(rr, rc, d)
grid[rr, rc](/rr, rc) = true
end
end
puts grid.length
Day 4: The Ideal Stocking Stuffer
Problem description: day/4.
Solution
For v1: Well, I just brute-forced this one, used Ruby’s Digest::MD5
to compute the checksum.
'digest'
require
'bgvyzdsv'
secret = 1
key = do
loop Digest::MD5.new
md5 =
md5.update(secret + key.to_s)
hex = md5.hexdigestif hex.start_with?('00000')
puts keybreak
end
1
key += end
For v2: The same as v1, just add one more zero.
'digest'
require
'bgvyzdsv'
secret = 1
key = do
loop Digest::MD5.new
md5 =
md5.update(secret + key.to_s)
hex = md5.hexdigestif hex.start_with?('000000')
puts keybreak
end
1
key += end
Day 5: Doesn’t He Have Intern-Elves For This?
Problem description: day/5.
Solution
For v1: Just follow the instructions carefully and you should be able to solve this problem.
def nice?(word)
//)
chars = word.split(
vowels = {'a' => 0,
'e' => 0,
'i' => 0,
'o' => 0,
'u' => 0
}
forbidden = {'ab' => true,
'cd' => true,
'pq' => true,
'xy' => true
}false
consecutive = 0.upto(chars.length - 2) do |i|
1]
pair = chars[i] + chars[i+return false if forbidden[pair] == true
1])
consecutive ||= (chars[i] == chars[i+end
return false unless consecutive
do |c|
chars.each 1 if vowels[c]
vowels[c] += end
return vowels.values.reduce(&:+) >= 3
end
File.readlines('input.txt').select {|w| nice?(w.chomp) }.length puts
For v2: Just follow the instructions even more carefully, I was trapped by a moment by a pesky bug in this version.
def nice?(word)
//)
chars = word.split(
pairs = {}false
contains_pair = ''
prev = 1).downto(1) do |i|
(chars.length - -1] + chars[i]
pair = chars[itrue)
contains_pair ||= (pairs[pair] == true
pairs[prev] =
prev = pairend
return false unless contains_pair
0.upto(chars.length - 3) do |i|
return true if chars[i] == chars[i+2]
end
false
end
File.readlines('input.txt').select {|w| nice?(w.chomp) }.length
puts 'qjhvhtzxzqqjkmpb')
puts nice?('xxyxx')
puts nice?('uurcxstgmygtbstg')
puts nice?('ieodomkazucvgmuy') puts nice?(