Я делаю "генетический калькулятор", он должен "скрещивать" каждую букву каждого элемента gens[[],[]] с другой другого элемента.
Есть такой код, который создаёт код, который затем исполняется:
for (var u in gens) {
var estr = "";
for (var i = 0; i < gens[u].length; i++) {
var na = gens[u][i].charAt(0).toUpperCase();
estr += 'for(var ' + na + '=0;' + na + '<=1;' + na + '++){
';
}
estr += 'var res=cross([';
for (var i = 0; i < gens[u].length; i++) {
var na = gens[u][i].charAt(0).toUpperCase();
estr += 'gens[' + u + '][' + i + '].charAt(' + na + '),';
}
estr = estr.substring(0, estr.length - 1);
estr += ']);
if(!test(gomets[' + u + '],res,true)){gomets[' + u + '].push(res);}
';
for (var i = 0; i < gens[u].length; i++) {
estr += '}
';
}
alert(estr);
//eval(estr);
}
Суть в том, что он при gens=[['AA','Bb'],['aa','BB']]; создаёт сначала код:
for (var A = 0; A <= 1; A++) {
for (var B = 0; B <= 1; B++) {
var res = cross([gens[0][0].charAt(A), gens[0][1].charAt(B)]);
if (!test(gomets[0], res, true)) {
gomets[0].push(res);
}
}
}
А потом
for (var A = 0; A <= 1; A++) {
for (var B = 0; B <= 1; B++) {
var res = cross([gens[1][0].charAt(A), gens[1][1].charAt(B)]);
if (!test(gomets[1], res, true)) {
gomets[1].push(res);
}
}
}
Суть в том, чтобы код создавал столько вложенных циклов, сколько элементов в gens[u], например, gens[0].
Каждый цикл должен считать от 0 до 1 (так длина строки "AA" ,"bb" и тд 2 символа) и записывать результат в переменную, имя которой соответствует gens[u].[номер элемента/цикла].charAt(0); в теле самого вложенного цикла исполняется функция, ей в параметры должен попадать масив с элементами gens[u][0].charAt(имя счётчика цикла), тк индекс колеблется от 0 до 1, то цикл берёт каждую букву. Я думал над алгоритмом, ничего лучше придумать не смог, т.к количество элементов в gens[u] колеблется и все буквы всех элементов надо по очереди передавать функции, а для этого нужно столько циклов, сколько элементов в gens[u]
Собственно вопрос: можно ли это организовать без eval'a?
ps Если что не понятно в вопросе, спрашивайте, я объясню.
UPD:
для gens=[['AA','Bb','Cc'],['aa','BB','Cc']]; генерируется код:
for (var A = 0; A <= 1; A++) {
for (var B = 0; B <= 1; B++) {
for (var C = 0; C <= 1; C++) {
var res = cross([gens[0][0].charAt(A), gens[0][1].charAt(B), gens[0][2].charAt(C)]);
if (!test(gomets[0], res, true)) {
gomets[0].push(res);
}
}
}
}
Ответ
Без рекурсии и излишних вложенных циклов.
Тут получается для каждого массива двоичная система. Соответственно комбинаций разных генов может быть 2^(длина массива). Надо перебрать все различные комбинации...
var gens = [['AA', 'Bb', 'Cc'], ['aa', 'BB', 'Cc']];
for (u in gens) {
var gen = gens[u];
for (var i = 0; i < 1 << gen.length; i++) {// 2^длина массива комбинаций
var args = [];
for (var j = 0; j < gen.length; j++) {// создаем массив разных сочетаний
var gi = (i & (1 << j)) >> j;// получаем индекс буквы
// по номеру комбинации
// и по номеру индекса элемента массива
// (сорри в генетике не силен,
// что как называется не в курсе)
args.push(gen[j].charAt(gi));// заполняем массив параметров для cross
}
var res = cross(args);
if (!test(gomets[u], res, true)) {
gomets[u].push(res);
}
}
}
JsFiddle тест для составления списка аргументов.
Комментариев нет:
Отправить комментарий