in reply to Bag uniform distribution algorithms
I'm not sure how "as uniformly distributed as possible" can be qualified ...
Do you have a test-code to check the "quality" of a solution?
But sorting according to a weighting function gives similar results like shown by you.
DB<171> %h=( A => 4, B => 2, C => 3, D => 1 ) => ("A", 4, "B", 2, "C", 3, "D", 1) DB<172> $sum=0; $sum+=$_ for values %h; => "" DB<173> @list=map { my ($k,$v)=($_,$h{$_}); my $int=$sum/$v; map { + [ $k => $int*($_-.5)] } 1..$v } keys %h => ( ["A", "1.25"], ["A", "3.75"], ["A", "6.25"], ["A", "8.75"], ["D", 5], ["C", "1.66666666666667"], ["C", 5], ["C", "8.33333333333333"], ["B", "2.5"], ["B", "7.5"], ) DB<174> map {$_->[0]} sort { $a->[1] <=> $b->[1] or $a->[0] cmp $b-> +[0]} @list => ("A", "C", "B", "A", "C", "D", "A", "B", "C", "A")
Changing the weighting function would also allow to repeat the pattern in a way that joined sequences are still equally distributed ( that is A doesn't neighbor A )
An iterator-version shouldn't be too difficult.
Cheers Rolf
( addicted to the Perl Programming Language)
update
code simplified
update
well after second thought it's quite easy to find input where this approach fails ... never mind! :(
In Section
Seekers of Perl Wisdom