giovedì, 21 Novembre 2024

[python] Disegnare matrice concentrica in Python data una dimensione arbitraria (e valutare le prestazioni)

Vogliamo scrivere un algoritmo in Python che, dato un lato n-esimo arbitrario, disegni una matrice di valori concentrici. Il risultato che vogliamo ottenere è il seguente:

Questo problema ha molteplici soluzioni e Python ne permette un’estrema sintesi.

Cominciamo dalla soluzione più semplice, ma che richiede il maggior numero di cicli.

Anzitutto calcoliamo la dimensione del quadrato:

Adesso prepariamo una matrice di dimensione dim fatta di soli 0

Il procedimento che seguiremo ora sarà quello di stringere la matrice sempre di più, ridisegnando i vari quadrati all’interno della matrice di 0 appena creata.

In questo modo disegneremo ad ogni passaggio un quadrato di numeri n-k

Stampiamo infine a video la matrice:

Possiamo misurare il tempo di calcolo necessario (questo tempo dipende principalmente dal processore in uso, quindi varia da macchina a macchina) utilizzando la libreria time

Il codice diventerebbe il seguente:

Nel mio caso l’operazione per un lato di dimensione 1000 impiega circa 131.700 ms. Su questo torneremo successivamente.

Possiamo però riscrivere l’algoritmo in un altra forma più sintetica.

Questa volta l’algoritmo impiega 1.250 ms circa, sempre per lato di dimensione 1000.

Il risultato è il medesimo, ma il tempo di calcolo è decisamente inferiore.

Un’altra versione potrebbe essere la seguente:

Questa volta il tempo di calcolo, per dimensione 1000 di lato, è di circa 490 ms.

Confrontando i tre algoritmi su range di calcoli da 50 a 1000, otteniamo le seguenti performance (il primo algoritmo lo chiamiamo A, l’ultimo lo chiamiamo C):

Che possiamo mettere in un grafico (con scala logaritmica) come il seguente:

[word] Rimuovere “Limita modifica” da un file docx di Word

Problema: Il file word risulta protetto con l’opzione Limita modifica che impedisce anche di copiare il testo dal file.

Soluzione: Rinominare il file docx con estensione zip, decomprimere il file, individuare all’interno della cartella il file word/settings.xml, aprirlo con un editor di testo ed impostare su false il parametro w:enforcement, salvare il file, ricomprimere tutto il contenuto della cartella in un file zip e rinominarlo in docx

Vediamo la procedura nel dettaglio.

Anzitutto individuiamo il file Word che non permette le modifiche. Aprendo il file e andando nella scheda Revisione > Proteggi cliccando sull’opzione Limita modifica si aprirà una finestra simile alla seguente:

Il file potrebbe essere protetto a diversi livelli e non consentire nemmeno la copia del testo.

Per rimuovere la protezione procediamo nella maniera seguente.

A questo punto prendiamo il file e rinominiamolo con l’estensione zip.

Per farlo da Windows 10 dobbiamo attivare la visualizzazione delle estensioni dei file. Se non l’abbiamo già fatto, in Esplora Risorse andiamo su Visualizza > Mostra / Nascondi e spuntiamo Estensioni nomi file.

Una volta rinominato il file in formato zip possiamo decomprimerlo in una cartella, trovando dentro una struttura simile a questa:

Entriamo nella cartella word e individuiamo il file settings.xml

Apriamo il file con un editor di testo (consiglio Notepad++) e individuiamo il parametro w:enforcement

Il parametro sarà probabilmente impostato su true oppure 1.

Modifichiamolo su false.

A questo punto torniamo nella cartella precedente e comprimiamo tutti i file.

Otterremo un nuovo file zip, cambiamo di nuovo l’estensione in docx e il gioco è fatto.

[python] Albero binario in Python

Riporto qui un classico dell’informatica di base: la realizzazione di un albero binario per l’ordinamento.

Quello dell’albero binario è un algoritmo che consente di ordinare dei valori in base al criterio di inserimento e successivamente di lettura.

Per far capire meglio il procedimento vediamo anzitutto come funziona.

Immaginiamo di avere la sequenza di numeri 3, 4, 1, 7, 6, 5, 8, 11, 9. L’algoritmo prevede la creazione di una struttura ad albero, composta di nodi, dove ogni nodo contiene un valore e un ramo di sinistra e uno di destra, che puntano rispettivamente al valore minore e maggiore, rispetto al valore nel nodo. La creazione dell’albero procederà quindi come nel video soprastante.

La lettura avverrà invece a partire dal primo nodo, procedendo anzitutto sul nodo di sinistra, poi stampando il valore del nodo corrente e poi procedendo sul nodo di destra. Come illustrato nella seguente animazione:

 

Procedendo in questo modo otterremo tutti i valori ordinati.

Questo algoritmo può essere scritto in Python nel modo seguente:

 

[plesk] Aggiungere manualmente IP alla blacklist di fail2ban

In Plesk purtroppo non è possibile, tramite l’interfaccia grafica, aggiungere manualmente IP alla blacklist di fail2ban.

Lo si può fare esclusivamente, al momento attuale, tramite terminale, interagendo direttamente con fail2ban.

Per bloccare manualmente un IP con fail2ban si può utilizzare il seguente comando:

Dove al posto di nome-jail si inserirà una delle jail configurate su fail2ban e al posto di xx.xx.xx.xx l’indirizzo IP che si intende bloccare.

[python] Semplice simulazione dell’espansione di un contagio tipo COVID19 con PyGame e OpenGL

Ripropongo un esercizio in Python simile a quello svolto in JavaScript in Simulazione sull’espansione del contagio da Coronavirus (COVID-19)

Questa volta utilizzeremo PyGame e OpenGL per costruire la simulazione, similmente a quanto fatto nel precedente articolo. Il programma è stato svolto in Python 3.9.

Il risultato produrrà qualcosa di simile a questo:

[python] Calcolare la dimensione delle cartelle sul computer e trovare quelle più grandi

Ecco un veloce script in python per ricavare la dimensione delle cartelle sul computer (vale sia per Windows che Mac e Linux) e stampare l’elenco ordinato (dalla più grande alla più piccola) di tutte quelle trovate sopra una certa dimensione.

A me è stato molto utile per svuotare C: che si era riempito di cartelle temporanee, di cache e cose totalmente dimenticate.

Lo script è stato scritto per Python 3.9

L’ouput finale genera qualcosa di simile (nel mio caso vedo che le macchine virtuali di Android occupano da sole 24GB!)

Faccio notare che nella stampa finale ho ridotto l’elenco a cartelle maggiori di 200MB.

[python] Semplice esercizio per riconoscere immagini di frutti con TensorFlow (machine learning)

Vogliamo realizzare un semplice programma in Python che sia in grado di riconoscere, utilizzando TensorFlow e machine learning, delle immagini di frutti.

Questo esercizio riprende i medesimi concetti già visti in: [python] Semplice esercizio su TensorFlow e il riconoscimento delle immagini nel gioco del Tris (Machine Learning)

Dato il seguente set di immagini (qui unite in una singola), vogliamo addestrare il programma a riuscire a riconoscere correttamente i frutti rappresentati:

Per farlo addestreremo il programma con altre immagini di training, suddivise rispettivamente in mele (che forse assomigliano più a dei pomodori), pere e banane:

 

 

 

 

 

Il risultato che vogliamo ottenere analizzando la prima immagine sarà qualcosa del genere (abbiamo tagliato l’immagine in tutte le sottoparti):

I tre numeri rappresentano la percentuale di probabilità per cui l’immagine sia, rispettivamente, una mela, una pera o una banana. Questo significa che la prima immagine è al 100% di probabilità una pera, mentre la seconda una banana ecc.

Il progetto si sviluppa in Python 3.7. Prima di procedere assicuriamoci di aver installato tutte le librerie necessarie, in particolare:

A questo punto prepariamo le immagini per il training ed il test. Attraverso le immagini di training alleneremo il nostro algoritmo, mentre useremo quelle per il test per verificare l’efficacia. Sottolineo ancora una volta come questo sia un esempio semplificato al massimo, utilizzando immagini semplici per non dover produrre una grande mole di dati sia per il training che per il test.

Per preparare le immagini dobbiamo tagliare i quattro file precedentemente preparati. A tale scopo creiamo una classe per elaborare le immagini nel modo seguente (nei commenti c’è la descrizione delle singole operazioni):

Per elaborare i due gruppi di immagini ci sarà sufficiente chiamare:

A questo punto creiamo una classe per elaborare questa base dati, nel modo seguente:

Fatto tutto questo possiamo anzitutto costruire il nostro modello, che andremo a salvare, nella stessa cartella dell’eseguibile come modello_frutta.

Per creare il modello anzitutto preleviamo le immagini con:

Costruiamo poi il nostro modello:

I tre layer servono rispettivamente per:

  1. keras.layers.Flatten(input_shape=(100,100,3)) ci permette di ridurre ad una dimensione la matrice tridimensionale delle immagini (100 righe x 100 colonne x 3 byte di colore) contenente 30.000 byte. Per farlo dobbiamo ricordarci lo shape dei dati passati in input, che provengono da una lista, contenente a sua volte una lista tridimensionale.
  2. keras.layers.Dense(128, activation="relu") applica l’algoritmo relu ai dati ottenuti dal primo layer, su 128 nodi (il numero è arbitrario, scelto per via principalmente sperimentale)
  3. keras.layers.Dense(3, activation="softmax") applichiamo l’algoritmo softmax per ridurre tutte le informazioni a 3 nodi, rappresentati i 3 dati di output che vogliamo ottenere.

Aggiungo una nota per comprendere meglio il passaggio dei layer intermedi. Il primo layer è necessario per ridurre i dati in input ad una forma univoca, mentre l’ultimo layer serve a portare in output i dati che passiamo come “descrizione”, ovvero output conosciuto, durante il training. I layer intermedi invece possono essere molteplici, e servono per manipolare i diversi aspetti dell’informazione, tentando di ridurla ad una schematizzazione ricorrente. Per capire meglio questo processo immaginiamo di voler interpretare un’immagine (non succede la medesima cosa, ma l’esempio descrive bene il concetto generale).

Se avessimo un immagine come questa di seguito, avremmo a che fare con un’enorme quantità di dettagli diversi da analizzare. Essendo l’immagine grande 1200 x 761 pixel, potremmo dire di aver bisogno di 1200×761 = 913.200 nodi per interpretare ogni informazione singolarmente, quindi potremmo decidere di utilizzare un layer con 913.200 nodi (o neuroni). Questo vorrebbe dire che diamo importanza ad OGNI singolo nodo e quindi ad OGNI singolo dettaglio dell’informazione. Laddove volessimo confrontare immagini diverse sarebbe molto complesso cercare di trovare un’affinità tra i singoli nodi e quindi un percorso che riconduca al medesimo output desiderato.

Albania Sud | Vagabondo

Dello stesso posto potremmo avere ad esempio la seguente immagine:

Turismo dentale Albania | EliteDental

Le due immagini risulterebbero, per il computer, prese tali e quali, fondamentalmente diverse. Adesso proviamo a ridurre il dettaglio dei pixel, nel modo seguente:

Adesso possiamo identificare, nelle immagini divese, zone analoghe associabili per forma e colore tra di loro (nonostante le differenze ancora esistenti). In questo caso abbiamo ridotto le immagini in quadrati da 36×36 pixel ciascuno, quindi in totale abbiamo ridotto il tutto a circa 700 nodi. Ovviamente si è ridotta la complessità e di conseguenza il livello di dettaglio. Potremo apprezzare meno dettagli, ma confrontare meglio i macro-elementi presenti in entrambe le immagini.

Detto tutto questo compiliamo il nostro modello:

E infine compiliamolo e salviamolo:

Per usare il modello salvato lo possiamo caricare usando:

A questo punto carichiamo le immagini di TEST e mettiamo a prova il nostro modello:

Adesso facciamo prevedere al modello i risultati:

Infine stampiamoli a video per ottenere il risultato iniziale:

Riporto anche tutto il codice insieme:

Qui il progetto con le immagini scaricabile in formato zip.

[HOI4] Evitare che l’Albania venga annessa dall’Italia automaticamente se si trova in una fazione in Hearts of Iron 4 [BUG risolto]

In Hearts of Iron 4, attorno agli inizi di aprile del 1939 (storicamente il 7 aprile 1939) l’Italia completa il focus Albanian Occupation, al quale segue l’ultimatum italiano all’Albania e la conseguente occupazione. Al giocatore umano compare un messaggio come il seguente, e può scegliere se arrendersi oppure resistere. In caso di resistenza l’Italia dichiara immediatamente guerra.

Il problema sorge quando a giocare l’Albania è l’IA, che si arrende sempre, in tutte le circostanze, anche quando sarebbe avvantaggiata. Questo succede per esempio quando l’Albania si trova con un governo comunista ed è alleata del Comintern oppure fa parte dell’Alleanza Balcanica dei Lavoratori (guidata dalla Jugoslavia comunista), anche se un altro stato la sta proteggendo.

Il problema sta nel trigger degli eventi che seguono al focus tree dell’Italia. Per analizzare il bug individuiamo la cartella /events nella radice di HOI4 (nel mio caso avendo il gioco su Steam il percorso completo è \Steam\steamapps\common\Hearts of Iron IV\events\) e apriamo il file Italy.txt. Le righe di codice che ci interessano sono dalla 51 alla 159.

L’errore si trova esattamente alla riga 104. Le chance perché l’IA decida per la resistenza sono calcolate nel modo seguente:

  1. fattore base per la probabilità impostato a 20
  2. Il primo modificatore moltiplica tale fattore per 0 (qui c’è l’errore) nel caso in cui accada una delle seguenti condizioni:
    1. l’Albania è in fazione con l’Italia e il leader è l’Italia
    2. Qualunque altro paese sia principale (major) oppure sia la Jugoslavia, non sia l’Italia, e stia garantendo oppure sia in fazione con l’Albania, assieme ai focus storici attivi
    3. Non sia in fazione, nessun altra nazione, eccetto dell’Italia, la stia garantendo
  3. Il secondo modificatore aggiunge 100 se l’Albania è in una fazione, che non contenga anche l’Italia
  4. Il terzo aggiunge 100 se l’Albania è controllata o è oggetto di un’altra nazione che non sia l’Italia

Il secondo modificatore dovrebbe aggiungere 100 alla probabilità (rendendola quindi certezza) laddove l’Albania si trovi in una fazione che non contenga l’Italia. Purtroppo però, come è spiegato sulla guida ufficiale, il modifier si comporta come un blocco AND, che moltiplica il risultato totale per il factor e ci aggiunge il valore in add. Purtroppo però vale anche un’altra regola: se il valore intermedio scende a 0 tutte le operazioni successive si fermano e nemmeno gli add possono più modificarlo.

Questo significa che in “Qualunque altro paese sia principale (major) oppure sia la Jugoslavia, non sia l’Italia, e stia garantendo oppure sia in fazione con l’Albania, assieme ai focus storici attivi” per assurdo il fattore viene moltiplicato per 0 e quindi le possibilità che la IA resista sono del 0%. Per correggere il problema è sufficiente rimuovere le seguenti righe di codice:

Questo lo possiamo fare creando anche una mod.

Per creare la mod rechiamoci nella cartella C:\Users\<nome-utente>\Documents\Paradox Interactive\Hearts of Iron IV\mod e creiamo un file chiamato CorrezioneAlbania.mod e una cartella chiamata CorrezioneAlbania

Nel file inseriamo le seguenti definizioni (dobbiamo sostanzialmente dare un nome alla mod e scegliere a che cosa si applichi).

Attenzione! Sostituire sempre <nome-utente> con il proprio nome utente nella cartella profilo di Windows.

Nella cartella creare un file chiamato descriptor.mod con al suo interno il seguente codice:

Creare infine una cartella events nella quale metteremo un file di testo chiamato CorrezioneAlbania.txt. Al suo interno copiamo il codice precedente corretto:

Fatto tutto questo salviamo e avviamo il gioco. Se è andato tutto bene e l’Albania è in fazione con noi, al momento dell’ultimatum dovrebbe rifiutarlo e noi riceveremo la seguente notizia.

In tale caso prepariamoci alla guerra con l’Italia, dal momento che le ultime righe di codice dell’evento la attivano automaticamente:

Per curiosità, togliendoli questo non avviene. In caso contrario conviene armarsi.

[chrome] Aggirare il blocco del click col tasto destro tramite javascript

Alcuni siti bloccano (senza alcuna vera utilità) l’utilizzo del tasto destro, ossia l’apertura del menù contestuale che, tra le altre cose, permetterebbe di copiare il testo o le immagini.

Questo tipo di blocco può essere aggirato tramite Google Chrome, nel modo seguente:

  1. Premere il tasto F12 mentre si è sulla pagina, aprendo così la console sviluppatore
  2. Aprire la tab della console (qualora non fosse aperta) e digitare document.oncontextmenu=null;
  3. Premere invio

Questo dovrebbe disattivare il blocco del tasto destro e dell’apertura del menù contestuale.

[python] Semplice esercizio per creare il gioco del campo minato in Python (da console)

In questo semplice esercizio vogliamo riprodurre in Python, in modo un po’ rudimentale, quello che era il gioco del campo minato (poi campo fiorito) per Windows.

Quello che vogliamo ottenere assomiglierà a questo all’avvio:

Mentre alla vittoria otterremo qualcosa di simile:

Il gioco sarà costruito su una griglia 10×10, di 100 caselle in totale, che faremo selezionare all’utente con un numero da 1 a 100.

Anzitutto costruiamo la griglia fatta di oggetti di tipo Casella, definiti nel modo seguente:

Per costruire il campo useremo la funzione random.randint() per distribuire le mine in modo casuale, nel modo seguente:

In questo caso la variabile difficolta viene usata per bilanciare la distribuzione casuale. Se impostiamo difficolta su 2, avremo in media il 50% di caselle con mine (1/2). Se impostiamo difficolta su 10 allora avremo circa il 10% di mine (1/10), ecc.

Fatto questo dobbiamo costruire due metodi che si occuperanno rispettivamente di conteggiare le mine e aprire le celle. All’interno di entrambi i metodi useremo due cicli for ricordandoci che rispetto alla posizione attuale quelle intorno partiranno da [-1,-1] fino a [1,1]

Riporto di seguito il codice, commentato, dell’intero giochino realizzato a partire da queste idee: