use 5.20.0; use warnings; use experimental qw/ signatures postderef /; use List::UtilsBy qw/ nsort_by /; use List::AllUtils qw/ min /; use Sim; use Graph::Directed; my $g = Graph::Directed->new; while(<>) { /Step (.).*before step (.)/; $g->add_edge( $1 => $2 ); } my $workers = 5; Sim->schedule( 0 => \&check_for_work, ); my %available = map { $_ => 1 } $g->vertices; Sim->run( fires => 100_000 ); sub time_for { ord(shift) - ord('A') + 1 + 60; } sub check_for_work { say "time: ", Sim->now; my @next = sort $g->predecessorless_vertices or return; while( $workers ) { my $next = shift @next or return; $available{$next} or next; delete $available{$next}; $workers--; Sim->schedule( Sim->now + time_for($next) => sub { say "time done $next: ", Sim->now; $g->delete_vertex($next); $workers++; Sim->schedule( Sim->now, \&check_for_work ); } ) } }