2015-08-13 10 views
5

Sto provando a creare una versione ricorsiva dei seguenti cicli nidificati e ottenere gli stessi risultati del codice di riferimento. L'esempio è sotto.Provare a convertire il ciclo annidato in funzione ricorsiva

Questa è una versione su Codepen http://codepen.io/anon/pen/XbQMLv

(L'intento del codice è quello di uscita solo combinazioni uniche di interi da indici.)

codice e di uscita originale:

var len = 4; 

for (var a = 0; a < len; a++) { 
    for (var b = a + 1; b < len; b++) { 
    for (var c = b + 1; c < len; c++) { 
     console.log(a, b, c); 
    } 
    } 
} 
// Outputs: 
// 0 1 2 
// 0 1 3 
// 0 2 3 
// 1 2 3 

codice ricorsivo e uscita:

var len = 4; 
var end = 3; 
var data = []; 

var loop = function (index) { 
    if (index === end) { 
    console.log(data); 
    return; 
    } 
    for (var i = index; i < len; i++) { 
    data[index] = i; 
    loop(i + 1); 
    } 
} 

loop(0); 
// Outputs: 
// [ 0, 1, 2 ] 
// [ 0, 2, 3 ] 
// [ 1, 3, 2 ] 
// [ 2, 3, 3 ] 

Non sono sicuro di cosa mi manchi qui.

+0

Come state usando 'FINE' con i loop? – elclanrs

+0

Se vuoi combinazioni univoche, vuoi dire che vuoi permutazioni di quella matrice? – elclanrs

+0

@elclanrs corretto – Geuis

risposta

3

si ha un solo piccolo errore nel codice:

si chiama una funzione ricorsiva dal i + 1, ma non il vostro index + 1.
Fa sì che index sia uguale all'array non attuale ma al valore.

Ad esempio, quando hai superato [0, 1, 2], i dati ora è [0, 1] e che si sta per inserire 3, si chiama loop(3 + 1), index 4 va fuori di un intervallo di matrice. La condizione if (index === end) non riesce e non viene emessa. Anche il ciclo for (var i = index; i < len; i++) fallisce e tutto va storto.

dovrebbe essere:

var len = 4; 
var end = 3; 
var data = []; 

var loop = function (index) { 
    if (index === end) { 
    console.log(data); 
    return; 
    } 
    for (var i = index; i < len; i++) { 
    data[index] = i; 
    loop(index + 1); // <--- HERE 
    } 
} 

loop(0); 

Ecco il lavoro JSFiddle demo.

Aggiornamento:

Oh, ora vedo. È necessaria la condizione a[i] > a[i-1] per tutte le combinazioni. Basta aggiungere una variabile start che salverà l'ultimo valore inserito per soddisfare questa regola.

var len = 4; 
var end = 3; 
var data = []; 

var loop = function (start, index) { 
    if (index === end) { 
    document.body.innerHTML += "<br/>" + data; 
    return; 
    } 
    for (var i = start; i < len; i++) { // We start from 'start' (the last value + 1) 
    data[index] = i; 
    loop(i + 1, index + 1); // Here, we pass the last inserted value + 1 
    } 
} 

loop(0, 0); // At beginning, we start from 0 

Updated JSFiddle demo with passing argument.

È possibile controllare il valore precedente anziché passare un valore come argomento se sembra sbagliato. La condizione sarà come "se è un primo numero, inizia da 0, altrimenti - inizia dal numero successivo a quello precedente".

var start = (index === 0 ? 0 : data[index-1] + 1); 

Updated JSFiddle demo with calculating start.

+0

Grazie, ma questo non è il risultato previsto. La tua versione sta iterando attraverso tutte le possibili versioni. Sto cercando di abbinare l'output dei loop nidificati per l'esempio originale. – Geuis

+0

@Geuis Lo aggiorna di nuovo :) –

+0

Grazie Santo! Un bug così sottile che mi è mancato. Stavo usando 'index' come inizio e stavo pensando che da quando è stato incrementato su ogni chiamata a loop() che dovrebbe essere sufficiente. Ho perso totalmente il fatto che da quando è stato incrementato nel ciclo stava buttando via gli indici per l'aggiornamento dei dati! – Geuis

2

Dato che si hanno tre cicli uno all'interno di un altro, è necessario passare 2 argomenti per la funzione di ricorsione.

var len = 4; 
 
var end = 3; 
 
var data = []; 
 

 
var loop = function(start, index) { 
 
    if (index === end) { 
 
    console.log(data); 
 
    return; 
 
    } 
 
    for (var i = start; i < len; i++) { 
 
    data[index] = i; 
 
    loop(i + 1, index + 1); //Pass as like a+1 & b+1 
 
    } 
 
} 
 

 
loop(0, 0);

2

ci sono un paio di errori; stai ricorsivamente a partire da i+1 anziché da index+1 e stai contando da index invece di contare da data[index-1]+1.

La versione corretta è:

var len = 4; 
var end = 3; 
var data = []; 

var loop = function (index) { 
    if (index === end) { 
    console.log(data); 
    return; 
    } 
    for (var i = (index==0 ? 0 : data[index-1]+1); i < len; i++) { 
    data[index] = i; 
    loop(index + 1); 
    } 
} 
0

uscita esattamente il risultato atteso.

var len = 4; 
 
var end = 3; 
 
var data = []; 
 

 
var loop = function(i) { 
 
    if(data.length === end) { 
 
    // console.log(data); -> Wont work in snippet 
 
    
 
    // Snippet workaround 
 
    document.getElementsByTagName('body')[0].innerHTML += data.join(',') + '<br/>'; 
 
    return; 
 
    } 
 

 
    if(i >= len) 
 
    return; 
 

 
    data.push(i); 
 
    loop(i + 1); 
 

 
    data.pop(); 
 
    loop(i + 1); 
 
}; 
 

 
loop(0);

Problemi correlati