constant $bs = 8; constant $debug = False; #| Gets the remaining number of items left to pack sub num-remain (%h) { [+] %h.values.».elems; } sub exists-and-elems ( %h, $key ) { %h{$key}:exists and %h{$key}.elems; } sub compute-packing ( @list where { .all ~~ Pair and $_.».value.all ~~ Int } ) is export { say "Received list: ", @list.perl if $debug; my @result; my $i = 0; my $visual; my %h{Int} = first-run(@list, @result); say %h.perl if $debug; say "before second run Packing:", @result.perl if $debug; second-run(%h, @result); say "before loopy Packing:", @result.perl if $debug; loopy(%h, @result); say "after loopy" if $debug; try say "packing:", @result.».value if $debug; push-remaining(%h, @result); die unless num-remain(%h) == 0; say "Final packing:", @result.».value if $debug; @result; } sub test-it { my @list = init(); say compute-packing(@list); } sub push-remaining (%h, @result) { for %h.keys.sort(-*) -> $key { while exists-and-elems(%h, $key) { @result.push(%h{$key}.pop => $key); } } } sub loopy (%h, @result) { my $left; my $i; repeat while $left != [+] %h.values.».elems { $left = [+] %h.values.».elems; say "left: ", $left if $debug; say "First final-run" if $debug; final-run(%h, @result); say "Remaining: ", %h.perl if $debug; say "Packing:", @result.perl if $debug; $i++; say "thing", "$left {[+] %h.values.».elems}" if $debug; last if $left == 0; } } sub init { my $i = 0; my @list; for ^10 { @list.push($i++ => (1..8).pick) for ^5; } @list.push($i++ => 1) for ^10; @list.push($i++ => 15); @list; } sub first-run (@list, @result) { # First categorize everything divisible by the bs sub mapper(Pair $i) returns List { $i.value %% $bs ?? 'div' !! 'not-div', } my $a = categorize &mapper, @list; say "first run \$a: ", $a.perl if $debug; unless $a