[Javascript] una funzione ricorsiva che non capisco come lavori

jomla

Nuovo Utente
30 Mag 2017
5
0
1
66
Ciao a tutti.
Prendete per favore in considerazione la funzione cc() del seguente script.
E' una funzione che calcola le combinazioni fra lettere o numeri a gruppi di 2 oppure 3 a scelta cambiando il parametro k.
Il suo funzionamento mi risulta comprensibile finchè k diventa 0 poi non capisco più niente in quanto continua a funzionare lo stesso con k=0.
A un certo punto però k diventa 2 e i che era già al limite dell'array ritorna ad essere 2
.
A questo punto io non ci capisco più niente
PS
L'editor di questo messaggio mi ha fatto impazzire perchè salta in su e giù
<HTML>
<html>
<head>
<style>
*{font-size:120px;text-align:center}
</style>

<script type="text/javascript">
var ret=[];
function cc(letters, comb, m, k) {

var t=1;
if (k == 0) {
document.writeln(comb + '<br />');

} else {
for (var i=m; i<= letters.length-k; ++i) {

cc(letters, comb+" "+letters+' ', i+1, k-1);
}
}

}
</script>
</head>
<body>
<script type="text/javascript">
var n=new Array("a","b","c","d","e");
cc(n,"",0,2);

</script>
</body>
</html>
</HTML>
 

WmbertSea

Utente Attivo
28 Nov 2014
159
21
28
Ciao, a parte la tua confusione, quale è esattamente la richiesta?
Sei partito in quarta e, credimi, è difficile capire cosa ti si debba rispondere senza sapere contro cosa stai combattendo.

In questo caso la regola d'oro è "aiuta gli altri ad aiutarti".

Cerchiamo di chiarire in ordine i vari punti che hai omesso ed eventualmente rispondi in modo dettagliato se hai interesse di ricevere aiuto:
  1. Quale è il contesto?
    Si tratta di un esercizio di tipo scolastico, di lavoro, di un tuo personale progetto, o cos'altro?
    Utile a capire quale è il tuo livello di esperienza e come rapportarsi con te nel risponderti.

  2. Quale è l'obbiettivo?
    Quella funzione è farina del tuo sacco o è un qualche vago copia-incolla?
    Cioè stai cercando di realizzare qualcosa da zero e ti serve aiuto a capire eventualmente quale può essere un metodo opportuno per procedere, oppure avevi già in mente la tua idea e stai cercando di adeguare un qualche script pescato a random sul web e non capisci come funziona?

  3. Cosa intendi per "funzione che calcola le combinazioni"?
    Io l'ho provata ma non mi calcola nulla; soltanto, stampa a video la stessa stringa ripetuta secondo il numero di iterazioni eseguite. Se parli di "calcolo" mi aspetterei un qualche valore che indichi il numero di combinazioni, o magari la visualizzazione delle varie combinazioni degli elementi nell'array, ma questo non lo fa.
    Ti chiedo quindi: la funzione è finita così o e ancora da sviluppare e ti sei arenato perché non capisci come lavora esattamente.

  4. Cosa intendi per "continua a funzionare lo stesso con k=0"?
    Esaminando lo script, quando k arriva al valore 0 la funzione non viene più richiamata; è chiaro però che tutte le precedenti chiamate all'interno del ciclo for devono essere portate a termine prima che k diventi 0. Tu cosa ti aspetti che faccia?

  5. Cosa non ti torna in questo: "A un certo punto però k diventa 2 e i che era già al limite dell'array ritorna ad essere 2"?
    Nel tuo esempio, k è uguale 2 solo la prima volta, durante la prima chiamata della funzione. Da quel che ho provato, non torna più a 2 ma va sempre decrementando fino a 0. Mentre la variabile i devi considerare che viene incrementata dentro il ciclo for e che inizialmente (per ogni iterazione della funzione) è popolata in base al valore di un'ulteriore variabile passata come parametro della funzione stessa; quindi il suo valore è contestuale ad ogni singola iterazione della funzione.
    Ti stai forse perdendo in questi concetti?
 

jomla

Nuovo Utente
30 Mag 2017
5
0
1
66
Ciao, a parte la tua confusione, quale è esattamente la richiesta?...............................................................................................................................................................................
Ciao e innanzitutto grazie per avermi risposta.

Prima di tutto devo dire che io sono un vecchio proff. di agraria in pensione.
Gestisco da sempre un mio sito costruito tutto da me in hrml5, css,javascript, php -mysql.
La mia conoscenza di javascript è media legata PERO' solo ai problemi che in 20 anni ho incontrato.
La funzione in oggetto non è legata al mio sito ma è uno sfizio matematico che attualmente ho risolto ma che non ho capito ancor oggi come lavori per dare il risultato che da.
L'avevo trovata in un sito di matematica che però non funzionava.
Col tempo l'autore l'ha modificata finchè ne ha pubblicata una diversa che io ho inserito in una pagina html che funziona molto bene

ma di cui continuo a non capire come faccia ad ottenere i risultati che da.
Ti passo l'intera mia pagina in cui ho implementato la funzione cc().
I campi del form li ho già valorizzati con valori di default che tu puoi cambiare.
Il primo campo accetta numeri e lettere divisi da uno spazio mentre il secondo campo accetta numeri da 2 al numero massimo di valori che hai inserito nel primo campo.
La tabella in cui vengono visualizzate le combinazioni è dinamica unicamente per mio piacere personale

Ciao



Codice:
<!doctype html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Calcolo combinazioni</title>

<style>


table{width:60%;margin:5% auto;border-collapse:collapse;padding:100px 0 100px 0}

table, tr,td {border:1px solid white;padding:2%;text-align:center}

</style>

<script>

var ret=[];

var t=1;

var k=0;

var full="<table><tr>";

function check()

{var z=1;

ret=[];

t=1;

var comb="";

var start=0;

var a=document.getElementById('arrai').value;

var k=document.getElementById('cappa').value;

a=a.split(' ');

cc(a,comb,start,k);

full="<table><caption><h1>combinazioni di "+k+" numeri</h1><br></caption><tr>";

var w=a.length-k;



for (var x=0;x<ret.length ;x++ )

{

full+="<td>"+ret[x]+"</td>";



if(z % w ==0)

{

full+="</tr><tr>";

}

z++;

}

full+="</tr></table><br><br><br>";

document.getElementById("disp").innerHTML =full;

}



function cc(c,g,j,k){



if(k==1)


for(var i=j;i<=c.length-k;i++)

{ret.push(g+c[i]+" ["+t+"°]<br>");t++;

}

else

{

for (var i=j;i<c.length;i++)

{

cc(c,g+c[i]+"-",i+1,k-1);

}

}



}

</script>

</head>

<body>

<form><div>

<input type ="text" id="arrai" value="1 2 3 4 5 6 7">scrivi i valoi che vuoi divisi da uno spazio (anche lettere)<br>

<input type ="text" id="cappa" value="3">scrivi un numero da 2 alla lunghezza massima del primo campo<br>

<input type="button" onclick="check();" value="calcola combinazioni"><br>

</div>

</form>

<br>

<div id="disp" style="background-color:black;color:yellow;height:auto;border:1px solid red;width:auto;font-size:150%;padding:1%"><h2>combinazioni</h2></div>

</body>

</html>
 

WmbertSea

Utente Attivo
28 Nov 2014
159
21
28
Ciao, benissimo, ora è certamente un po' tutto più chiaro.

Tu pensa che leggendo solo il tuo primo post ti avevo inquadrato come uno studente degli ultimi anni di un qualche liceo, che si cimentava in qualche esercizio appioppatogli da qualche vecchio prof :D

Anche se questo non dovrebbe influire sull'atteggiamento di chi eventualmente risponde, è comunque sempre importante, soprattutto quando si fa una richiesta in un forum come in questo caso, fornire quanti più dettagli possibili così da dare modo a chi ti legge (magari per la prima volta) di comprendere appieno il contesto e il senso stesso della richiesta, quindi poter fornire a sua volta delle risposte più precise e mirate a quella particolare situazione.

Chiaramente sono giusto dei consigli da un vecchio frequentatore di forum.

Venendo alla tua richiesta, abbiamo inquadrato che si tratta di "calcolo combinatorio" e in particolare di un sistema che elabora e mostra le possibili "combinazioni semplici" secondo vari parametri.

Nel tuo secondo post hai riportato l'intero codice funzionante. Questo è importante perché vedendo il codice del primo post, chiaramente mancante di quelle parti che danno un responso anche visivo (così da poterne valutare anche il corretto funzionamento), mi era difficile capire se ti serviva "aggiustare" la funzione in sé piuttosto che avere giusto delle informazioni per comprendere come questa lavori.

Detto ciò, parto con qualche consiglio iniziale. In generale, quando si sviluppa del codice, è importante fare uso di tutte quelle tecniche, convenzioni e buone pratiche riguardo la buona programmazione, così che dovendo riesaminare in futuro il proprio elaborato si abbiano dei riferimenti utili, se non indispensabili, per comprendere meglio come funziona il tutto. Questo a grandi linee.
E' chiaro che nel caso specifico tu non abbia troppa colpa dal momento che stai prendendo del codice elaborato da terzi per adeguarlo ad un tuo progetto.

In questo caso, prima di entrare in un discorso troppo tecnico sul funzionamento di quel codice, il mio secondo consiglio è quello di riprendere l'intero codice riga per riga, quindi "riscriverlo" secondo, appunto, quelle buone regole di programmazione. Certo, capisco che (come hai scritto) avendo un livello medio di programmazione, per te sarebbe impensabile procedere in questo modo. Su questo posso venirti in aiuto. Anche io non posso dire comunque di avere un'esperienza universitaria riguardo la programmazione ma ho qualche buona base e avrei il piacere (per sfizio personale) di "abbellire" il tuo codice cosi che ti aiuti a capire meglio alcuni aspetti prima di passare eventualmente ad un discorso più tecnico.

Io procederei in questo modo:

- Applicare una corretta indentazione a tutto il codice. Non so se il tuo codice originario è indentato, ma ciò che hai riportato qui non lo è affatto. Ad ogni modo risulta molto utile utilizzare una corretta indentazione per poter comprendere l'organizzazione gerarchica delle varie parti di codice e script, cosi da avere una percezione migliore su come queste agiscono all'interno del loro contesto. Se utilizzi editor avanzati per la stesura del codice, spesso trovi già degli strumenti che ti aiutano ad indentarlo; diversamente puoi usare anche strumenti come questo (o altri che puoi trovare con una ricerca del tipo "indent online") per ottenere facilmente una rapida formattazione del tuo elaborato. Se può interessarti vedi in generale anche l'argomento "indentazione" nell'ambito della programmazione.

- Attribuire un nome consono e autoesplicativo ad ogni elemento, variabile e funzione. Questo chiaramente aiuta a determinare in modo rapido quale sia il ruolo di ogni singolo elemento. Se può interessarti vedi anche argomenti come design pattern e camel case.

- Usare la "modalità strict". Probabilmente in questo caso non è così necessario ma serve più che altro per essere forzati all'uso di alcune regole più rigide durante lo sviluppo dello script così da ottenere una struttura meglio definita del codice.

- Applicare dei commenti per le varie parti più o meno rilevanti del codice. Aiuta te, ed eventuali altri sviluppatori che mettono mano al tuo codice, a comprendere esattamente cosa fa o deve fare ogni parte/riga del codice, così anche riprendendo il codice a distanza di tempo è possibile interpretarne correttamente le funzionalità. Particolarmente utile soprattutto a scopo didattico proprio per poter trasmettere, agli altri utilizzatori del mio codice, tutte quelle informazioni necessarie a comprenderne appieno il funzionamento.

- In JavaScript fare eventuale uso della funzione "console.log()" per controllare fasi del processo durante l'esecuzione dello script e/o eventuali valori utilizzati, così da poter comprendere meglio, appunto, i vari passaggi che questo compie. Utile in genere per la fase di debug ma anche in casi esemplificativi e/o a scopo didattico.

Direi che per il momento la lezione è terminata :D
A parte gli scherzi, proverò a cimentarmi (lo faccio comunque anche per mio diletto) nella rielaborazione del tuo codice secondo i punti appena indicati. Da lì sicuramente avrai modo di apprezzarne meglio il funzionamento; eventualmente si potrà procedere poi con un discorso più tecnico e dettagliato se lo ritieni opportuno.

Buona serata.
 

jomla

Nuovo Utente
30 Mag 2017
5
0
1
66
iù tecnico e dettagliato se lo ritieni opportuno.

.....................................................
.....................................................................
Buona serata.
dunque,
la formattazione c'era e penso si sia persa nel copia incolla.
Io uso da sempre editplus che formatta automaticamente.
La formattazione avviene man mano che scrivo tranne quando faccio modifiche all'interno di testo già scritto.
Nei miei programmi faccio pochissimi commenti e questo so che è un errore.
Le variabili normalmente le scrivo con nomi italiani interi ma non sempre.
Nei cicli for, while ecc. uso solo lettere tranne nei cicli while mysql.
Ciao buona serata anche a te
 

WmbertSea

Utente Attivo
28 Nov 2014
159
21
28
Ciao, come precedentemente avevo accennato, ho giochicchiato un po' col codice da te proposto.
Per il momento mi preme fare giusto qualche anticipazione prima di postare poi l'elaborato.

Posso dirti che, dopo svariate peripezie, sono arrivato ad un buon risultato. A parte l'applicazione dei punti indicati nel mio ultimo post (sostanzialmente, rielaborazione e ottimizzazione dell'intero codice), mi sono dilettato a cercare di sviluppare un metodo che potesse in qualche modo aiutare a capire (dal punto di vista umano) come l'interprete JavaScript effettua i vari passaggi che vengono eseguiti durante l'esecuzione di uno script, che può avere anche una certa complessità come in questo caso in cui ci si scontra con la presenza di funzioni ricorsive.

A grandi linee ho sviluppato un sistema che, attraverso la console log del proprio browser, possa mostrare in modo dettagliato ciò che avviene durante l'esecuzione dello script. Eseguito lo script, nella console apparirà quindi un rapporto formattato e dettagliato con tutte le descrizioni del caso per poter comprendere al meglio i diversi passaggi più o meno complicati dello script. Si tratta più che altro di un piccolo strumento per uso didattico. E' chiaro che nulla avviene in modo automatico ma il tutto deve essere impostato opportunamente all'interno dello script da qualcuno che abbia già una discreta conoscenza di come tale script funzioni. Ovviamente in questo caso me ne sono occupato io.

Devo precisare che ho fatto dei test su Win 10 con delle attuali versioni di FireFox, Chrome, Edge e Safari.
Solo su FF e CH ho ottenuto dei risultati apprezzabili. Su CH un po' meno ma comunque accettabile, mentre gli altri browser, su cui ho provato, non supportano alcune funzionalità, quindi daranno un risultato scadente e praticamente non utilizzabile per lo scopo. Questo chiaramente solo per ciò che riguarda lo strumento didattico, non per ciò che riguarda invece il codice del progetto in sé, che comunque funziona egregiamente.

In particolare si fa uso di alcuni metodi dell'oggetto console (vedi questa documentazione per una panoramica).
Non è detto che non funzioni magari anche su altri browser ma è forse preferibile disporsi già per l'utilizzo su FF oppure CH.

Fammi comunque sapere se non ci sono problemi riguardo questo punto.
A breve posterò il mio elaborato ed eventualmente ti darò indicazioni su come proseguire.

Per ora è tutto, buona serata.
 

WmbertSea

Utente Attivo
28 Nov 2014
159
21
28
Ho preso un po' di tempo per mettere a punto il tutto.

In allegato trovi uno zip contenente un file html col codice rivisto, ottimizzato e commentato nel dettaglio. Una volta estratto il file dallo zip, puoi intanto eseguirlo per verificarne il funzionamento; puoi quindi aprirlo sul tuo editor e leggere i vari commenti (in particolare quelli che ho inserito all'interno della parte JavaScript) così da iniziare a comprendere i principi di funzionamento e le dinamiche della ricorsione riguardo quella specifica funzione.

Per il momento attendo un tuo riscontro. Fammi sapere se hai bisogno di altri eventuali chiarimenti prima di proseguire; quindi posterò in seguito il file comprendente il suddetto strumento didattico con le funzioni di log, così da poter entrare maggiormente nel dettaglio per poter comprendere meglio i vari passaggi ricorsivi della funzione.

Attendo tue nuove, buona lettura.
 

Allegati