2012-10-24 22 views
7

Próbuję wykonać funkcję z każdą pojedynczą kombinacją elementów z tabeli. (In Lua). Tabela i elementy mogą się zmieniać, ale struktura pozostanie taka sama. Tabela jest zorganizowana w taki sposób, że [1] jest pierwszym argumentem funkcji i tak dalej.Znajdowanie każdej kombinacji elementów w tabeli (Lua/PseudoCode)

Jeśli jest to tabela, które mam,

Table = { 
    [1] = {Player1, Player2} 
    [2] = {PlayerA, PlayerB, PlayerC} 
    [3] = {PlayerOne, PlayerTwo} 
} 

Gdybym napisał, że się ręcznie, to prawdopodobnie wyglądać tak: (zważywszy, że funkcja nazywa EXE).

Exe(Player1, PlayerA, PlayerOne) 
Exe(Player2, PlayerA, PlayerOne) 
Exe(Player3, PlayerA, PlayerOne) 

Exe(Player1, PlayerB, PlayerOne) 
Exe(Player2, PlayerB, PlayerOne) 
Exe(Player3, PlayerB, PlayerOne) 

Exe(Player1, PlayerC, PlayerOne) 
Exe(Player2, PlayerC, PlayerOne) 
Exe(Player3, PlayerC, PlayerOne) 


Exe(Player1, PlayerA, PlayerTwo) 
Exe(Player2, PlayerA, PlayerTwo) 
Exe(Player3, PlayerA, PlayerTwo) 

Exe(Player1, PlayerB, PlayerTwo) 
Exe(Player2, PlayerB, PlayerTwo) 
Exe(Player3, PlayerB, PlayerTwo) 

Exe(Player1, PlayerC, PlayerTwo) 
Exe(Player2, PlayerC, PlayerTwo) 
Exe(Player3, PlayerC, PlayerTwo) 

Jednak nie chcę napisać, że obecnie, i to łamie mi ogólną regułą, że jeśli kopiowania i wklejania w programie, robisz to źle.

Zamiast tego chciałbym przejść przez tabelę i wykonać każdą możliwą kombinację. Problem polega na tym, że tabela może (potencjalnie) mieć dowolną liczbę tabel wewnątrz niej, a także, że tabela wewnątrz tabeli może potencjalnie mieć nieograniczoną liczbę wartości.

Na przykład, tabela może skończyć patrząc tak:

Table = { 
    [1] = {Player1, Player2} 
    [2] = {PlayerA} 
    [3] = {PlayerOne} 
} 

W której wykonanie będzie wyglądać jak to ręcznie:

Exe(Player1, PlayerA, PlayerOne) 
Exe(Player2, PlayerA, PlayerOne) 

Również tabela może skończyć jak ten :

Table = { 
    [1] = {Player1, Player2} 
    [2] = {PlayerA} 
    [3] = {PlayerOne} 
    [4] = {PlayerUno, PlayerDos} 
    [5] = {PlayerApple, PlayerBoy, PlayerCat, PlayerDog} 
} 

W którym exeuction skończy się jak ..

Exe(Player1, PlayerA, PlayerOne, PlayerUno, PlayerApple) 
Exe(Player2, PlayerA, PlayerOne, PlayerUno, PlayerApple) 

Exe(Player1, PlayerA, PlayerOne, PlayerDos, PlayerApple) 
Exe(Player2, PlayerA, PlayerOne, PlayerDos, PlayerApple) 


Exe(Player1, PlayerA, PlayerOne, PlayerUno, PlayerBoy) 
Exe(Player2, PlayerA, PlayerOne, PlayerUno, PlayerBoy) 

Exe(Player1, PlayerA, PlayerOne, PlayerDos, PlayerBoy) 
Exe(Player2, PlayerA, PlayerOne, PlayerDos, PlayerBoy) 


Exe(Player1, PlayerA, PlayerOne, PlayerUno, PlayerCat) 
Exe(Player2, PlayerA, PlayerOne, PlayerUno, PlayerCat) 

Exe(Player1, PlayerA, PlayerOne, PlayerDos, PlayerCat) 
Exe(Player2, PlayerA, PlayerOne, PlayerDos, PlayerCat) 


Exe(Player1, PlayerA, PlayerOne, PlayerUno, PlayerDog) 
Exe(Player2, PlayerA, PlayerOne, PlayerUno, PlayerDog) 

Exe(Player1, PlayerA, PlayerOne, PlayerDos, PlayerDog) 
Exe(Player2, PlayerA, PlayerOne, PlayerDos, PlayerDog) 

Jak widać, znalazłem wzór ... Byłem w stanie podzielić powyższą rzecz "Wykonanie" powyżej na segmenty/grupy, takie jak linia 1 i linia 2 mają jedną zmianę. Następnie są kopiowane do linii 4 i 5, ale następna zmienna get ulega zmianie.

Jak widać, mam problem z umieszczeniem tego wzoru w kodzie. Myślę, że niektóre funkcje rekursji będą wymagane, ale nie jestem pewien, jak ją usunąć lub powtórzyć przez nią. Myślę, że będę musiał użyć funkcji z ... jako argumentami i funkcją rozpakowywania, ale nie jestem pewna, jak to by działało.

Powód, dla którego jest to wymagane, a nie tylko ręczne kopiowanie i wklejanie (co w rzeczywistości byłoby łatwiejsze), polega na tym, że treść tabeli zostanie wygenerowana.

Czy możecie mi pomóc?

Odpowiedz

7

Użyj rekursji.

Wyobraźmy sobie funkcję map_all (fcn, tab, idx, ...) który mapuje fcn iloczynowi elementów wszystkich tabel tab[1] do tab[idx] poprzedzał ...

Sprawa zasadą jest, gdy idx jest mniejsza niż 1.W tym przypadku wystarczy zastosować fcn(...)

W przeciwnym razie, map_all(fcn, tab, idx-1, <el>, ...) dla wszystkich <el> w tab[idx]

function map_all (fcn, tab, idx, ...) 
    if idx < 1 then 
     fcn(...) 
    else 
     local t = tab[idx] 
     for i = 1, #t do map_all(fcn, tab, idx-1, t[i], ...) end 
    end 
end 

So,

> Table = { 
>>  [1] = {'Player1', 'Player2'}, 
>>  [2] = {'PlayerA', 'PlayerB', 'PlayerC'}, 
>>  [3] = {'PlayerOne', 'PlayerTwo'} 
>> } 
> map_all(print, Table, #Table) 
Player1 PlayerA PlayerOne 
Player2 PlayerA PlayerOne 
Player1 PlayerB PlayerOne 
Player2 PlayerB PlayerOne 
Player1 PlayerC PlayerOne 
Player2 PlayerC PlayerOne 
Player1 PlayerA PlayerTwo 
Player2 PlayerA PlayerTwo 
Player1 PlayerB PlayerTwo 
Player2 PlayerB PlayerTwo 
Player1 PlayerC PlayerTwo 
Player2 PlayerC PlayerTwo 

i

> Table = { 
>>  [1] = {'Player1', 'Player2'}, 
>>  [2] = {'PlayerA'}, 
>>  [3] = {'PlayerOne'} 
>> } 
> map_all(print, Table, #Table) 
Player1 PlayerA PlayerOne 
Player2 PlayerA PlayerOne 

i

> Table = { 
>>  [1] = {'Player1', 'Player2'}, 
>>  [2] = {'PlayerA'}, 
>>  [3] = {'PlayerOne'}, 
>>  [4] = {'PlayerUno', 'PlayerDos'}, 
>>  [5] = {'PlayerApple', 'PlayerBoy', 'PlayerCat', 'PlayerDog'}, 
>> } 
> map_all(print, Table, #Table) 
Player1 PlayerA PlayerOne PlayerUno PlayerApple 
Player2 PlayerA PlayerOne PlayerUno PlayerApple 
Player1 PlayerA PlayerOne PlayerDos PlayerApple 
Player2 PlayerA PlayerOne PlayerDos PlayerApple 
Player1 PlayerA PlayerOne PlayerUno PlayerBoy 
Player2 PlayerA PlayerOne PlayerUno PlayerBoy 
Player1 PlayerA PlayerOne PlayerDos PlayerBoy 
Player2 PlayerA PlayerOne PlayerDos PlayerBoy 
Player1 PlayerA PlayerOne PlayerUno PlayerCat 
Player2 PlayerA PlayerOne PlayerUno PlayerCat 
Player1 PlayerA PlayerOne PlayerDos PlayerCat 
Player2 PlayerA PlayerOne PlayerDos PlayerCat 
Player1 PlayerA PlayerOne PlayerUno PlayerDog 
Player2 PlayerA PlayerOne PlayerUno PlayerDog 
Player1 PlayerA PlayerOne PlayerDos PlayerDog 
Player2 PlayerA PlayerOne PlayerDos PlayerDog 
> 
+0

Tak, jak w przebiegu przez to funkcja będzie wyjąć górną wartość w tabeli głównej, to w tym przypadku: > Tabela = { >> [1] = { „Gracz1”, „player2 '}, >> [2] = {' PlayerA '}, >> [3] = {' PlayerOne '} >>} Wyciągnie [3], a następnie wyciągnie [2], i który mógłby się wycofać [1]. Więc ... część będzie powoli przesuwać się, aby je pomieścić, dopóki wszystkie argumenty nie istnieją? Co więcej, byłby on uruchamiany, gdy nie ma nic do wyciągnięcia, prawda? Po prostu próbuję dowiedzieć się, jak to działa ... – Stormswept

+1

Tak, iteruje przez główny stół, zaczynając od ostatniej subtable, pchając wartości na przedzie '...', i wywołując funkcję, kiedy w końcu zabraknie jej podtabeli. Kiedy funkcja wraca, powraca o jeden poziom do następnej iteracji; gdy iteracja się zakończy, również powraca o jeden poziom do następnej interakcji. –

Powiązane problemy