AdventOfCode-2018/day7.cr

88 lines
1.9 KiB
Crystal

require "./common.cr"
lines = File.read("day7_input").split("\n")
lines.pop
REGEX = /Step (.+) must be finished before step (.+) can begin./
all_children = {} of String => Set(String)
all = Set(String).new
finished = Set(String).new
finished_array = Array(String).new
lines.map(&.match(REGEX)).each do |match|
match = match.not_nil!
child = match[1]
parent = match[2]
all << child
all << parent
parent_set = all_children[parent]? || Set(String).new
parent_set << child
all_children[parent] = parent_set
end
available_at = {} of String => Int32
class String
def cost
return (self[0].bytes[0] - 'A'.bytes[0]).to_i32 + 1
end
end
def get_available(all, finished, children)
available = all.select do |it|
next false if finished.includes? it
next true unless set = children[it]?
next true if set.size == 0
end
end
children = all_children.clone
while finished.size != all.size
available = get_available(all, finished, children)
available.sort!
first = available.first
finished << first
finished_array << first
children.values.each do |value|
value.delete first
end
end
puts finished_array.join ""
finished.clear
finished_array.clear
children = all_children.clone
workers = [0, 0, 0, 0, 0]
current_time = 0
finished_at = {} of String => Int32
while finished.size < all.size
workers.each_with_index do |worker, index|
next if worker > current_time
current_finished = finished_at.select { |k, v| v <= current_time }.map(&.[0]).to_set
available = all.select do |it|
next false if finished.includes? it
next true unless nodes = children[it]?
(nodes - current_finished).size == 0
end
available = available.sort!
next if available.empty?
first = available.first
finished_at[first] = current_time + first.cost + 60
workers[index] = current_time + first.cost + 60
finished_array << first
finished << first
end
current_time += 1
end
puts finished_at.values.max