Questo articolo viene da una discussione sul Forum di Excel VBA. La discussione non ha avuto molto seguito in verità, però l’idea era carina (era basata su vecchio gioco) e mi ha dato uno spunto interessante per approfondire l’argomento.
Lo spunto di partenza prevede una tabella di numeri interi reali (non importa se positivi o negativi: questo aspetto rende il gioco più affascinante) e occorre raggiungere un valore obiettivo applicando a due o più elementi della tabella una o più delle quattro operazioni fondamentali (addizione, sottrazione, moltiplicazione, divisione). Nota che si può anche scegliere di escludere uno o più operatori.

La sfida non era facile ma con qualche trucco e cercando un pochino in Rete ho tirato fuori questa proposta, basata sulle combinazioni (dei numeri iniziali) e sulle permutazioni (dei simboli delle quattro operazioni).

In sostanza genero la tabella delle combinazioni dei numeri iniziali e ogni combinazione (non ripetuta) è memorizzata come stringa nella forma “m n”. Successivamente al carattere spazio viene sostituito in sequenza uno degli operatori permessi. Si ottiene una nuova sequenza di stringhe del tipo “m+n”, “m-n”, e così via.
Infine viene valutato il risultato di ogni singola stringa, e se coincide con il valore obiettivo, viene conservata la sequenza che lo origina per presentarlo, finalmente, all’utente.

Ho preparato un semplice foglio Excel che illustrerà bene tutto il meccanismo. Lo scenario prevede:
tabella numeri iniziale (con intestazione): colonna A;
numero obiettivo: cella D2;
– cella (D4) con hyperlink che scatena il codice sottostante.

Codice del Foglio1:

'codice in Foglio1
Option Explicit

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim v As Variant, arr() As Variant
Dim i As Long, j As Long

    If Target.Range(1) = Range("D4") Then
        i = [COUNTA(A:A)] - 1
        ReDim arr(i) As Variant
        For j = 0 To i - 1
            arr(j) = Cells(j + 2, "A").Value2
        Next
         
        i = 2
        Range("G:G").ClearContents
        Range("G1") = "Risultati:"
        For Each v In Split(find_goal(arr, Range("D2")), vbNewLine)
            Cells(i, "G") = v
            Cells(i, "G").NumberFormat = "Text"
            i = i + 1
        Next
        
        MsgBox "Procedura completata.", , [COUNTA(G:G)] - 1 & " operazioni"
    End If
End Sub

Codice del Modulo1:

Option Explicit

' fondamentale lasciare gli spazi nella stringa, anche quello finale!
Private Const ALLOWED_OPERATORS = "+ - * / "

Private sTmp As String

Public Function find_goal(nums(), goal As Long) As String
Dim i As Long, j As Long
Dim s As String
Dim ac As Range
Dim k As Variant
Dim nops As Long
Dim m As String
Dim z As String
Dim t As String
Dim q As String
Dim n As Long
    
    ' calcola le combinazioni dei numeri della tabella iniziale
    ' raggruppandoli a coppie, terne, quaterne e così via
    For j = 2 To UBound(nums)
        s = s & get_combinations(nums, j)
    Next
    s = Left(s, Len(s) - 2)
    
    ' per ogni combinazione applica in sequenza (permutandoli)
    ' gli operatori della const ALLOWED_OPERATORS
    ' per esempio la combinazione "5 2"  viene trasformata
    ' in sequenza in "5+2", "5-2", "5*2", "5/2"
    ' infine valuta l'espressione risultante
    ' se il risultato è uguale all'obiettivo lo conserva
    ' e lo restituisce al codice chiamante (in Foglio1)
    For Each k In Split(s, vbNewLine)
        nops = UBound(Split(k))
        z = PermutationsN_P_R(nops)
        For j = 1 To Len(z) Step nops
            m = Mid(z, j, nops)
            t = k
            For n = 1 To nops
                t = Replace(t, " ", Mid(m, n, 1), , 1)
            Next
            
            If Evaluate(t) = goal Then
                q = q & t & vbNewLine
            End If
        Next
    Next
    
    find_goal = q
End Function


Public Function get_combinations(ByRef arr(), ByVal r As Long) As String
Dim n As Long, i As Long, j As Long
Dim idx() As Long
Dim s As String
    
   'genera le combinazioni dei numeri nella tabella iniziale
   'i numeri vengono combinati a gruppi di r elementi e
   'sono separati da uno spazio che poi verrà riempito dagli operatori
   'definiti nella const ALLOWED_OPERATORS

    n = UBound(arr) - LBound(arr)

    ReDim idx(r - 1) As Long
    For i = 0 To r - 1
        idx(i) = i
    Next i

    Do
        s = ""
        For j = 0 To r - 1
            s = s & arr(idx(j)) & " "
        Next j
        get_combinations = get_combinations & Trim(s) & vbNewLine

        ' localizza il penultimo indice
        i = r - 1
        While (idx(i) = n - r + i)
            i = i - 1
            ' termine delle iterazioni
            If i < 0 Then
                Exit Function
            End If
        Wend

        ' predispone il successivo ciclo
        idx(i) = idx(i) + 1
        For j = i + 1 To r - 1
            idx(j) = idx(i) + j - i
        Next j
    Loop
End Function


' PGC Dez 2009
' Permutations of N elements taken 1 to p at a time
Function PermutationsN_P_R(n As Long) As String
Dim vElements As Variant
Dim vResult() As Variant
Dim s As String, i As Long

    ' genera le permutazioni degli operatori definiti nella costante iniziale
    ' in modo che vengano assegnati in sequenza agli spazi vuoti della stringa
    ' contenente la combinazione corrente
    ' la permutazione è ripetuta per cui si avrà +++, ---, ** e ////

    vElements = Split(ALLOWED_OPERATORS)

    sTmp = ""
    ReDim vResult(n)
    s = get_permutationsNPR(vElements, n - 1, vResult, 0, vbNullString)
    PermutationsN_P_R = s
End Function
 
Private Function get_permutationsNPR(vElements As Variant, p As Long, vResult As Variant, iIndex As Integer, s As String) As String
Dim i As Long

    ' funzione ricorsiva di supporto a PermutationsN_P_R
    ' crea le permutazioni di n elementi dell'array di operatori
    ' a gruppi di r
    
    sTmp = s
    For i = 0 To UBound(vElements)
        vResult(iIndex) = vElements(i)
        If iIndex = p Then
            sTmp = sTmp & Join(vResult, vbNullString)
        Else
            Call get_permutationsNPR(vElements, p, vResult, iIndex + 1, sTmp)
        End If
    Next i
    get_permutationsNPR = sTmp
End Function

Con un userform potrebbe anche diventare un gioco carino, perchè no? magari anche una sfida a tempo con gli amici, a chi indovina più combinazioni 🙂

Scarica il file di esempio da qui!

Combinazioni e permutazioni

Combinazioni e permutazioni

Login Registrati
Stai vedendo 2 articoli - dal 1 a 2 (di 2 totali)
  • Autore
    Articoli
  • #7884 Risposta

    vecchio frac
    Moderatore
      16 pts

      Questo articolo viene da una discussione sul Forum di Excel VBA. La discussione non ha avuto molto seguito in verità, però l'idea era carina (era basata su vecchio gioco) e mi ha dato uno spunto interessante per approfondire l'argomento.
      Lo spunto di partenza prevede una tabella di numeri interi reali (non importa se positivi o negativi: questo aspetto rende il gioco più affascinante) e occorre raggiungere un valore obiettivo applicando a due o più elementi della tabella una o più delle quattro operazioni fondamentali (addizione, sottrazione, moltiplicazione, divisione).......

      [Leggi tutto al seguente link: https://www.excelvba.it/forumexcel/combinazioni-e-permutazioni/]

      #7886 Risposta
      albatros54
      albatros54
      Moderatore
        10 pts

         

         

        Qual è il punto di avere gusti diversi, se non mostrare che i cervelli lavorano diversamente, che pensiamo diversamente? ( Alan Turing)
        Sempre il mare, uomo libero, amerai!
        ( Charles Baudelaire )
      Login Registrati
      Stai vedendo 2 articoli - dal 1 a 2 (di 2 totali)
      Rispondi a: Combinazioni e permutazioni
      Gli allegati sono permessi solo ad utenti REGISTRATI
      Le tue informazioni:



      vecchio frac - 591 risposte

      albatros54
      albatros54 - 507 risposte

      Marius44
      Marius44 - 270 risposte

      patel
      patel - 257 risposte

      Luca73
      Luca73 - 194 risposte

      ChatBox per richiedere velocemente assistenza a semplici problematiche

      Devi fare il login per scrivere nella chat

      0
      1