Javascript : 如何在排列后取回初始值
Javascript : How to retrieve initial value after permutation
从一个 6 位数的值(即“123456”)和一个 [0->9] table 开始,这个脚本(但许多其他存在......)产生 table :
let tabl10 = [0,1,2,3,4,5,6,7,8,9],
permut = permutation( 123456 , tabl10 )
console.log(permut) // 0,4,1,6,5,9,2,3,7,8
function permutation(n,a) {
let f, k = [], l = a.length;
a = a.slice();
while (l--) {
f = factorial(l);
k.push(Math.floor(n / f));
n %= f;
}
return k.map(function (i) {
return a.splice(i, 1)[0];
});
}
function factorial(n) {
let r = 1;
while (n) {
r *= n;
n--;
}
return r;
}
我的问题是:是否可以从“0,4,1,6,5,9,2,3,7,8”排列中检索“123456”?
我们有 10 个! (362.88 万)种可能的排列并一一尝试所有排列,直到我们发现第 123456 种排列是痛苦的:可以探索所有排列并用 7 位 table [0,1,2 ,3,4,5,6]: 7!=5040,但 8 位数字 (40320) 或更高数字肯定会冻结浏览器。如何实现?
在一个Lehmer code的排列perm
中,第i个数是i
右边小于perm[i]
的元素个数.因此,给定一个排列,您可以先计算它的 LC,然后将 LC 从阶乘系统转换为 int,从而为您提供排列的索引。
完整代码:
// int => LC
function int2lc(n, len) {
let lc = []
for (let i = 1; i <= len; i++) {
lc[len - i] = (n % i)
n = (n / i) | 0
}
return lc
}
// LC => int
function lc2int(lc, len) {
let n = 0, f = 1
for (let i = 1; i <= len; i++) {
n += lc[len - i] * f
f *= i
}
return n
}
// LC => permutation
function lc2perm(a, lc) {
let perm = [], copy = [...a]
for (let i = 0; i < lc.length; i++) {
perm[i] = copy[lc[i]]
copy.splice(lc[i], 1)
}
return perm
}
// permutation => LC
function perm2lc(perm) {
let lc = []
for (let i = 0; i < perm.length; i++) {
let c = 0
for (let k = i + 1; k < perm.length; k++)
c += perm[k] < perm[i]
lc[i] = c
}
return lc
}
//
A = [0,1,2,3,4,5,6,7,8,9]
// index to perm
N = 123456
lc = int2lc(N, A.length)
console.log('LEHMER', ...lc)
perm = lc2perm(A, lc)
console.log('PERMUT', ...perm)
// perm to index
lc2 = perm2lc(perm)
console.log('LEHMER', ...lc2)
M = lc2int(lc2, A.length)
console.log('INDEX ', M)
从一个 6 位数的值(即“123456”)和一个 [0->9] table 开始,这个脚本(但许多其他存在......)产生 table :
let tabl10 = [0,1,2,3,4,5,6,7,8,9],
permut = permutation( 123456 , tabl10 )
console.log(permut) // 0,4,1,6,5,9,2,3,7,8
function permutation(n,a) {
let f, k = [], l = a.length;
a = a.slice();
while (l--) {
f = factorial(l);
k.push(Math.floor(n / f));
n %= f;
}
return k.map(function (i) {
return a.splice(i, 1)[0];
});
}
function factorial(n) {
let r = 1;
while (n) {
r *= n;
n--;
}
return r;
}
我的问题是:是否可以从“0,4,1,6,5,9,2,3,7,8”排列中检索“123456”?
我们有 10 个! (362.88 万)种可能的排列并一一尝试所有排列,直到我们发现第 123456 种排列是痛苦的:可以探索所有排列并用 7 位 table [0,1,2 ,3,4,5,6]: 7!=5040,但 8 位数字 (40320) 或更高数字肯定会冻结浏览器。如何实现?
在一个Lehmer code的排列perm
中,第i个数是i
右边小于perm[i]
的元素个数.因此,给定一个排列,您可以先计算它的 LC,然后将 LC 从阶乘系统转换为 int,从而为您提供排列的索引。
完整代码:
// int => LC
function int2lc(n, len) {
let lc = []
for (let i = 1; i <= len; i++) {
lc[len - i] = (n % i)
n = (n / i) | 0
}
return lc
}
// LC => int
function lc2int(lc, len) {
let n = 0, f = 1
for (let i = 1; i <= len; i++) {
n += lc[len - i] * f
f *= i
}
return n
}
// LC => permutation
function lc2perm(a, lc) {
let perm = [], copy = [...a]
for (let i = 0; i < lc.length; i++) {
perm[i] = copy[lc[i]]
copy.splice(lc[i], 1)
}
return perm
}
// permutation => LC
function perm2lc(perm) {
let lc = []
for (let i = 0; i < perm.length; i++) {
let c = 0
for (let k = i + 1; k < perm.length; k++)
c += perm[k] < perm[i]
lc[i] = c
}
return lc
}
//
A = [0,1,2,3,4,5,6,7,8,9]
// index to perm
N = 123456
lc = int2lc(N, A.length)
console.log('LEHMER', ...lc)
perm = lc2perm(A, lc)
console.log('PERMUT', ...perm)
// perm to index
lc2 = perm2lc(perm)
console.log('LEHMER', ...lc2)
M = lc2int(lc2, A.length)
console.log('INDEX ', M)