Was ist eine gute Möglichkeit, variable verschachtelte Schleifen zu strukturieren?

Angenommen, Sie arbeiten in einer Sprache mit Arrays variabler Länge (z. B. mit A[i] for all für alle i in in 1..A.length) and have to write a routine that takes ) und müssen eine Routine schreiben, die n ( ( n : 1..8) variable length arrays of items in a variable length array of length ) Variable-Länge-Arrays von Elementen in einem Array variabler Länge der Länge n, and needs to call a procedure with every possible length verwendet und eine Prozedur mit jeder möglichen Länge n array of items where the first is chosen from the first array, the second is chosen from the second array, and so forth. Array von Elementen aufrufen muss, bei denen das erste Array aus dem ersten Array ausgewählt wird. wird das zweite Array aus dem zweiten Array ausgewählt usw.

Wenn Sie etwas Konkretes visualisieren möchten, Stellen Sie sich vor, Dass Ihre Routine Daten wie:

[ [ 'top hat', 'bowler', 'derby' ], [ 'bow tie', 'cravat', 'ascot', 'bolo'] ... ['jackboots','galoshes','sneakers','slippers']]

nehmen und die folgenden Prozeduraufrufe (in beliebiger Reihenfolge) tätigen muss:

try_on ['top hat', 'bow tie', ... 'jackboots']
try_on ['top hat', 'bow tie', ... 'galoshes']
 :
try_on ['derby','bolo',...'slippers']

Dies wird manchmal als chinesisches Menüproblem bezeichnet, und für feste n can be coded quite simply (e.g. for kann ganz einfach codiert werden (z.B. für n = 3, in pseudo code) = 3, in Pseudo-Code)

procedure register_combination( items : array [1..3] of vararray of An_item)
    for each i1 from items[1]
        for each i2 from items[2]
            for each i3 from items[3]
                register( [ii,i2,i3] )

Aber was ist, wenn n can vary, giving a signature like: variieren kann, eine ähnliche Signatur gebend :

procedure register_combination( items : vararray of vararray of An_item)

Der geschriebene Code enthielt eine hässliche Fallanweisung, die ich durch eine viel einfachere Lösung ersetzte. Aber ich bin mir nicht sicher, ob es der beste (und es ist sicherlich nicht der einzige) Weg, dies umzugestalten.

Wie würden Sie es tun? Clever und überraschend sind gut, aber klar und wartungsfähig sind besser - ich gehe gerade durch diesen Code und möchte nicht zurückgerufen werden. Prägnant, klar und clever wäre ideal.

Bearbeiten: Ich werde meine Lösung später heute veröffentlichen, nachdem andere die Möglichkeit hatten, zu antworten.

Teaser: Ich habe versucht, eine rekursive Lösung zu verkaufen, aber sie würden es nicht tun, also musste ich mich daran halten, fortran in einer HLL zu schreiben.

Die Antwort, mit der ich ging, unten gepostet.

Antwort auf "Was ist eine gute Möglichkeit, variable verschachtelte Schleifen zu strukturieren? " 3 von antworten

Rekursion.

Oder, besser noch, versuchen, Rekursion mit stapelähnlichen Strukturen und while-Anweisungen zu beseitigen.

Für Ihr Problem, das Sie angegeben haben (Aufrufen einer Funktion mit Variablenargumenten), hängt es ganz von der Programmiersprache ab, in der Sie codieren; viele von ihnen ermöglichen das Übergeben von Variablenargumenten.

Entweder der rekursive Algorithmus

procedure register_combination( items )
        register_combination2( [], items [1:] )

procedure register_combination2( head, items)
    if items == []
        print head
    else
       for i in items[0]
           register_combination2( head ++ i, items [1:] )

oder derselbe mit tail-Aufrufen optimiert, wobei ein Array für die Indizes verwendet wird und der letzte Index so lange inkrementiert wird, bis er die Länge des entsprechenden Arrays erreicht und dann das Inkrement nach oben trägt.

Da sie gegen Rekursion waren (bitte nicht fragen) und ich gegen chaotische Fallaussagen war (die, wie sich herausstellte, a bug) I went with this: versteckten, ging ich mit:

procedure register_combination( items : vararray of vararray of An_item)
    possible_combinations = 1
    for each item_list in items
        possible_combinations = possible_combinations * item_list.length
    for i from 0 to possible_combinations-1
        index = i
        this_combination = []
        for each item_list in items
            item_from_this_list = index mod item_list.length
            this_combination << item_list[item_from_this_list]
            index = index div item_list.length
        register_combination(this_combination)

Grundsätzlich finde ich heraus, wie viele Kombinationen es gibt, weise jeder eine Zahl zu und schleife dann die Zahl, die die entsprechende Kombination erzeugt. Kein neuer Trick, vermute ich, aber einer wissenswerten.

Es ist kürzer, funktioniert für jede praktische Kombination von Listenlängen (wenn es mehr als 2 bis 60 Kombinationen gibt, haben sie andere Probleme), ist nicht rekursiv und hat nicht the bug. .