You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
advent-of-code/2022/ruby/day_19.rb

93 lines
2.3 KiB

1 year ago
SEEN = []
class Factory
attr_reader :time, :robots, :resources
def initialize(
blueprint,
time=0,
robots={ ore: 1, clay: 0, obsidian: 0, geode: 0 },
resources={ ore: 0, clay: 0, obsidian: 0, geode: 0 }
)
@blueprint = blueprint
@time = time
@robots = robots
@resources = resources
end
def max_geodes
if @time == 20
pp self if @robots.values_at(:ore, :clay, :obsidian, :geode) == [1, 4, 2, 1]
return @resources.fetch(:geode)
end
resources = @resources.merge(@robots) { _2 + _3 }
branches = @blueprint.filter_map {|robot, cost|
if cost.all? {|res, qty| @resources.fetch(res) >= qty }
Factory.new(
@blueprint,
@time + 1,
@robots.merge({robot => 1}) { _2 + _3 },
resources.merge(cost) { _2 - _3 },
)
else
nil
end
}
if @blueprint.any? {|_, cost| cost.any? {|res, qty| @robots.fetch(res) > 0 && @resources.fetch(res) < qty }}
pp self
branches << Factory.new(@blueprint, @time + 1, @robots, resources)
end
branches = branches.reject {|factory|
SEEN.any? {|other|
%i[ ore clay obsidian geode ].all? {|res|
factory.robots.fetch(res) <= other.robots.fetch(res) &&
factory.resources.fetch(res) <= other.resources.fetch(res) &&
factory.time >= other.time
}
}
}
SEEN.concat(branches)
return @resources.fetch(:geode) if branches.empty?
branches.map(&:max_geodes).max
end
def to_s
"<time: #@time robots: #{@robots.values} resources: #{@resources.values}>"
end
alias_method :inspect, :to_s
end
blueprints = ARGF.read
.split("\n\n").map { _1.lines(chomp: true).join }
.map { _1.scan(/\d+/).map(&:to_i) }
.map {
_1.shift # id
{
ore: {ore: _1.shift },
clay: {ore: _1.shift },
obsidian: {ore: _1.shift, clay: _1.shift },
geode: {ore: _1.shift, obsidian: _1.shift },
}
}
p Factory.new(blueprints[0]).max_geodes
p SEEN.count
__END__
Blueprint 1:
Each ore robot costs 4 ore.
Each clay robot costs 2 ore.
Each obsidian robot costs 3 ore and 14 clay.
Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2:
Each ore robot costs 2 ore.
Each clay robot costs 3 ore.
Each obsidian robot costs 3 ore and 8 clay.
Each geode robot costs 3 ore and 12 obsidian.