טוב רשמית אני בדיליי אבל אין מה לעשות חודש שלם לפתור חידות יום אחרי יום זה קשה. בכל מקרה זה כיף אז ממשיכים גם אם קצת אחרי כולם.
קישור לחידה המקורית:
https://adventofcode.com/2018/day/12
פיתרון בשפת רובי:
class Garden
# initial state: #..#.#..##......###...###
attr_accessor :gen
def initialize(initial_state)
@ruleset = {}
@flowers = {}
@flowers.default = '.'
@gen = 0
@flowers[-2] = Flower.new(-2, @ruleset, false)
@flowers[-1] = Flower.new(-1, @ruleset, false)
initial_state.each_char.each_with_index do |char, index|
@flowers[index] = Flower.new(index, @ruleset, char == '#')
end
last = initial_state.length
@flowers[last] = Flower.new(last, @ruleset, false)
@flowers[last + 1] = Flower.new(last + 1, @ruleset, false)
end
def sum_indexes_with_plants
@flowers.select {|idx, plant| plant.state }.keys.reduce(0, :+)
end
# rule: ..##. => .
def add_rule(rule)
key, result = rule.split(/\s*=>\s*/)
@ruleset[key] = result == '#' ? true : false
end
def set_neighbors
@flowers.each do |index, flower|
flower.l2 = @flowers[index - 2]
flower.l1 = @flowers[index - 1]
flower.r1 = @flowers[index + 1]
flower.r2 = @flowers[index + 2]
end
end
def nextgen
@flowers.each { |i, f| f.update }
@flowers.each { |i, f| f.finish_update }
first, last = @flowers.keys.minmax
if @flowers[first].state || @flowers[first + 1].state
@flowers[first - 2] = Flower.new(@flowers[first].id - 2, @ruleset, false)
@flowers[first - 1] = Flower.new(@flowers[first].id - 1, @ruleset, false)
end
if @flowers[last].state || @flowers[last - 1].state
@flowers[last + 1] = Flower.new(@flowers[last].id + 1, @ruleset, false)
@flowers[last + 2] = Flower.new(@flowers[last].id + 2, @ruleset, false)
end
set_neighbors
@gen += 1
end
def to_s
minkey, maxkey = @flowers.keys.minmax
"%2d %s [%d,%d]" % [@gen, @flowers.sort_by {|k, v| k }.map {|i, f| f.to_s }.join(''), minkey, maxkey ]
end
end
class Flower
attr_accessor :state, :l2, :l1, :r1, :r2, :next_state, :ruleset, :id
def initialize(id, ruleset, state)
@ruleset = ruleset
self.state = state
@id = id
end
def to_s
state ? '#' : '.'
end
def update
key = "#{l2}#{l1}#{self}#{r1}#{r2}".rjust(5, '.')
if ruleset.key?(key)
self.next_state = ruleset[key]
else
self.next_state = false
end
end
def finish_update
self.state = next_state
end
end
garden = nil
ARGF.each_line do |line|
line = line.chomp
if line =~ /initial state:/
garden = Garden.new(line.match(/initial state: ([#.]+)$/)[1])
elsif line =~ /#/
garden.add_rule(line)
end
end
garden.set_neighbors
200.times do |i|
prev_result = garden.sum_indexes_with_plants
garden.nextgen
diff = garden.sum_indexes_with_plants - prev_result
# Turns out the diff between numbers is the same after ~100 rounds
# for me it was 73
puts "#{garden.gen} - #{garden.sum_indexes_with_plants} [#{diff}]"
end
puts (50_000_000_000 - 200) * 73 + garden.sum_indexes_with_plants