martedì 1 novembre 2011

[Excel VBA] Insieme delle Parti

Descrizione :
Un metodo per l'estrazione dell'Insieme delle Parti da un Insieme dato di N elementi.

+ Articolo :

Dato un insieme S, per Insieme delle Parti di S si intende l'insieme di tutti i sottoinsiemi di S.
Questa collezione di insiemi viene anche detta insieme potenza di S o booleano di S.
Per esempio, se S è l'insieme {a,b,c}, allora la lista completa dei suoi sottoinsiemi risulta :

(l'insieme vuoto)
{a}
{b}
{c}
{a,b}
{a,c}
{b,c}
{a,b,c} che coincide con l'insieme stesso S

Detto N il numero di elementi di S, l'Insieme delle Parti di S contiene 2^N Elementi ( 2-elevato-N ).
Nel caso del presente esempio, gli elementi restituiti vengono disposti per colonne, e non viene considerato l'insieme vuoto, perciò vengono restituiti (N^2 - 1) Elementi.

Ammettiamo di avere un pulsante su Foglio1 e che Foglio2 sia il Foglio destinato a contenere i risultati dell'elaborazione.

--> Anzitutto la Function :

Public Function CombinazioniSemplici(ByVal arrayElementi As Variant, _
                                     ByVal dimensioneGruppo As Integer, _
                                     ByVal delimitatore As String) As Collection
 
    Dim LC As New Collection
    If UBound(arrayElementi) = 0 Then
        Set CombinazioniSemplici = LC
    End If
    If dimensioneGruppo = 0 Or dimensioneGruppo > UBound(arrayElementi) Then
        Set CombinazioniSemplici = LC
    End If
    Dim aP() As Integer
    ReDim aP(dimensioneGruppo - 1)
    Dim i As Integer
    For i = 0 To UBound(aP)
        aP(i) = i
    Next i
    Dim j As Integer
    Dim C As String
    Dim cnt As Integer
    Do
        C = ""
        For i = 0 To UBound(aP)
            If i < UBound(aP) Then
                C = C & arrayElementi(aP(i)) & delimitatore
            Else
                C = C & arrayElementi(aP(i))
            End If
        Next i
        LC.Add (C)
 
        cnt = 0
        For i = UBound(aP) To 0 Step -1
            If aP(i) = UBound(arrayElementi) - cnt Then
                cnt = cnt + 1
                If cnt = UBound(aP) + 1 Then Exit Do
            Else
                aP(i) = aP(i) + 1
                For j = 0 To UBound(aP)
                    If i < j Then aP(j) = aP(i) + (j - i)
                Next
                Exit For
            End If
        Next i
    Loop
 
    Set CombinazioniSemplici = LC
 
End Function

Questa Function è una versione modificata di altra mia Function generica per il Calcolo delle Combinazioni Semplici, disponibile qui :
http://marcoggblog.blogspot.com/2011/10/vb6-combinazioni-semplici-e-con.html

--> ESEMPIO di utilizzo con N numerici da 1 a 5 :
    Dim N As Integer
    N = 5 '<-- Numero elementi desiderato
 
    Dim delim As String
    delim = "/" '<-- delimitatore desiderato
 
    Dim WS As Worksheet 'Foglio risultati
    Set WS = ThisWorkbook.Worksheets("Foglio2")
    WS.Cells.ClearContents
 
    Dim A() As Variant
    ReDim A(N - 1)
    Dim i As Integer
    For i = 0 To UBound(A)
        A(i) = i + 1
    Next i
    Dim temp As Variant
    Dim j As Integer
    Dim K As Integer
    Dim CS As Collection
    Dim C As Long 'Indice di colonna
 
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False
 
    For K = N To 1 Step -1
 
        Set CS = CombinazioniSemplici(A, K, delim)
 
        For i = 1 To CS.Count
 
            C = C + 1
            temp = Split(CS(i), delim)
 
            For j = 0 To UBound(temp)
                WS.Cells(j + 1, C).FormulaR1C1 = temp(j)
            Next j
 
        Next i
 
    Next K
 
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
 
    MsgBox "OK"

NOTE :

--> Gli elementi dell'insieme delle parti vengono correttamente disposti per colonne.

--> Un Foglio Excel 2007 / 2010 ha un max di 16384 Colonne ( 2^14 ), perciò, dato che il numero di elementi nell'insieme delle parti di un insieme di partenza di N elementi è di 2^N ( 2-elevato-N ), il limite sarà in questo caso di 2^14 = 16384.
Perciò, con questo particolare procedimento, N dovrà essere al massimo di 14 elementi.
Per N>14 il mio codice funziona allo stesso modo, ma bisognerà pensare ad un'altra disposizione dei risultati.

--> La mia Function funziona non solo con valori Integer nell'insieme, ma con qualsiasi valore, che siano numeri con o senza virgola, o stringhe.

--> ESEMPIO con 5 Stringhe :
    Dim N As Integer
    N = 5 '<-- Numero elementi desiderato
 
    Dim delim As String
    delim = "/" '<-- delimitatore desiderato
 
    Dim WS As Worksheet 'Foglio risultati
    Set WS = ThisWorkbook.Worksheets("Foglio2")
    WS.Cells.ClearContents
 
    Dim A() As Variant
    ReDim A(N - 1)
    Dim i As Integer
    For i = 0 To UBound(A)
        A(i) = Chr(i + 65) & (i + 1)
    Next i
    Dim temp As Variant
    Dim j As Integer
    Dim K As Integer
    Dim CS As Collection
    Dim C As Long 'Indice di colonna
 
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False
 
    For K = N To 1 Step -1
 
        Set CS = CombinazioniSemplici(A, K, delim)
 
        For i = 1 To CS.Count
 
            C = C + 1
            temp = Split(CS(i), delim)
 
            For j = 0 To UBound(temp)
                WS.Cells(j + 1, C).FormulaR1C1 = temp(j)
            Next j
 
        Next i
 
    Next K
 
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
 
    MsgBox "OK"

+ Fine Articolo.

Un Click su "Mi Piace" è il modo migliore per ringraziare l'autore di questo articolo.



0 commenti:

Posta un commento

 
Design by Free WordPress Themes Modificato da MarcoGG