Given N > 0
and M > 0
, I want to enumerate all (x, y) pairs such that 1 <= x <= N and 1 <= y <= M in descending order of (x * y).
An
I got it!
Consider the grid as a set of M columns where every column is a stack containing the elements from 1 at the bottom to N at the top. Every column is tagged with its x coordinate.
The elements inside every column stack are ordered by its y value and so also by x*y as x has the same value for all of them.
So, you just have to go picking the stack that has the bigger x*y value at its top, pop it and repeat.
In practice you will not need stacks, just the index of the top value and you can use a priority queue to get the column with the bigger x*y value. Then, decrement the value of the index and if it is bigger than 0 (indicating that the stack has not been exhausted) reinsert the stack on the queue with its new priority x*y.
The complexity of this algorithm for N=M is O(N2logN) and its memory usage O(N).
Update: Implemented in Perl...
use Heap::Simple;
my ($m, $n) = @ARGV;
my $h = Heap::Simple->new(order => '>', elements => [Hash => 'xy']);
# The elements in the heap are hashes and the priority is in the slot 'xy':
for my $x (1..$m) {
$h->insert({ x => $x, y => $n, xy => $x * $n });
}
while (defined (my $col = $h->extract_first)) {
print "x: $col->{x}, y: $col->{y}, xy: $col->{xy}\n";
if (--$col->{y}) {
$col->{xy} = $col->{x} * $col->{y};
$h->insert($col);
}
}