sub rearrange { my($dim, $height, $v, $args) = @_; my @bitmap = (0 .. $dim - 1); my($ones, $zeros) = (0, $dim - 1); # find holes in the ones looking from the bottom and plugs # in the zeros looking from the top, then swap them while ($ones < $zeros) { ++$ones , next if ($v & (1 << $ones )) != 0; --$zeros, next if ($v & (1 << $zeros)) == 0; @bitmap[$ones, $zeros] = @bitmap[$zeros, $ones]; ++$ones; --$zeros; } ++$ones if $ones == $zeros && ($v & (1 << $ones)) != 0; # $ones is now a count of the number of 1-bits # may need an extra swap to get the 'x' at the right height if ($bitmap[$height] != $ones) { my($lowest) = grep $bitmap[$_] == $ones, 0 .. $dim - 1; @bitmap[$height, $lowest] = @bitmap[$lowest, $height]; } # we now know what row should go where, so build and return the mapped result my @invmap = sort { $bitmap[$a] <=> $bitmap[$b] } 0 .. $dim - 1; my @vmap = (0); for (0 .. $dim - 1) { my $mapped = 1 << $invmap[$_]; push @vmap, map $_ + $mapped, @vmap; } ($bitmap[$height], [ @$args[ @vmap ] ]); }