C'est un problème de Power Loop typique, et je n'ai besoin que d'un simple et élégant (compact ) solution ... Je vais montrer d'abord l'exemple de problème / solution avec les boucles for imbriquées . Supposons que je doive transformer ce morceau de code en une récursivité:
3 '000' 2 '00' 1 '0' 3 '001' 2 '01' 1 '1' 3 '010' 2 '10' 1 '0' 3 '011' 2 '11' 1 '1' ...
La sortie de 14 lignes uniques de cet exemple à 3 niveaux est
callManyTimes([2,2,2], show); function callManyTimes(maxIndices, func) { doCallManyTimes(maxIndices, func, [], 0); } function doCallManyTimes(maxIndices, func, args, index) { if (maxIndices.length == 0) { let x = args.slice(0); // cloning while(x.length>0) { func(x); // why send array[array]? x.shift(); } } else { var rest = maxIndices.slice(1); for (args[index] = 0; args[index] < maxIndices[0]; ++args[index]) { doCallManyTimes(rest, func, args, index + 1); } } } function show(...args) { if (typeof args[0] == 'object') args=args[0] // workaround... can optimize? let code = String( args.reduce( (ac,cur) => ''+ac+cur ) ) console.log( code.length, code ) }
4 Réponses :
Vous pouvez utiliser une fonction qui prend un tableau temporaire pour les valeurs générées.
function show(...args) { let code = args.join(''); console.log(code.length, code); } function callManyTimes(max, cb, items = []) { var i, temp; if (items.length === max.length) return; for (i = 0; i < max[items.length]; i++) { temp = items.concat(i); cb(...temp); callManyTimes(max, cb, temp); } } callManyTimes([2, 2, 2], show);
Une simple fonction récursive de retour en arrière les visitera dans l'ordre du premier exemple avec quelque chose comme:
function* iter(maxlength, prefix = []){ if (prefix.length >= maxlength) return for (let i = 0; i < 2; i++){ yield [i, ...prefix] yield * iter(maxlength, [i, ...prefix]) } } console.log([...iter(3)].map(a => a.join(',')))
Vous pouvez également générer un tableau avec la même idée et une fonction génératrice (ici, il renvoie un tableau de tableaux à joindre plus tard, mais le même principe):
function iter(maxlength, cur = ''){ if (cur.length >= maxlength) return for (let i = 0; i < 2; i++){ console.log(cur.length + 1 + ":", cur + i) iter(maxlength, cur + i) } } iter(3)
Vous réduisez le problème-échantillon en un algorithme de chaîne pure, mais il est très élégant (!), Il en est de même d'une réponse valable ... Eh bien, comment voter "accepté"? C'est peut-être pour les lecteurs le plus simple et le plus didactique, mais la solution de Nina est la plus utile pour moi.
Je pense que vous recherchez
callManyTimes([2,2,2], show); function callManyTimes(maxIndices, func, args=[]) { if (maxIndices.length == 0) { func(...args); } else { func(...args); var rest = maxIndices.slice(1); var index = args.length; args = args.slice(); for (args[index] = 0; args[index] < maxIndices[0]; ++args[index]) { callManyTimes(rest, func, args); } } } function show(...args) { let code = args.join(" "); console.log(args.length + ": "+ code ) }
Au lieu de cette boucle while
, vous voulez appeler func
une seule fois. Pour obtenir les résultats partiels, vous placez un appel func
avant la boucle avec les appels récursifs, comme vous l'avez fait dans votre version étendue. J'ai également éliminé le paramètre index
qui est juste le args.length
, et j'ai fait des copies de args
avant d'ajouter un nouveau niveau.
Vous devez également simplement utiliser la syntaxe de propagation pour l'appel, car vous recevez les arguments dans show
avec la syntaxe de paramètre rest.
Merci (!), Une correction parfaite de mon code "essayer de résoudre".
Oui, il vaut mieux répondre que votre question précédente :-)
Vous pouvez écrire la sortie à la main et utiliser .repeat()
const f = (a,b,c=[a+b,b+a,a+b+a,a+a+b,a+b+b,b+a+b,b+b+a,b+a+a]) => { for(let i=3;i;c.push(a.repeat(i),b.repeat(i)),i--);return c }; console.log(f('0','1'));
Bon programme one-liner (!), C'est comme un cache combinatoire ... Mais ce n'est pas général, il faut aussi un générateur combinatoire pour être général (il ne s'agit pas seulement de changer 3
en 8
pour obtenir la boucle à 8 niveaux).
@PeterKrauss Oui, la partie du code a été composée à la main en raison de la sortie restreinte. Similaire au fait d'avoir généralement moins d'octets à écrire let a = 'abcdefghijklmnopqrstuvwxyz
que a = `$ {Object.keys (top)}` .match (/ [az] / g) code > (non trié) ou
a = [... new Set (`$ {Object.keys (top)}` .match (/ [az] / g) .sort ())]. join