Страницы

Поиск по вопросам

вторник, 30 октября 2018 г.

Как сделать такой же код без eval'a?

Я делаю "генетический калькулятор", он должен "скрещивать" каждую букву каждого элемента 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 тест для составления списка аргументов.

Комментариев нет:

Отправить комментарий