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.
93 lines
2.3 KiB
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.
|