64 lines
1.0 KiB
Perl
64 lines
1.0 KiB
Perl
|
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 );
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|