感谢 peg.js 的强大功能,如果元素列表s
是一组元素的组合S
(不允许重复),提供一个返回 true(并使用输入)的检查函数并不难。基本思想是计算 的幂集S
并将 的每个元素映射s
到素数。的每个元素S
映射到其对应元素的素数的乘积,即幂集的每个元素S
映射到唯一的数字。一个集合s
是元素的组合S
当且仅当相应素数的乘积在s
从计算的素数乘积中S
. (我想,执行此检查的方法不止一种 :-))。下面是 peg.js 的一个解决方案,它有 5 个我认为非常有效的元素。(使用时的一个小问题& { predicate }
:内部的 javascript 使用参数对象中的所有命名表达式调用,因此(a / b /c /d /e)+
必须有一个名称,例如el:(a / b /c /d /e)+
)。
{
// array of elements (expressions)
var data = ['a','b','c', 'd', 'e'];
// map elements to primes
var primemap = {
a: 2,
b: 3,
c: 5,
d: 7,
e: 11
};
// powerset of an array
function powerset(arr) {
var ps = [ [] ];
for (var i=0; i < arr.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(arr[i]));
}
}
return ps;
}
// compute the product of primes corresponding to each element of an array arr
function primeprod(arr) {
return arr.reduce( function(p,c) { return p * primemap[c] }, 1 );
}
// compute powerset and remove empty set at index 0 of the powerset
var ps = powerset(data);
ps.splice(0,1);
// map elements of powerset to products of primes
var prods = ps.map( function(el) { return primeprod(el); });
// returns true if an arr is a combination of the elements
function isCombination(arr) {
return prods.indexOf(primeprod(arr)) !== -1
}
}
expr = exp / blankline;
exp = (el:(a / b / c / d / e)+ &{ return isCombination(Array.prototype.slice.call(arguments)[0]); } {return el; } ) rest*
a = _ a:'a' {return a; }
b = _ b:'b' {return b; }
c = _ c:'c' {return c; }
d = _ d:'d' {return d; }
e = _ e:'e' {return e; }
rest = [^abcde]
blankline =
[ \t]* ("\n" / eof) { return []; }
_ = [ \t]*
eof = !.