Last active
December 14, 2015 21:32
-
-
Save grondilu/18a2f01d76677de1a7e3 to your computer and use it in GitHub Desktop.
permutations with NQP code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use nqp; | |
sub permutations(int $n where $n > 0) { | |
Seq.new: | |
class :: does Iterator { | |
# See: L<https://en.wikipedia.org/wiki/Permutation#Generationn_lexicographic_order> | |
has int $!n; | |
has Mu $!permutation; | |
submethod BUILD(:$n) { $!n = $n; $!permutation := nqp::list(); self } | |
#method is-lazy { True } | |
method pull-one { | |
unless nqp::elems($!permutation) { | |
my int $i = -1; | |
nqp::bindpos($!permutation, $i, +$i) while ++$i < $!n; | |
return nqp::clone($!permutation); | |
} | |
# Find the largest index k such that a[k] < a[k + 1]. | |
# If no such index exists, the permutation is the last permutation. | |
my int $k = $!n - 2; | |
$k-- or return IterationEnd until nqp::atpos($!permutation, $k) < nqp::atpos($!permutation, $k + 1); | |
# Find the largest index l greater than k such that a[k] < a[l]. | |
my int $l = $!n - 1; | |
$l-- until nqp::atpos($!permutation, $k) < nqp::atpos($!permutation, $l); | |
# use L<https://en.wikipedia.org/wiki/XOR_swap_algorithm> | |
# @!permutation[$k, $l].=reverse | |
nqp::bindpos($!permutation, $k, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
nqp::bindpos($!permutation, $l, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
nqp::bindpos($!permutation, $k, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
# @!permutation[$k+1 .. @!permutation.end].=reverse; | |
$l = $!n; | |
until ++$k >= --$l { | |
nqp::bindpos($!permutation, $k, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
nqp::bindpos($!permutation, $l, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
nqp::bindpos($!permutation, $k, nqp::bitxor_i(nqp::atpos($!permutation, $k), nqp::atpos($!permutation, $l))); | |
} | |
return nqp::clone($!permutation); | |
} | |
method count-only { [*] 1 .. $!n } | |
}.new(:$n) | |
} | |
.say for permutations(6); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment