62 lines
1.7 KiB
Raku
62 lines
1.7 KiB
Raku
my %costs =
|
|
:W{:16A, :16B, :13C, :22D, :17E},
|
|
:X{:14A, :14B, :13C, :19D, :15E},
|
|
:Y{:19A, :19B, :20C, :23D, :50E},
|
|
:Z{:50A, :12B, :50C, :15D, :11E};
|
|
|
|
my %demand = :30A, :20B, :70C, :30D, :60E;
|
|
my %supply = :50W, :60X, :50Y, :50Z;
|
|
|
|
my @cols = %demand.keys.sort;
|
|
|
|
my %res;
|
|
my %g = (|%supply.keys.map: -> $x { $x => [%costs{$x}.sort(*.value)».key]}),
|
|
(|%demand.keys.map: -> $x { $x => [%costs.keys.sort({%costs{$_}{$x}})]});
|
|
|
|
while (+%g) {
|
|
my @d = %demand.keys.map: -> $x
|
|
{[$x, my $z = %costs{%g{$x}[0]}{$x},%g{$x}[1] ?? %costs{%g{$x}[1]}{$x} - $z !! $z]}
|
|
|
|
my @s = %supply.keys.map: -> $x
|
|
{[$x, my $z = %costs{$x}{%g{$x}[0]},%g{$x}[1] ?? %costs{$x}{%g{$x}[1]} - $z !! $z]}
|
|
|
|
@d = |@d.grep({ (.[2] == max @d».[2]) }).&min: :by(*.[1]);
|
|
@s = |@s.grep({ (.[2] == max @s».[2]) }).&min: :by(*.[1]);
|
|
|
|
my ($t, $f) = @d[2] == @s[2] ?? (@s[1],@d[1]) !! (@d[2],@s[2]);
|
|
my ($d, $s) = $t > $f ?? (@d[0],%g{@d[0]}[0]) !! (%g{@s[0]}[0], @s[0]);
|
|
|
|
my $v = %supply{$s} min %demand{$d};
|
|
|
|
%res{$s}{$d} += $v;
|
|
%demand{$d} -= $v;
|
|
|
|
if (%demand{$d} == 0) {
|
|
%supply.grep( *.value != 0 )».key.map: -> $v
|
|
{ %g{$v}.splice((%g{$v}.first: * eq $d, :k),1) };
|
|
%g{$d}:delete;
|
|
%demand{$d}:delete;
|
|
}
|
|
|
|
%supply{$s} -= $v;
|
|
|
|
if (%supply{$s} == 0) {
|
|
%demand.grep( *.value != 0 )».key.map: -> $v
|
|
{ %g{$v}.splice((%g{$v}.first: * eq $s, :k),1) };
|
|
%g{$s}:delete;
|
|
%supply{$s}:delete;
|
|
}
|
|
}
|
|
|
|
say join "\t", flat '', @cols;
|
|
my $total;
|
|
for %costs.keys.sort -> $g {
|
|
print "$g\t";
|
|
for @cols -> $col {
|
|
print %res{$g}{$col} // '-', "\t";
|
|
$total += (%res{$g}{$col} // 0) * %costs{$g}{$col};
|
|
}
|
|
print "\n";
|
|
}
|
|
say "\nTotal cost: $total";
|