Профил
Loading...
+ Нов въпрос
Reath avatar Reath 188 Точки

Започване на рекурсия от даден index

Разглеждайки начини как динамично да създавам вложени цикли, стигнах до следния отговор в stackoverflow който предлага решение на този проблем чрез рекурсия: https://stackoverflow.com/a/4683760/4138686

 

Това е кода

function callManyTimes(maxIndices, func) {
    doCallManyTimes(maxIndices, func, [], 0);
}

function doCallManyTimes(maxIndices, func, args, index) {
    if (maxIndices.length == 0) {
        func(args);
    } else {
        var rest = maxIndices.slice(1);
        for (args[index] = 0; args[index] < maxIndices[0]; ++args[index]) {
            doCallManyTimes(rest, func, args, index + 1);
        }
    }
}
като той се извиква по този начин:
callManyTimes([2,3,5], doSomething);

Работи страхотно, но в програмата която правя извършвам итерации от сорта на [2000, 2000, 2000] което е огромно число и искам да направя функционалност за запазване на стейта. За да направя това записвам до кои index-и съм стигнал в localStorage, проблема обаче е в случай на рестарт как чрез този код горе да започна рекурсията от дадени index-и? Например не искам да започна от [0, 0, 0] ами от [3, 3, 3]. Представям си да извиквам функцията така:
callManyTimes([2000,2000,2000], doSomething, [942, 800, 0]);
Като новия, трети, параметър да са index-ите от които да започне рекурсията. Какво ли не пробвах, знам че трябва да стартирам for цикъла от дадено число, но не мога да направя сметките. За да ви стане ясно как работи горния код ви съветвам да извикате с console.log, за да видите какво печата и как increment-ва index-ите.
callManyTimes([2,3,5], function(iterators) {
    console.log(iterators);
});

 

Тагове:
0
Module: JS Advanced
qwertyto avatar qwertyto 15 Точки

За какво ти е да извикваш функция 8 милиарда пъти в динамично генерирани цикли?

0
TeodorStefanovPld avatar TeodorStefanovPld 1278 Точки

и на мен ми се изгуби малко идеята на колегата :Д

callManyTimes([2000,2000,2000], doSomething, [942, 800, 0]); иначе това не ми се струва ок,по-скоро

callManyTimes([2000,2000,2000], doSomething,callManyTimes [iterators]) като по някакъв начин ще трябва да си записваш индексите които ти трябват и да ги подаваш просто,но малко се изгубих защо искаш да въртиш рекурсия в for цикъл и тои да се вика сам на определени индекси това дори само като го написах и звучи сттранно

0
Reath avatar Reath 188 Точки

Client side bruteforce :)

Знам, че javascript не е най-оптималните езици за постигане на целта, но поради някакви съображения съм написал програмата именно на js. Извинявам се ако съм описал странно проблема си, ще опитам отново.

 

Имам рекурсия благодарение на която мога да направя bruteforce с едно неизвестно, или с две, или с колкото си искам неизвестни. Единия for цикъл е просто инструмент с който рекурсивната функция си борави за да успее да направи имитацията на вложените цикли. Когато извикваме тази функция с параметъра maxIndices настроен на [5] ще ни викне callback функцията веднъж с 0, после с 1,2,3,4.. Ако извикаме рекурсията с параметър [3,3] ще започне първо от 0,1; 0,2; 1,0; 1,1; 1,2; 2,0; 2,1... Въпроса ми е ако вече съм минал през 0,1; 0,2, но програмата ми е била затворена, как при следващото стартиране да стартирам рекурсията директно от 1,0 и тя да продължи към 1,1; 1,2; 2,1...

 

Един вид искам същата тази рекурсивна функция да мога да я викам, но да мога да я настроя да не започва от 0леви index-и

0
Reath avatar Reath 188 Точки

В крайна сметка избрах да използвам тази функция за динамично създаване на вложени цикли:

function everyPermutation(args, fn, startFromIndexes) {
    let indices;

    if (startFromIndexes)
        indices = startFromIndexes;
    else
        indices = args.map(a => a.min);

    for (let j = args.length; j >= 0;) {
        fn.call(null, indices);

        // go through indices from right to left setting them to 0
        for (j = args.length; j--;) {
            // until we find the last index not at max which we increment
            if (indices[j] < args[j].max) {
                ++indices[j];
                break;
            }
            indices[j] = args[j].min;
        }
    }
}

//Normal usage
everyPermutation([
        {min: 0, max: 2},
        {min: 0, max: 2},
        {min: 0, max: 2}],
    function (iterators) {
        console.log(iterators)
    });

//Start from indexes
everyPermutation([
        {min: 0, max: 2},
        {min: 0, max: 2},
        {min: 0, max: 2}],
    function (iterators) {
        console.log(iterators)
    }, [2, 0, 0]);

Освен добавения бонус че си имам min & max параметри с които мога да упомена range за всеки index от пермутацията, благодарение на третия параметър мога да започна от дадени index-и

0