Anagrammi e combinazioni con ripetizione

Documenti analoghi
Utilizzare le RegExp e IE per esplorare il Web

Convertire numeri da lettere a cifre (UDF)

UsedRange - eccezioni e alternative

Elenchi univoci funzioni di ordinamento e verifica chiave

Convertire un numero da cifre a lettere (UDF)

Convertire un numero da cifre a lettere (UDF)

Codici a barre - Seconda parte (EAN 8 ed EAN 13)

Calcolo del Bollo auto (UDF con IE)

Rimuovere la password dalle protezioni di foglio e cartella in Excel

Excel & VBA. Excel e Visual Basic for Application

28/02/2014 Copyright V. Moriggia

Elementi di Informatica e Programmazione

Programmazione con il linguaggio LibreOffice Basic

Rimuovere la password dalle protezioni di foglio e cartella in Excel

Caratteristiche generali del linguaggio Visual Basic

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Ruggero Cerino. Strumenti informatici per indici dei nomi. Come creare un indice analitico con MS-WORD

5 Array Cicli iterativi Contenuto di cella 28/02/2014 Copyright V. Moriggia 1

4. I moduli in Access 2000/2003

Note per la programmazione in linguaggio Visual Basic di Excel

VBA Principali Comandi

Algoritmi e dintorni: La radice quadrata Prof. Ettore Limoli. Formule iterative

Algoritmo per l ordinamento di un array

Excel & VBA. Excel e Visual Basic for Application

VERIFONE PROTOCOLLO SCAMBIO IMPORTO

STRUTTURE DI CONTROLLO DEL C++

Verifica su Record e File

osservazione: 1 MCD(m,n) min(m,n) = si provano i numeri compresi tra 1 e min(m,n) conviene iniziare da min(m,n) e scendere verso 1

VISUAL BASIC FOR APPLICATION

PASCAL: I VETTORI TRATTO DA CAMAGNI-NIKOLASSY, CORSO DI INFORMATICA, VOL. 1, HOEPLI. Informatica

I costrutti forniti dal linguaggio si dividono in corrispondenti classi di istruzioni

IMPOSTAZIONI DI EXCEL. Per rendere disponibile l ambiente di sviluppo di Visual Basic for Application in Excel:

Informatica (A-K) 5. Algoritmi e pseudocodifica

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

MANUALE OPERATIVO PROTOCOLLO DI COMUNICAZIONE TERMOMETRI SITEL CONTROL SERIE A BASSA TEMPERATURA

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

Prof. Giuseppe Chiumeo. Avete già studiato che qualsiasi algoritmo appropriato può essere scritto utilizzando soltanto tre strutture di base:

Programma del corso. Elementi di Programmazione. Introduzione agli algoritmi. Rappresentazione delle Informazioni. Architettura del calcolatore

Fondamenti di Informatica

C: panoramica. Violetta Lonati

Esercizi vari. Alberto Montresor. 19 Agosto, 2014

Transcript:

Anagrammi e combinazioni con ripetizione Inviato da Roberto giovedì 23 aprile 2009 Il Blog di Excelvba Spesso mi è capitato di dover affrontare quesiti sullo sviluppo di combinazioni o permutazioni. Ho raccolto alcune funzioni scritte da me che sfruttano le espressioni regolari e l'oggetto dictionary per sviluppare anagrammi e combinazioni con ripetizione. Le propongo non perchè migliori di altre che si possono trovare nel web ma in quanto diciamo particolari. Hanno il merito di mostrare meccanismi e tecniche meno noti legati a quegli oggetti e per questo spero le troverete interessanti. Nelle funzioni che anagrammano una parola, viene utilizzato il metodo replace delle RegExp con sequenze meno documentate che sono sicuro troverete interessanti. Nelle funzioni che sviluppano le combinazioni viene utilizzato un ciclo for each su un dizionario che si alimenta all'interno del ciclo stesso, una sorta di ricorsione, simile la seconda funzione che però utilizza le espressioni regolari. Il codice è commentato per spiegarne il funzionamento. In fondo come al solito alcune routine per testare le funzioni. Due parole sulla funzione Nuovo_Range (utilizzata nelle routine Test) che personalmente sfrutto moltissimo e che serve per settare un range destinato alla scrittura dei risultati di una procedura. Il nuovo range ovviamente è la cella A1 di un nuovo foglio dal nome base che passiamo come secondo argomento. Buon lavoro Saluti r Option Explicit Function Anagramma_RE(Parola As String) 'Funzione che anagramma una Parola 'Utilizza un oggetto Dictionary e le 'espressioni regolari, in particolare 'il metodo replace delle RegExp Dim v, i, l As Long

Dim s As String Dim Dic As Object Dim RE As Object 'verifico che la stringa non sia vuota If Len(Parola) = 0 Then Exit Function 'setto dictionary e RegExp Set Dic = CreateObject("scripting.dictionary") Set RE = CreateObject("vbscript.regexp") 'voglio tutti i risultati RE.Global = True 'il pattern \w indica un singolo carattere 'letterale, numerico o trattino basso 'equivalente a [A-z0-9_] non comprende le 'lettere accentate RE.Pattern = "\w" 'aggiungo Parola al dizionario Dic.Add Parola, 0 'la seconda aggiunta di una stringa vuota 'serve a consentire la reiterazione del primo ciclo 'for each che in alternativa terminerebbe subito Dic.Add "", 0 For Each i In Dic 'applico la sostituzione s = RE.Replace(CStr(i), "$`$'$& ")

'Il pattern "$`$'$1 " sfrutta tre particolari 'sequenze vediamole: '"$`" sostituisce il risultato con la parte di 'stringa sorgente fino al risultato 'il carattere accento è digitabile con la 'combinazione Alt+096 '"$'" sostituisce il risultato con la parte di 'stringa sorgente che segue il risultato '"$& " sostituisce con il risultato 'passando per es "12345" al primo ciclo 'quello che avviene nel dettaglio è questo: 'la ricerca trova "1" -> $`="" $'="2345" $& ="1 " 'la ricerca trova "2" -> $`="1" $'="345" $& ="2 " 'la ricerca trova "3" -> $`="12" $'="45" $& ="3 " 'la ricerca trova "4" -> $`="123" $'="5" $& ="4 " 'la ricerca trova "5" -> $`="1234" $'="" $& ="5 " 'il risultato è "23451 13452 12453 12354 12345 " 'divido la stringa per caricare gli 'anagrammi nel dictionary v = Split(s, " ") For l = 0 To UBound(v) s = v(l) 'carico ricorsivamente il dictionary If Dic.Exists(s) = False Then Dic.Add s, 0 End If

'tolgo la stringa vuota Dic.Remove "" 'recupero il vettore con le chiavi Anagramma_RE = Dic.Keys End Function Function Anagramma_RE2(Parola As String) 'utilizza la funzione generica replace_re 'per il resto identica alla precedente Dim v, i, l As Long Dim s As String Dim Dic As Object Set Dic = CreateObject("scripting.dictionary") If Len(Parola) = 0 Then Exit Function Dic.Add Parola, 0 Dic.Add "", 0 For Each i In Dic v = Split(replace_RE(CStr(i), _ "\w", "$`$'$& ", True), " ") For l = 0 To UBound(v) s = v(l) If Dic.Exists(s) = False Then Dic.Add s, 0 End If

Dic.Remove "" Anagramma_RE2 = Dic.Keys End Function Function replace_re( _ Parola As String, _ spattern As String, _ sreppattern As String, _ Optional bglobal As Boolean, _ Optional bignorecase As Boolean) As String 'funzione generica di sostituzione Dim RE As Object Set RE = CreateObject("vbscript.regexp") RE.Global = bglobal RE.IgnoreCase = bignorecase RE.Pattern = spattern replace_re = RE.Replace(Parola, sreppattern) End Function Sub Combina_Dic( _ ByVal sc As String, _ ByVal ls As Long, _ StartRng As Excel.Range) Dim dic1 As Object Dim L1 As Long, L2 As Long, L3 As Long Dim S1 As String, S2 As String Dim V1 As Variant

'Combinazioni con ripetizione 'sc è l'insieme dei caratteri 'ls è la lunghezza delle stringhe 'risultati 'StartRng è la cella da cui partire 'per scrivere le combinazioni di 'ogni carattere di sc (anche ripetuto) 'per una lunghezza di ls caratteri 'volendo sarebbe sufficiente commentare 'la if nell'ultimo ciclo for 'per avere come risultato tutte le 'combinazioni di lunghezza da 1 fino a ls Set dic1 = CreateObject("Scripting.dictionary") L1 = Len(sC) 'carico i caratteri di sc sul 'dictionary e su un vettore ReDim sarr(1 To L1) As String For L2 = 1 To L1 sarr(l2) = Mid(sC, L2, 1) dic1.add sarr(l2), "" 'la stringa di chiusura S2 = String(lS, sarr(l1)) 'carico ricorsivamente il dictionary

'fino alla stringa di chiusura For Each V1 In dic1 For L2 = 1 To L1 S1 = V1 & sarr(l2) dic1.add S1, "" If S1 = S2 Then Exit For 'recupero solo le stringhe di lunghezza ls L2 = 0 For Each V1 In dic1 'commentare la if per avere come 'risultato tutte le combinazioni di 'lunghezza da 1 fino a ls If Len(V1) = ls Then StartRng.Offset(L2) = V1 L2 = L2 + 1 End If End Function Sub Combina_RE( _ ByVal sc As String, _ ByVal ls As Long, _ StartRng As Excel.Range) Dim RE As Object Dim L1 As Long, L2 As Long Dim S1 As String, S2 As String, S3 As String Dim V1 As Variant, B1 As Boolean

'Combinazioni con ripetizione 'sc è l'insieme dei caratteri 'ls è la lunghezza delle stringhe 'risultati 'StartRng è la cella da cui partire 'per scrivere le combinazioni di 'ogni carattere di sc (anche ripetuto) 'per una lunghezza di ls caratteri 'volendo ottenere tutte le combinazioni 'con lunghezza da 1 a ls basta escludere 'la if interruttore all'interno del loop Set RE = CreateObject("VBScript.RegExp") L1 = Len(sC) RE.Global = True 'creo la stringa di partenza 'con i singoli caratteri delimitati 'da uno spazio RE.Pattern = "\w" S1 = RE.Replace(sC, " $&") 'creo la stringa di controllo di 'fine loop composta da ls caratteri 'tutti uguali all'ultimo carattere 'di sc S2 = String(lS, Right(sC, 1)) 'ciclo aggiungendo ad ogni parola '(serie di caratteri delimitati da

'spazio) ogni carattere di sc 'al primo for azzero la stringa 'liberando memoria (utilizzo una 'variabile boolean come interruttore) RE.Pattern = "\w+" Do Until S3 = S2 B1 = True For Each V1 In RE.Execute(S1) 'l'interruttore If B1 Then S1 = "" B1 = False End If 'ciclo di polamento For L2 = 1 To L1 S3 = V1 & Mid(sC, L2, 1) S1 = S1 & " " & S3 Loop 'ultimo ciclo per caricare le '*parole* nelle celle L2 = 0 For Each V1 In RE.Execute(S1) StartRng.Offset(L2) = V1 L2 = L2 + 1 End Sub Function Nuovo_Range( _ Wb As Excel.Workbook, _ Optional Nome_base As _

String = "Foglio") As Excel.Range 'restituisce la cella A1 di un nuovo foglio 'il nuovo foglio viene rinominato in base 'all'argomento Nome_base Dim b Set Nuovo_Range = Wb.Worksheets.Add.Range("A1") Application.ScreenUpdating = False On Error Resume Do Err.Clear Nuovo_Range.Parent.Name = Nome_base & b b = b + 1 Loop While Err Application.ScreenUpdating = True End Function Sub test_combina_dic() Dim rng As Excel.Range Set rng = Nuovo_Range(ThisWorkbook, "Combina_Dic_Res ") Combina_Dic "abcde", 6, rng End Sub Sub test_combina_re() Dim rng As Excel.Range

Set rng = Nuovo_Range(ThisWorkbook, "Combina_RE_Res ") Combina_RE "abcd", 3, rng End Sub Sub test_anagramma_re() Dim v, t Dim l As Long, c As Long Dim rng As Excel.Range Const Parola As String = "roberto" 'nel caso si voglia solo gli anagrammi di 'senso compiuto... decommentare le righe 'Attenzione! 'i tempi si allungano notevolmente 'Dim appw As Object 'Set appw = CreateObject("Word.application") Set rng = Nuovo_Range(ThisWorkbook, Parola & " ") v = Anagramma_RE(Parola) For Each t In v 'If appw.checkspelling(cstr(t)) Then rng.offset(l, c) = t l = l + 1 If l > Cells.Rows.Count Then c = c + 1 End If 'End If End Sub