PDA

View Full Version : [VBA] permutazioni con ripetizioni ma con limite alle ripetizioni


xp2400
27-10-2014, 10:44
Ho un array di N Elementi (es A, B, C, D) e voglio estrarre tutte le permutazioni possibili (CLASSE) es = 3.

AAA
AAB
AAC
AAD
ABB
ABC
ABD
ACD..
..
DDD
notare che ABA = AAB e scompare dall'elenco
il codice qui sotto fa egregiamente il suo lavoro (trovato in rete.





Public Function CombinazioniConRipetizione(ByVal arrayElementi As Variant, ByVal Classe As Byte) As Collection

Dim LC As New Collection
If UBound(arrayElementi) = 0 Then
Set CombinazioniConRipetizione = LC
End If
If Classe = 0 Then
Set CombinazioniConRipetizione = LC

End If
Dim aP() As Integer
ReDim aP(Classe - 1)
Dim i As Integer
Dim j As Integer
Dim C As String
Dim cnt As Integer


Do

C = ""
For i = 0 To UBound(aP)
C = C & arrayElementi(aP(i))
Next i


Application.StatusBar = "Sto creando la Combinazione " & LC.Count & "/" & MaxCombinazioni & "-->" & C
DoEvents

cnt = 0
For i = UBound(aP) To 0 Step -1
If aP(i) = UBound(arrayElementi) 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)
Next
Exit For
End If
Next i
Loop

Set CombinazioniConRipetizione = LC
End Function

a questo punto vi chiedo: E' possibile limitare il numero di ripetizioni di ogni singolo elemento dell'array a N volte?
ad esempio se pongo N = 2, le permutazioni (AAA e BBB e CCC e DDD) non vengono calcolate....

tenete presente che sto lavorando con classi > 10.. e il numero di combinazioni sale col fattoriale...

Daniels118
27-10-2014, 14:20
Per favore indenta il codice quando posti sul forum.

Puoi utilizzare questa funzione (non testata) per contare il numero di ripetizioni e scartare quindi le combinazioni che non ti interessano:
Public Function maxNumRipetizioni(arrayElementi As Variant, aP() As Integer) As Integer
Dim i As Integer
Dim p As Integer
Dim c() As Integer
Dim m As Integer
ReDim c(UBound(arrayElementi))
For i = 0 To UBound(aP)
p = aP(i)
c(p) = c(p) + 1
If c(p) > m Then m = c(p)
Next i
maxNumRipetizioni = m
End Function
Se arrayElementi è grande conviene allocare c all'esterno e prevedere un ulteriore ciclo di pulizia nella funzione.

xp2400
28-10-2014, 08:22
Per favore indenta il codice quando posti sul forum.

Puoi utilizzare questa funzione (non testata) per contare il numero di ripetizioni e scartare quindi le combinazioni che non ti interessano:
Public Function maxNumRipetizioni(arrayElementi As Variant, aP() As Integer) As Integer
Dim i As Integer
Dim p As Integer
Dim c() As Integer
Dim m As Integer
ReDim c(UBound(arrayElementi))
For i = 0 To UBound(aP)
p = aP(i)
c(p) = c(p) + 1
If c(p) > m Then m = c(p)
Next i
maxNumRipetizioni = m
End Function
Se arrayElementi è grande conviene allocare c all'esterno e prevedere un ulteriore ciclo di pulizia nella funzione.

Grazie.
Però mi serve qualcosa che scarti la combinazione che supera max ripetizioni durante la generazione,non dopo. Questo perchè la collection in VBA non supera circa 330k item.. e io lo supero abbondantemente...

Daniels118
28-10-2014, 08:30
Si avevo capito, basta che metti il codice che genera la combinazione all'interno di un if:
If maxNumRipetizioni(arrayElementi, aP) < valore Then
C = ""
For i = 0 To UBound(aP)
C = C & arrayElementi(aP(i))
Next i
Application.StatusBar = "Sto creando la Combinazione " & LC.Count & "/" & MaxCombinazioni & "-->" & C
End If

PS.
Comunque nella tua routine non usi mai la collection e ci sono alcune istruzioni inutili, forse ci stai ancora lavorando?