#!perl
use strict;
use warnings;
use bigint;
sub nth_permutation($@) {
my ($p, @c) = @_;
my @repno;
my $d = 1;
my $fact = 1;
$fact *= $_ for (2..$n);
for( @c ) {
$repno[$_] ++;
$d *= $repno[$_];
}
SLOT: for (my $i=0; $i<$n; $i++) {
$fact /= $n - $i;
DIGIT
: for (my $j=0; $j<scalar(@repno); $j++) { if ($repno[$j] < 1) { next DIGIT; }
my $p2 = $fact / ($d / $repno[$j]);
if ($p2 > $p) {
$d /= $repno[$j];
$repno[$j] --;
$c[$i] = $j;
next SLOT;
}
$p -= $p2;
}
}
}
sub permno(@) {
my (@choices) = @_;
my $n = @choices;
# for now assume symbols are 0-based integers
# with no gaps
my @repno = map {0} (0..$n-1); # number of times each symbol is repeated
my $p = 0;
my $d = 1;
my $fact = 1;
for (my $i = $n -1; $i >= 0; $i--) {
my $c = $choices[$i];
$repno[$c] ++;
$d *= $repno[$c];
for (my $j = 0; $j < $c; $j ++ ) {
next unless $repno[$j] > 0;
$p += $fact / ( $d /$repno[$j]);
}
$fact *= $n - $i;
}
}
while (<>) {
my ($m, @c) = split(/\s*[,]*\s+/); if ($m =~ /^ *pn/) {
my $p = permno( @c);
}
elsif ($m=~ /^ *p/) {
my ($p, @code) = @c;
my @order = nth_permutation($p, @code);
}
}
IyFwZXJsCgp1c2Ugc3RyaWN0Owp1c2Ugd2FybmluZ3M7CnVzZSBiaWdpbnQ7CgpzdWIgbnRoX3Blcm11dGF0aW9uKCRAKSB7CglteSAoJHAsIEBjKSA9IEBfOwoJbXkgQHJlcG5vOwoJbXkgJGQgPSAxOwoJbXkgJGZhY3QgPSAxOwoJbXkgJG4gPSBzY2FsYXIoQGMpOwoJCgkkZmFjdCAqPSAkXyBmb3IgKDIuLiRuKTsKCQoJCglmb3IoIEBjICkgewoJICAgICRyZXBub1skX10gKys7CgkgICAgJGQgKj0gJHJlcG5vWyRfXTsKCX0KCQogIFNMT1Q6IGZvciAobXkgJGk9MDsgJGk8JG47ICRpKyspIHsKCSAgJGZhY3QgLz0gJG4gLSAkaTsKCURJR0lUOiBmb3IgKG15ICRqPTA7ICRqPHNjYWxhcihAcmVwbm8pOyAkaisrKSB7CgkgICAgaWYgKCRyZXBub1skal0gPCAxKSB7IG5leHQgRElHSVQ7IH0KCSAgICBteSAkcDIgPSAkZmFjdCAvICgkZCAvICRyZXBub1skal0pOwoJICAgIGlmICgkcDIgPiAkcCkgewoJCSRkIC89ICRyZXBub1skal07CgkJJHJlcG5vWyRqXSAtLTsKCQkKCQkkY1skaV0gPSAkajsKCQluZXh0IFNMT1Q7CgkgICAgfQoJICAgICRwIC09ICRwMjsKCX0KICB9CQoJCglyZXR1cm4gQGM7Cn0KICAgIApzdWIgcGVybW5vKEApIHsKICAgIG15IChAY2hvaWNlcykgPSBAXzsKICAgIG15ICRuID0gQGNob2ljZXM7CgogICAgIyBmb3Igbm93IGFzc3VtZSBzeW1ib2xzIGFyZSAwLWJhc2VkIGludGVnZXJzCiAgICAjIHdpdGggbm8gZ2FwcwogICAgCiAgICBteSBAcmVwbm8gPSBtYXAgezB9ICgwLi4kbi0xKTsgICMgbnVtYmVyIG9mIHRpbWVzIGVhY2ggc3ltYm9sIGlzIHJlcGVhdGVkCiAgICAgCiAgICBteSAkcCA9IDA7CiAgICBteSAkZCA9IDE7CiAgIAogICAgbXkgJGZhY3QgPSAxOwogCiAgICBmb3IgKG15ICRpID0gJG4gLTE7ICRpID49IDA7ICRpLS0pIHsKICAgICAgICBteSAkYyA9ICRjaG9pY2VzWyRpXTsKCgkgICAgJHJlcG5vWyRjXSArKzsKCSAgICAkZCAqPSAkcmVwbm9bJGNdOwoKCSAgICBmb3IgKG15ICRqID0gMDsgJGogPCAkYzsgJGogKysgKSB7CgkJbmV4dCB1bmxlc3MgJHJlcG5vWyRqXSA+IDA7CgkJJHAgKz0gJGZhY3QgLyAoICRkIC8kcmVwbm9bJGpdKTsKCSAgICB9CgkgICAgJGZhY3QgKj0gJG4gLSAkaTsJCiAgICB9IAogICAgcmV0dXJuICRwOwp9CgoKd2hpbGUgKDw+KSB7CiAgICBteSAoJG0sIEBjKSA9IHNwbGl0KC9ccypbLF0qXHMrLyk7CglpZiAoJG0gPX4gL14gKnBuLykgewogICAgICAgIG15ICRwID0gcGVybW5vKCBAYyk7CiAgICAgICAgcHJpbnQgJHAgLiAiXG4iOwoJfQoJZWxzaWYgKCRtPX4gL14gKnAvKSB7CgkgICAgbXkgKCRwLCBAY29kZSkgPSBAYzsKCSAgICBteSBAb3JkZXIgPSBudGhfcGVybXV0YXRpb24oJHAsIEBjb2RlKTsKCSAgICBwcmludCBqb2luICgnICcsIEBvcmRlcikgLiAiXG4iOwoJfQp9
cG4gNSA0IDMgMiAxIDAKcG4gMiAxIDAgMApwbiA1IDAgMSAyIDUgMCAxIDIgMCAwIDEgMSA1IDQgMyAyIDEgMApwbiA4IDggOCA4IDggOCA4IDggOCA3IDcgNyA2IDUgMCAxIDIgNSAwIDEgMiAwIDAgMSAxIDUgNCAzIDIgMSAwIDYgNyA4CnAgNzE5LCAwIDEgMiAzIDQgNSAgCnAgMTEsIDAgMCAxIDIKcCAxMDU3NzI4NjExOSwgMCAwIDAgMCAwIDEgMSAxIDEgMSAyIDIgMiAzIDQgNSA1IDUKcCAzMjY5NjA1MzYyMDQyOTE5NTI3ODM3NjI0LCAwIDAgMCAwIDAgMSAxIDEgMSAxIDIgMiAyIDMgNCA1IDUgNSA2IDYgNyA3IDcgNyA4IDggOCA4IDggOCA4IDggOCA4
pn 5 4 3 2 1 0
pn 2 1 0 0
pn 5 0 1 2 5 0 1 2 0 0 1 1 5 4 3 2 1 0
pn 8 8 8 8 8 8 8 8 8 7 7 7 6 5 0 1 2 5 0 1 2 0 0 1 1 5 4 3 2 1 0 6 7 8
p 719, 0 1 2 3 4 5
p 11, 0 0 1 2
p 10577286119, 0 0 0 0 0 1 1 1 1 1 2 2 2 3 4 5 5 5
p 3269605362042919527837624, 0 0 0 0 0 1 1 1 1 1 2 2 2 3 4 5 5 5 6 6 7 7 7 7 8 8 8 8 8 8 8 8 8 8