Skip to content

Commit

Permalink
chore: solution for day14b
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaxwood committed Dec 14, 2023
1 parent 394dac4 commit 19af966
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 15 deletions.
146 changes: 131 additions & 15 deletions lib/day14.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'base64'

# Day14
class Day14
def load(file)
Expand All @@ -17,23 +19,72 @@ def parse
end

def tilt(map, direction)
width = map.keys.max_by(&:first).first
height = map.keys.max_by(&:last).last

case direction
when :north
width = map.keys.max_by(&:first).first
height = map.keys.max_by(&:last).last
(0..width).each do |x|
(0..height).each do |y|
if map[[x, y]] == 'O'
map[[x, y]] = '.'
while y >= 0
y -= 1
if map[[x, y]] == '.'
next
else
map[[x, y + 1]] = 'O'
break
end
end
next unless map[[x, y]] == 'O'

map[[x, y]] = '.'
yy = y
while yy >= 0
yy -= 1
next if map[[x, yy]] == '.'

map[[x, yy + 1]] = 'O'
break
end
end
end
when :west
(0..width).each do |x|
(0..height).each do |y|
next unless map[[x, y]] == 'O'

map[[x, y]] = '.'
xx = x
while xx >= 0
xx -= 1
next if map[[xx, y]] == '.'

map[[xx + 1, y]] = 'O'
break

end
end
end
when :south
(0..width).each do |x|
height.downto(0).each do |y|
next unless map[[x, y]] == 'O'

map[[x, y]] = '.'
yy = y
while yy <= height
yy += 1
next if map[[x, yy]] == '.'

map[[x, yy - 1]] = 'O'
break
end
end
end
when :east
width.downto(0).each do |x|
(0..height).each do |y|
next unless map[[x, y]] == 'O'

map[[x, y]] = '.'
xx = x
while xx <= width
xx += 1
next if map[[xx, y]] == '.'

map[[xx - 1, y]] = 'O'
break
end
end
end
Expand All @@ -55,9 +106,74 @@ def weight(map)
sum
end

def key(map)
key = ''
width = map.keys.max_by(&:first).first
height = map.keys.max_by(&:last).last
(0..width).map do |x|
(0..height).map do |y|
key += map[[x, y]]
end
end
Base64.encode64(key)
end

def draw(map)
puts
width = map.keys.max_by(&:first).first
height = map.keys.max_by(&:last).last
(0..height).each do |y|
(0..width).each do |x|
print map[[x, y]]
end
puts
end
end

def part1
map = parse
new_map = tilt(map, direction = :north)
weight(new_map)
map = tilt(map, direction = :north)
weight(map)
end

def part2
map = parse

cycles = 0
cycle_key = ''
cycle_found = false

cache = {}
keys = []

break_at = 1_000_000_000

loop do
cycles += 1

%i[north west south east].each do |direction|
map = tilt(map, direction)
end

# look for a cycle
key = key(map)
if cache[key]
cycle_key = key if cycle_key == ''
keys.push(cycles) if key == cycle_key
end
cache[key] = true

# cycle found - find next cycle
if keys.size == 2 && !cycle_found
cycle = keys[1] - keys[0]
offset = keys[0] - cycle
break_at = cycle + offset + ((1_000_000_000 - offset) % cycle) + cycle
cycle_found = true
end

break if cycles == break_at
end

weight(map)
end
end
12 changes: 12 additions & 0 deletions test/unit/day14_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,21 @@ def test_day14a
assert_equal(136, sut.part1)
end

def test_day14b
sut = Day14.new
sut.load('data/day14a.txt')
assert_equal(64, sut.part2)
end

def test_day14_part1
sut = Day14.new
sut.load('data/day14.txt')
assert_equal(108_792, sut.part1)
end

def test_day14_part2
sut = Day14.new
sut.load('data/day14.txt')
assert_equal(99_118, sut.part2)
end
end

0 comments on commit 19af966

Please sign in to comment.