[python] Calcolare le soluzioni di un sistema lineare di primo grado utilizzando il metodo di Cramer (senza librerie aggiuntive)

Obiettivo: Vogliamo calcolare, utilizzando Python, tutte le soluzioni per un sistema lineare di primo grado utilizzando le matrici e il metodo di Cramer. Per farlo non utilizzeremo librerie aggiuntive, se non quanto disponibile nativamente dentro Python.

Ovviamente lo scopo dell’esercizio è l’utilizzo di Python, visto che si potrebbe risolvere agilmente con librerie come SciPy e NumPy.

Supponiamo di avere un sistema lineare come quello seguente (l’ho scopiazzato spudoratamente da YouMath, dove c’è anche un’esaustiva spiegazione sul metodo di Cramer):

\begin{cases}2x+y+z=1 \\ 4x-y+z=-5 \\ -x+y+2z=5 \end{cases}

La matrice associata ai coefficienti ed il relativo determinante sarebbe questo:

\mbox{D}=\left| \begin{matrix} 2 & 1 & 1 \\ 4 & -1 & 1 \\ -1 & 1 & 2 \end{matrix}\right|=-12

Mentre la matrice dei termini noti sarebbe:

\mbox{A}=\left| \begin{matrix} 1 \\ -5 \\ 5 \end{matrix}\right|

Giusto per curiosità la soluzione immediata con NumPy sarebbe la seguente:

Il risultato nel caso specifico darà: [-1. 2. 1.]

Noi vogliamo costruire qualcosa di simile in Python 2.7.

Cominciamo creando la base della nostra classe perché possa accettare i medesimi argomenti:

Fatto questo cominciamo a creare i metodi di cui avremo bisogno. Il metodo di Creamer con il calcolo del determinante implica, per matrici di dimensione superiore a 2×2, che si debba poter ridurre la matrice in sottomatrici.

Giusto per chiarezza, nel caso del determinante D della suddetta matrice, il calcolo si svolgerebbe in questo modo:

\mbox{D}=\left| \begin{matrix} 2 & 1 & 1 \\ 4 & -1 & 1 \\ -1 & 1 & 2 \end{matrix}\right|= 2 * \left| \begin{matrix} -1 & 1 \\ 1 & 2 \end{matrix}\right| - 1 * \left| \begin{matrix} 4 & 1 \\ -1 & 2 \end{matrix}\right| + 1 * \left| \begin{matrix} 4 & -1 \\ -1 & 1\end{matrix}\right| =\newline = 2*(-1*2-1*1)-1*(4*2-(-1)*1)+1*(4*1-(-1)*(-1)) = \newline = 2*(-3)-1*(9)+1*(3)=\newline =-6-9+3=-12

Ogni sottomatrice prende tutti i valori della matrice corrente eccetto quelli nella riga e nella colonna della posizione attuale. Scriviamo quindi la nostra funzione nella maniera seguente:

Per calcolare il determinante vogliamo fare due operazioni distinte: il calcolo per matrici 2×2 e il calcolo per riduzione delle matrici di dimensione superiore. Iniziamo scrivendo l’operazione per quelle 2×2:

Per calcolare gli altri determinanti procederemo invece con:

In particolare con (1-2*(c%2)) calcoliamo il segno per ogni elemento della prima riga. In particolare ricordiamo che gli elementi saranno calcolati in ordine da 0, 1, 2, 3, 4 ecc. Se calcoliamo il resto per ognuno di essi avremo 0, 1, 0, 1, 0 ecc. Eseguendo la suddetta operazione avremo quindi 1-0, 1-2, 1-0, 1-2, 1-0 ecc. Questo ci darà i segni come 1, -1, 1, -1, 1 ecc.

A questo punto ci manca solo un metodo che ci permetta di creare nuove matrici per calcolare i vari determinanti per x, y, z ecc. Ricordiamoci che i vari risultati saranno dati da:

x=\frac{\mbox{D}_x}{\mbox{D}}=\frac{12}{-12}=-1\\ \\ \\ y=\frac{\mbox{D}_y}{\mbox{D}}=\frac{-24}{-12}=2\\ \\ \\ z=\frac{\mbox{D}_z}{\mbox{D}}=\frac{-12}{-12}=1

Dobbiamo fare attenzione ad un dettaglio importante. In Python le liste vengono passate per riferimento, questo vuol dire che modificando ogni lista “copiata” si modifica in realtà la lista originale all’indirizzo di memoria. Per copiare una matrice multidimensionale è necessario quindi copiare i singoli valori nella nuova matrice, nella maniera seguente darebbe errore:

Quindi procediamo in questo modo:

La nostra funzione di sostituzione sostituirà quindi i termini noti nella colonna preselezionata.

A questo punto possiamo scrivere il metodo che calcolerà la soluzione, alla maniera seguente:

Infine implementiamo il metodo solve aggiungendo un paio di chiamate di errore, nel caso in cui la matrice non sia adatta.

Nel suo complesso la classe che avremo creato sarà la seguente:

Per utilizzarla sarà sufficiente scrivere:

Se abbiamo fatto tutto correttamente il risultato che otterremo sarà: [-1.0, 2.0, 1.0]

Errori durante il file upload con PHP, Apache & nginx

Riallacciandomi al precedente articolo ([php] Configurare php.ini per l’upload dei file) voglio approfondire il problema del caricamento di file di grosse dimensioni su server che utilizzano PHP, Apache e nginx (nel mio caso specifico anche Plesk).

Gli errori che possono sorgere sono difatti innumerevoli e spesso apparentemente senza senso.

Cominciamo riepilogando il necessario per quello che riguarda il PHP. Come spiegato nel precedente articolo, assicuriamoci di avere una configurazione simile alla seguente nel file php.ini

In questo caso sto supponendo che caricheremo file fino a 512MB.

Per quanto riguarda il PHP ci dobbiamo assicurare che la quantità di memorie allocabile sia compatibile con la dimensione dei file da caricare e che lo sia anche il tempo di esecuzione.

Con un tempo di 1200 secondi si suppone che l’upload avverrà ad un minimo di 0,43MB/s. Questo significa che parte del caricamento dipende anche dalla velocità di upload del client, che potrebbe non essere sufficientemente alta da permettere al server di terminare l’operazione nei tempi consentiti.

Per inciso ricordiamoci che le classiche connessioni ADSL 20 Mega hanno upload che si aggirano attorno a 1 Mbit, ovvero 0,12 MB/s. Questo significa che il tempo di esecuzione dovrebbe essere per lo meno di 4.300 secondi (approssimando per eccesso).

Detto tutto questo si potrebbe incorrere in altri problemi, come ad esempio, lato client: Failed to load resource: net::ERR_HTTP2_PROTOCOL_ERROR

Se si sta tentando di gestire l’upload tramite javascript e si incorre in questo errore, esso nulla ha a che fare con il protocollo HTTP/2 (e tanto meno è utile tornare al HTTP/1.1 o simili), ma è legato al fatto che la pagina non invia una risposta corretta. La risposta non viene inviata correttamente perché ad interrompere l’upload possono essere Apache oppure nginx.

Controllando il log del server si potrebbe trovare infatti un errore simile al seguente: 19855#0: *532 client intended to send too large body: 180584796 bytes

In questo caso sto cercando di caricare circa 172MB di file ed nginix blocca l’operazione.

Nel mio caso specifico posso verificare la cosa, confrontando su Windows la dimensione dei file che sto tentando di inviare al server con un unico upload.

Si può notare come la dimensione bloccata sia leggermente più grande dei file in upload, perché, come già discusso nel precedente articolo, il corpo che viene inviato al server contiene anche informazioni aggiuntive che vanno al di là dei singoli file che si stanno caricando.

A questo punto dobbiamo intervenire su nginx aggiungendo l’istruzione:

La configurazione predefinite di nginx sarebbe di 1m, mentre sotto Plesk è di 128m.

Questo parametro può essere modificato all’interno del file /etc/nginx/nginx.conf

Per farlo su Plesk procediamo nel modo seguente (è anche spiegato nella vademecum ufficiale, anche se ci sono delle piccole incongruenze):

  1. Colleghiamoci via SSH al Server con Plesk
  2. Creiamo un file di configurazione aggiuntivo a cui aggiungeremo l’istruzione precedente: echo 'client_max_body_size 128m;' > /etc/nginx/conf.d/aa_client_max_body.conf
  3. Verifichiamo se esiste il file /usr/local/psa/admin/conf/panel.ini
  4. Se non dovesse esistere creiamolo copiandolo dal file predefinito: cp /usr/local/psa/admin/conf/panel.ini.sample /usr/local/psa/admin/conf/panel.ini
  5. Aggiungiamo l’impostazione per la massima dimensione del corpo: echo -e "[webserver]\n nginxClientMaxBodySize = 512m\n" >> /usr/local/psa/admin/conf/panel.ini
  6. Modifichiamo i permessi: chmod 644 /usr/local/psa/admin/conf/panel.ini
  7. Riconfiguriamo il tutto: plesk sbin httpdmng --reconfigure-all
  8. Riavviamo nginx: service nginx restart
  9. Assicuriamoci che su tutti i webserver sia configurato il parametro giusto: nginx -T | grep client_max_body_size
  10. Nel caso non lo fosse possiamo usare l’istruzione, per riconfigurare il tutto: plesk repair web -y -v

In generale dovremmo assicurarci che, rispetto ai parametri suddetti, nelle configurazioni di nginx, sotto la voce server, compaiano i seguenti due valori:

Questi valori dovrebbero essere in linea (o superiori) con quelli scelti per il PHP.

Infine dobbiamo verificare che anche Apache consenta l’esecuzione dell’upload. Nel caso specifico potrebbero esserci due parametri ad influenzarlo: FcgidMaxRequestLen  e LimitRequestBody

Impostiamoli nel modo seguente:

Se abbiamo configurato tutto correttamente dovremmo essere in grado di caricare i file come definito all’inizio.

[php] Configurare php.ini per l’upload dei file

L’upload dei file, nel PHP, dipende da diverse parametri, alcuni diretti ed altri indiretti, configurabili nel php.ini.

Anzitutto individuiamo il file di configurazione in uso. Per farlo è sufficiente utilizzare, in una pagina php, l’istruzione phpinfo();

Otterremo un output simile a questo:

Nel mio caso specifico, sotto Plesk, il file si trova in /opt/plesk/php/7.3/etc/php.ini

In una configurazione predefinita di Ubuntu Server 19.10 avremmo qualcosa di simile invece:

Il percorso del file php.ini in questo caso è /etc/php/7.3/apache2/php.ini

Detto questo modifichiamo il suddetto file individuando le seguenti istruzioni:

upload_max_filesize

Questo è il parametro principale, quello che riguarda la massima dimensione di un file in upload. Di solito si trova impostato a 2M oppure 8M. Se volessimo consentire un upload di 20MB dovremmo metterlo a: upload_max_filesize = 20M

post_max_size

Questo parametro indica la massima dimensione dell’intestazione di POST, nel caso specifico se volessimo aumentare il valore a 20MB dovremmo digitare: post_max_size = 20M

Attenzione, perché il POST contiene non solo il file in upload, ma anche altre istruzioni. Con una dimensione di 20MB significa che il massimo file caricabile sarà probabilmente attorno ai 19MB, perché una parte del post è utilizzata per inviare anche altre istruzioni, per quanto in genere ridotte e piccole. Un’istruzione più corretta potrebbe essere: post_max_size = 21M

max_file_uploads

Questo parametro definisce invece il numero massimo di file caricabili. Di predefinito è impostato su 20, quindi si potranno caricare al massimo 20 file in una volta. Se volessimo consentire il caricamento simultaneo di 50 file, potremmo impostarlo come: max_file_uploads = 50

 

A queste, che sono le istruzioni specificatamente dedicate al caricamento dei file, se ne aggiungono altre che sono strettamente connesse.

memory_limit

Il limite di memoria allocabile dal processo di PHP per l’esecuzione delle operazioni. Nel caso di grossi caricamenti questo limite potrebbe dover essere aumentato. Di solito il valore è 128M, ovvero 128MB, se volessimo aumentare il valore a 256MB dovremmo scrivere: memory_limit = 256MB

max_execution_time

Il massimo tempo di esecuzione del processo PHP. Di predefinito è impostato su 30 secondi, il che vuol dire che se l’upload impiega più tempo il PHP chiuderà l’operazione allo scadere del limite del tempo. Possiamo aumentare questo valore, per esempio su 10 minuti (60 secondi x 10), digitando: max_execution_time = 600

max_input_time

Come prima, anche questo parametro concorre col precedente. Se il tempo massimo di esecuzione è inferiore a questo parametro il processo di input verrà comunque interrotto; viceversa se questo valore è basso l’input verrà interrotto secondo quest’ultimo parametro. Se vogliamo dare anche qui 10 minuti per il massimo tempo di input digitiamo: max_input_time = 600

 

Riassumiamo infine tutte quante le variabili assieme:

[php] Costruire un oggetto iterabile che possa essere percorso con foreach, grazie alle interfacce Iterator, ArrayAccess e Countable

Oggi propongo un semplice esercizio in PHP dove vogliamo costruire un oggetto iterabile che sia accessibile come un vettore e percorribile da foreach.

Immaginiamo di avere due classi Studente e Scuola, quello che vogliamo ottenere è il qualcosa di analogo a questo:

L’output sarà così:

in tutto ci sono 4 studenti
0 -> Squall
1 -> Zell
2 -> Rinoa
3 -> Edea

Anzitutto cominciamo costruendo la classe Studente. Questa è molto semplice e non ha nulla di particolare, la possiamo costruire come vogliamo ed in particolare, ai fini dell’esercizio, la farò con una sola proprietà e due metodi (set e get).

Adesso costruiamo Scuola implementando i metodi Iterator, ArrayAccess, Countable.

Le tre interfacce permettono di implementare diverse proprietà. Affinché l’oggetto costruito con Scuola sia percorribile dal foreach usiamo l’interfaccia Iterator.

L’interfaccia implementa i seguenti metodi astratti:

Si suppone che la nostra classe abbia una proprietà “posizione“, per cui si possa ricavare un valore da questa posizione corrente con current(). Il metodo key() dovrà restituire tale posizione corrente, next() permetterà di andare alla posizione successiva, mentre rewind() consentirà di ripartire dalla posizione iniziale. Infine il metodo valid() verificherà se nella posizione attuale esiste o meno un oggetto.

Cominciamo allora costruendo la classe nel modo seguente:

Per rendere la classe operativa aggiungiamo anche un altro paio di metodi. In particolare:

Con il controllo if( $studente instanceof Studente ) vogliamo assicurarci che l’oggetto aggiunto tramite il metodo add() sia del tipo Studente. Se il tipo non è quello giusto solleviamo un errore del tipo InvalidArgumentException dove avvisiamo l’utente.

Significa che la forma:

Produrrà un errore del tipo Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in iterator.php:92 Stack trace: #0 iterator.php(87): Scuola->erroreOggettoNonValido() #1 iterator.php(98): Scuola->add('Squall') #2 {main} thrown in iterator.php on line 92

L’operazione valida sarà invece:

A questo punto l’oggetto è già iterabile mediante foreach, che può essere chiamato nel modo seguente:

Vogliamo dare la possibilità di aggiungere gli oggetti anche alla maniera di $scuola[] = new Studente("Edea");

Per farlo implementiamo la nostra classe Scuola anche su ArrayAccess. L’interfaccia ArrayAccess richiede i seguenti metodi:

Quindi implementiamoli nella nostra classe Scuola alla maniera seguente:

Anche qui usiamo if( $value instanceof Studente ) per verificare che l’oggetto sia di tipo Studente. Nel metodo offsetGet() utilizziamo il null coalescing operator per restituire null nel caso in cui l’oggetto non esista.

A questo punto l’istruzione $scuola[] = new Studente("Edea"); diventa utilizzabile, mentre $scuola[] = "Edea"; produce il solito errore Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in...

Infine vogliamo poter usare il metodo count($scuola) sul nostro oggetto, ottenendo il conteggio di tutti gli studenti inseriti. Se lo usiamo senza ulteriori implementazioni il risultato sarebbe sempre e comunque 1.

L’interfaccia Countable richiede un unico metodo:

Implementiamolo nel modo seguente:

Probabilmente sarebbe stato più carino implementare un metodo interno alla classe, magari un contatore che tenesse conto delle aggiunte, ma ai fini dell’esercizio ci accontentiamo di chiamare count sul vettore interno degli studenti.

Fatto tutto questo vediamo il risultato finale così ottenuto:

[wordpress] Got error ‘crayon-syntax-highlighter/crayon_langs.class.php on line 340

Problema: Dopo l’aggiornamento al PHP 7.3 il plugin per WordPress Crayon Syntax Highlighter, utilizzato per evidenziare codici di programmazione, smette di funzionare e blocca la visualizzazione delle pagine nelle quali è utilizzato.

Soluzione: Modificare due file per rendere compatibile il riconoscimento per espressioni regolari con le nuove definizioni di PCRE2

L’errore che si presenta è tipo il seguente: AH01071: Got error 'crayon-syntax-highlighter/crayon_langs.class.php on line 340PHP message: PHP Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in

Purtroppo il plugin, per quanto buono, non è aggiornato da 4 anni.

In particolare presenta problemi con l’aggiornamento del PHP alla versione 7.3, per via delle nuove definizioni PCRE2 ed in particolare proprio per la presenza di un segno – (meno), proprio come trattato nel precedente articolo.

Per risolvere il problema facciamo nel modo seguente. Posizioniamoci nella cartella del plugin /wp-content/plugins/crayon-syntax-highlighter/

Modifichiamo il file crayon_langs.class.php alla riga 340

Sostituiamo la riga con:

Modifichiamo il file crayon_formatter.class.php alla riga 118

Sostituiamo le due righe con:

Fatto tutto questo il problema sarà risolto e potremo continuare ad usare il plugin.

Differenze e novità tra PHP5 e PHP7, con esempi di programmazione

Con la scusa di un po’ di esercizio vediamo anche quali sono le principali differenze tra (l’ormai vecchio) PHP 5 e il nuovo PHP 7 (che comunque è in circolazione già da un bel po’).

1. Sintassi flessibile per Heredoc e Newdoc
2. Operatore Spaceship
3. Null Coalesce Operator
4. Virgola finale negli argomenti di funzione
5. Migrazione a PCRE2
6. Unicode Codepoint Escape Syntax
7. Chiamata di errore nella codifica JSON
8. Exceptions per i fatal errors
9. Classi anonime
10. Dichiarazione del tipo di dato restituito
11. Metodo is_countable()
12. Primi e ultimi valori e chiavi di un array
13. Il metodo Closure->call
14. Prestazioni migliorate

1. Sintassi flessibile per Heredoc e Newdoc

Nell’ultimo aggiornamento del PHP 7.3 viene introdotta la possibilità di terminare il heredoc con UNA indentazione. Sottolineo UNA perché la cosa è un po’ comica, visto che una doppia indentazione (due tabulazioni) oppure degli spazi producono comunque errore.

In sostanza prima si doveva scrivere così:

Adesso è possibile scrivere così:

Questa singola tabulazione certo non farà la felicità assoluta di nessuno, però permette di aggiungere un po’ di chiarezza al codice (sebbene personalmente continui a trovarla una novità abbastanza inutile, tale qual’è).

2. Operatore Spaceship

A differenza della precedente, questa è una novità effettivamente significativa.

Viene introdotto l’operatore <=>, chiamato spaceship, che fa le veci (quasi ma non del tutto) della funzione strcmp. Questo velocizza la scrittura e ottimizza la sintassi, riducendo così il numero di passaggi a volte necessari.

Avendo il seguente codice:

Avremo il seguente output:

a <=> b : -1
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Utilizzando invece strcmp avremmo avuto il seguente codice:

Ed il seguente output:

a <=> b : -1
mario <=> maria : 14
marii <=> mario : -6
maria <=> mario : -14
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Come si può notare il comportamento non è identico, se consideriamo i valori numerici e non i segni.

Per riprodurre il comportamento dell’operatore spaceship in PHP 5 potremmo immaginare di scrivere una funzione simile a questa:

Applicandola all’elenco precedente:

Avremo gli stessi risultati di <=> in PHP 7:

a <=> b : 0
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Immaginiamo dunque di voler scrivere una funzione di ordinamento per un array. In PHP 5 avremmo potuto scrivere:

Mentre in PHP 7 possiamo sintetizzare con:

Entrambi i casi produrranno un output ordinato come il seguente:

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 7 [5] => 8 )

Inutile dire che per entrambi gli esempi avremmo potuto incorporare direttamente una funzione anonima dentro ad usort in questo modo:

Infine nel PHP 5 l’uso dell’operatore spaceship produrrebbe un errore di questo tipo:

Parse error: syntax error, unexpected '>' in /index.php on line 16

3. Null Coalesce Operator

In PHP 7 viene introdotto il null coalescing operator ??, proseguendo così le implementazioni sull’if lineare, già introdotte nel PHP 5.3 con l’Elvis operator ?:.

In generale sappiamo che possiamo scrivere un’istruzione con if lineare (o operatore ternario) di questo tipo:

Questa istruzione equivale a scrivere:

In generale questa istruzione può essere utilizzata per riassegnare la medesima variabile in uno dei due casi. Per esempio immaginiamo di voler scrivere:

Con l’Elvis operator possiamo sintetizzare la scrittura nel modo seguente:

Quello che viene assegnato è l’argomento del test. Se l’argomento del test comprende operatori logici viene assegnato il risultato dell’operazione logica.

Per capire meglio immaginiamo di voler trovare il più grande valore tra quelli dati (ci sarebbero altri mille modi, ma per lo scopo dell’esercizio prendiamo questo):

Il risultato di questa operazione darà ovviamente come risultato 8.

Se lo riscrivessimo con l’Elvis operator potremmo avere qualcosa del genere:

Purtroppo però il risultato non sarebbe più 8, bensì 1, e questo indipendentemente dal fatto che 1 esista nell’array. E’ 1 perché 1 è true, il risultato di una delle operazioni di test. (il penultimo massimo è 8, quindi 8 è maggiore di 2? sì, vero, quindi 1!)

Praticamente serve solo quando il risultato che vogliamo valutare è tra true o false, stringa nulla o meno, ecc.

A questo si aggiunge il null coalescing operator che integra il controllo della nullità della variabile, sostituendosi alla funzione isset. Immaginiamo di avere:

Questo può diventare ora:

Il comportamento è identico. Il risultato è che le seguenti due scritture sono fondamentalmente uguali, eccetto per un dettaglio:

La prima non produce una notice, mentre la seconda ci segnala qualcosa del tipo:

Notice: Undefined index: valore in index.php on line 9

Facciamo un altro esempio con entrambe:

La prima scrittura restituisce Mario senza ulteriori errori, l’oggetto non è dichiarato, quanto l’attributo; la seconda produce ancora due notice:

Notice: Undefined variable: studente in index.php on line 15

Notice: Trying to get property 'nome' of non-object in index.php on line 15

A questo punto potremmo anche scrivere:

Per dichiarare l’oggetto laddove inesistente, mentre la seguente scrittura produrrebbe sempre una notice:

A questo punto potremmo scrivere altre due equivalenze, dal punto di vista del risultato:

Ovviamente possiamo sfruttare l’operatore per altre aggregazioni del tipo:

Dove il risultato è 42, ovvero il primo valore non null della sequenza.

4. Virgola finale negli argomenti di funzione

Adesso è possibile dimenticarsi una virgola dopo l’ultimo argomento di una funzione, senza che il PHP si agiti per questo 🙄

Mentre sia nel PHP 5 che nel PHP 7 la seguente dicitura non provocava problemi:

Provare a fare lo stesso con una funzione, che accetti argomenti predefiniti o meno, provoca un errore:

Nel PHP 5 entrambe le funzioni avrebbero prodotto un errore del tipo:

Parse error: syntax error, unexpected ')' in index.php on line 12

Personalmente non la trovo un’innovazione strepitosa, ma va bene, adesso sappiamo che c’è.

5. Migrazione a PCRE2

Il PHP utilizza in generale PCRE per l’interpretazione delle espressioni regolari. Nel PHP 7.3 è stato finalmente introdotto l’utilizzo del PCRE2 che ha aspetti un po’ più stringenti e severi sulla sintassi. Facciamo un esempio, immaginando di avere una stringa dalla quale vogliamo trovare tutte le parole, compreso il simbolo (meno) e il . (punto); nel PHP 5 entrambe le seguenti scritture sarebbero state valide:

Soprassediamo sul fatto che i caratteri speciali verranno saltati e considerati alla stregua di spazi, ma il risultato sarà qualcosa di simile a:

 

Usando la prima espressione regolare all’interno di un programma come il Notepad++ avremmo ottenuto un errore:

Mentre la seconda è valida. Adesso anche nel PHP 7.3 la seconda espressione è l’unica valida, mentre la prima non funziona producendo un errore del tipo:

Warning: preg_match_all(): Compilation failed: invalid range in character class at offset 3 in index.php on line 10

Giusto per curiosità, se si volessero prendere anche i caratteri speciali potremmo utilizzare la seguente espressione regolare:

6. Unicode Codepoint Escape Syntax

Visto che si parla di stringhe facciamo un piccolo appunto a proposito dei riferimenti ai caratteri Unicode. Adesso è possibile specificarli direttamente nelle stringhe di testo con la sintassi \u{XXX}. Maggiori approfondimenti si possono trovare qui sul sito ufficiale. Questo significa che scrivendo:

Nel PHP 5 vedremo la stringa tale e quale:

\u{202E}Testo inverso

Mentre nel PHP 7 vedremo:

‮Testo inverso

Il carattere in questione è il U+202E RIGHT-TO-LEFT OVERRIDE

Si possono usare tutti i caratteri unicode, anche quelli associati agli smile, per cui echo "\u{1F602}"; produrrà 😂

7. Chiamata di errore nella codifica JSON

Adesso è finalmente possibile forzare il JSON a sollevare un errore in caso di stringhe non (de)codificabili. E’ possibile infatti scrivere nel modo seguente:

Senza l’aggiunta di JSON_THROW_ON_ERROR non ci sarebbe nessuna segnalazione di errore. Grazie a tale istruzione otteniamo invece il seguente errore fatale:

Fatal error: Uncaught JsonException: Syntax error in index.php:8 Stack trace: #0 index.php(8): json_decode('stringa JSON no...', NULL, 512, 4194304) #1 {main} thrown in index.php on line 8

8. Exceptions per i fatal errors

A proposito di errori, finalmente è stato migliorato il sistema di cattura delle eccezioni con try… catch. Primo era sostanzialmente, per farla breve, necessario chiamare throw new Exception(); per sollevare un’eccezione. Adesso è possibile intercettare anche le eccezioni di sistema. Nel caso precedente l’eccezione è intercettabile con:

Come altro esempio immaginiamo di chiamare una funzione non esistente:

Nel dobbiamo usare Error per intercettare l’errore, e mentre nel PHP 5 avremmo comunque avuto il seguente output:

Fatal error: Call to undefined function funzione() in index.php on line 9

Mentre nel PHP 7 avremmo il seguente valore, prodotto dal nostro echo:

errore: Call to undefined function funzione()

9. Classi anonime

Tra le varie novità vi è la possibilità di implementare classi anonime. Cominciamo dall’esempio più semplice:

Nel PHP 5 questo produrrebbe un errore del tipo:

Parse error: syntax error, unexpected 'class' (T_CLASS) in index.php on line 7

Alla classe anonima possono essere passati anche degli argomenti per il costruttore, nel modo seguente:

L’output invece che Mario sarà Luigi. Le classi anonime possono anche estendere altre classi, come ad esempio:

Oppure implementarle:

Senza implementare il metodo stampaNome() avremmo il seguente errore:

Fatal error: Class class@anonymous contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Studente::stampaNome) in index.php on line 11

10. Dichiarazione del tipo di dato restituito

Il PHP 7 introduce la possibilità di forzare il tipo di dato restituito da una funzione. Immaginiamo di voler scrivere una funzione somma che restituisca solamente valori interi. Nella maniera classica avremmo scritto:

Passando come argomento 2.5 e 3 il risultato sarebbe stato 5.5, un float. Per forzare l’output di un intero avremmo potuto scrivere:

In PHP 7 è possibile anche scrivere:

Sintassi che nel PHP 5 avrebbe prodotto il seguente errore:

Parse error: syntax error, unexpected ':', expecting '{' in index.php on line 7

11. Metodo is_countable()

In PHP 7 è possibile verificare se un oggetto sia “conteggiabile” ovvero sia del tipo Countable. Immaginiamo la seguente serie di istruzioni:

Essendo Studenti conteggiabile viene stampato il conteggio. Nel PHP 5 avremmo ovviamente avuto un errore del tipo:

Fatal error: Call to undefined function is_countable() in index.php on line 19

Facciamo un altro esempio di funzione implementabile su Countable e dove ci può tornare utile il nuovo metodo:

In questo caso non abbiamo bisogno di chiamare la funzione count() all’interno di public function count(), ma possiamo tenere traccia della quantità di voci aggiunte al vettore $studenti tramite un contatore interno.

12. Primi e ultimi valori e chiavi di un array

Immaginiamo di avere un array di questo tipo:

Alla maniera precedente avremmo potuto scrivere:

In questo modo avremmo ottenuto un output del genere:

primo valore: 1
prima chiave: a
ultimo valore: 100
ultima chiave: c

Questo implica anche che stiamo spostando il cursore nella posizione attuale dell’array. Se provassimo a scrivere:

Il risultato non sarebbe corretto e avremmo:

primo valore: 1
ultimo valore: 100
prima chiave: c
ultima chiave: c

Quindi questa scrittura sarebbe stata impossibile. Ora, con il PHP 7.3 è possibile scrivere nel modo seguente:

Le funzioni proposte sono attualmente: array_key_first(), array_key_last() and array_value_first(), array_value_last() anche se sono state introdotte, nel PHP 7.3 solamente quelle riguardanti le chiavi. Maggiori dettagli sulla questione qui: PHP RFC: array_key_first(), array_key_last() and array_value_first(), array_value_last()

13. Il metodo Closure->call

Nel PHP 7 viene introdotta una semplificazione nell’atto di binding delle closure.

 

Se sembra che tutti si stia dicendo cose a caso vediamo un esempio:

Notiamo che la funzione scritta su $closure va ad integrare la classe, potendo interagire con tutte le sue variabili interne anche se private.

14. Prestazioni migliorate

Infine il PHP 7 introduce notevoli implementazioni in termini di performance. Di seguito riporto i risultati di benchmark ottenuti grazie a benchmark-php su un medesimo server, ma con due diverse versioni di PHP. In particolare la versione PHP 7.3 introduce notevole stabilità nell’esecuzione e nel mantenimento delle performance.

PHP 7.3.5 PHP 5.6.40

 

[wordpress] Cambiare le bandierine per le lingue di PolyLang

Per cambiare le immagini delle bandiere delle lingue del plugin PolyLang è sufficiente procedere nella maniera seguente:

  1. Creare dei file PNG (*.png), JPG (*.jpg) o SVG (*.svg) nominandoli secondo il codice della lingua, ad esempio: it_IT per italiano, en_GB o en_US per inglese (dipende quale si è scelto nelle impostazioni di PolyLang), de_DE per il tedesco ecc
  2. Creare la cartella /wp-content/polylang (la cartella non esiste di predefinito)
  3. Caricare nella cartella i file delle bandiere creati in precedenza
  4. Andare su WordPress in Bacheca > Lingue > Impostazioni > Modifiche dell’URL > Impostazioni, senza dover apportare modifiche premere su Salva modifiche

A questo punto le nuove bandiere saranno visibili al posto di quelle predefinite.

[excel] Calcolare tutte le possibili combinazioni con ripetizione usando le matrici in Excel

Obiettivo: dato un insieme di elementi distinti n vogliamo calcolare tutte le possibili combinazioni che si possono formare con k degli n elementi dati, dove k \in \mathbb{N}

Secondo il calcolo combinatorio il numero di combinazioni con ripetizione che possiamo ottenere si calcola con la seguente formula:

C'_{(n,k)}=\left(\begin{matrix} n+k-1 \\ k \end{matrix} \right)=\frac{(n+k-1)!}{k!(n-1)!}

Con Excel vogliamo ottenere una matrice contenente tutti gli elementi, dove ogni elemento può essere testuale o numerico. A tale scopo utilizzeremo le caratteristiche sul calcolo matriciale introdotte recentemente in Office365 e le seguenti funzioni: INDICE, INDIRETTO, MATR.TRASPOSTA, RIPETI, UNICI, STRINGA.ESTRAI, FILTRO

Prima di procedere ricordiamo che UNICI e FILTRO sono per ora disponibili solo con Office365. Inoltre useremo il # (cancelletto) nella costruzione dei riferimenti, per prendere gli intervalli dinamici generati dalle matrici.

Definiamo quindi anzitutto gli elementi n e il numero di ripetizioni k in questo modo:

Nella riga 1 potremo aggiungere altri elementi a piacere, mentre in B2 inseriremo il numero di ripetizioni desiderate. Per praticità ho chiamato gli elementi A, B e C.

Cominciamo allora calcolando anzitutto il numero di elemento n nella cella B3:

Adesso vogliamo determinare il numero di disposizioni con ripetizione possibili, ovvero tutti i modi in cui possiamo disporre gli n elementi presi a gruppi di k, dove conta l’ordine.

Per chi non fosse pratico dell’argomento se abbiamo i suddetti 3 elementi, allora nelle combinazioni con ripetizione ABC e ACB sono la stessa combinazione (contengono ciascuna tutti e 3 gli elementi), mentre nelle disposizioni con ripetizione ABC e ACB sono elementi distinti.

Il numero totale di disposizioni con ripetizione sarà dato dalla formula:

D'_{(n,k)}=n^k

Che tradotta in Excel possiamo scrivere in B5 come:

Date queste informazioni calcoliamo tutti gli elementi possibili con la seguente formula in B11:

Questa genererà un risultato come il seguente:

L’idea è fondamentalmente quella di generare una matrice di riferimenti agli elementi dati in modo ordinato. Con 3 elementi presi 3 per volta avremo in tutto 27 disposizioni con ripetizione. Generiamo allora una matrice colonna con valori [1…27]. Nella prima colonna da [1…9] avremo il primo elemento, da [10…18] avremo il secondo elemento e così via. Siccome il primo elemento corrisponde a 1 e il secondo a 2, questo significa che presi i valori da [1…27] li dovremo dividere in 3 parti di 9 elementi ciascuna.

Questo lo potremmo ottenere scrivendo:

In questo modo generiamo [1…27] e dividiamo per 9, poi arrotondiamo per eccesso il risultato. Ne seguirà che, arrotondati per eccesso, 1/9 ⇒ 1, 9/9 ⇒ 1, 10/9 ⇒ 2, 18/9 ⇒ 2, 19/9 ⇒ 3, 27/9 ⇒ 3. Avremo insomma tre intervalli fatti, rispettivamente, di [1…1], [2…] e [3…3], ciascuno di 9 sottoelementi.

Nell’immagine di seguito vediamo la schematizzazione di ciò che vogliamo ottenere:

Per ciascun gruppo della prima colonna vorremo ottenere, nella seconda colonna, altri 3 sottogruppi, per ciascuno dei quali, nella terza colonna, vorremo ottenere altri 3 sottogruppi (questa volta di dimensione 1). Quindi i gruppi saranno 1, 3 e 9. Questi sono anche i valori per i quali dobbiamo sezionare gli intervalli delle colonne.

Per generare questi valori usiamo:

La matrice trasposta ci serve per metterli in riga, anziché in colonna. Dividiamo infine la prima colonna per questa riga.

Fatto questo spostiamoci in I10 e digitiamo:

In questo modo riportiamo semplicemente gli elementi scritti da B1 in poi.

In I11 calcoliamo quante volte appare ciascun elemento della matrice in B11#:

NB: grazie al cancelletto selezioniamo tutta la matrice generata da B11.

Il risultato che avremo sarà:

Nella prima riga A è presente 3 volte, gli altri due elementi 0 volte. Nella seconda riga abbiamo 2 A e 1 B, ecc.

In questo caso stiamo semplicemente usando la funzione CONTA.PIÙ.SE su righe successive, per ciascuno dei valori immessi.

A questo punto, sapendo quanti sono i singoli valori, possiamo usare la funzione RIPETI per riscriverli. Tale funzione ripete un dato valore per n volte. Quindi in P11 scriviamo:

Otterremo un risultato come il seguente:

Adesso facciamo una mossa un po’ astrusa. Siccome sappiamo che per ogni riga ci sono k elementi, ovvero 3 elementi, concateniamo tutta la matrice in una singola stringa e la spezziamo in pezzi da 3 elementi per volta. Verrà quindi una lunghissima stringa che comincerà con AAAAABAACAABABBABCAAC… e che verrà spezzata in AAA, AAB, AAC, AAB, ABB ecc.

Per farlo in W11 digitiamo:

La parte di formula con:

Genera una matrice colonna tipo:

La usiamo per spezzare la stringa in parti da 3 a partire dal 1° carattere, il 4° carattere, il 7° carattere ecc.

Il risultato che otterremo saranno tutte le disposizioni con ripetizione di cui parlavamo prima:

Per ottenere le combinazioni con ripetizione che stavamo cercando possiamo fare in due modi.

1. Utilizzando la funzione UNICI

In Z11 scriviamo:

E ricaviamo immediatamente l’elenco ridotto delle combinazioni in questo modo:

Questa è la maniera più semplice e veloce.

2. Utilizzando la funzione FILTRO

Questo è un modo un pizzico più complicato. Per ciascuno dei valori in W11# vogliamo calcolare la presenza del valore stesso nelle righe precedenti. Per farlo utilizzeremo la funzione SCARTO, aumentando la altezza della colonna della matrice di controllo via via che scendiamo. A questa applicheremo il CONTA.SE per vedere se il valore attuale, cioè ciascun valore della matrice, è presente nella sottomatrice precedente calcolata con SCARTO. Confrontando questo valore con 1, ovvero che debba comparire una sola volta, costruiremo la matrice colonna per il filtro da applicare alla funzione FILTRO.

La formula quindi sarà:

In entrambi i casi il risultato sarà identico:

Dal seguente link è possibile scaricare il file Excel con tutti i calcoli già fatti: combinazioni semplici

[PCSX2] Giocare a Harry Potter e il prigioniero di Azkaban per PS2 su PC con PCSX2

Harry Potter e il prigioniero di Azkaban uscì per PS2 nel 2004. Se avete ancora il gioco, ma non una PlayStation2 e volete provare a giocarci da PC una possibile soluzione è utilizzando l’emulatore PCSX2.

Ringrazio @Memento_Gallery per la foto

Prima di procedere premetto che questo è uno di quei giochi (tutta la serie di Harry Potter per PS2 sembra essere affetta dal medesimo problema) che sugli emulatori dà più rogne che altro.

Anzitutto vediamo di cosa abbiamo bisogno:

  1. Emulatore PCSX2 v1.5.0-dev-3362 (quella su cui ho testato la presente soluzione)
  2. Emulatore joystick PS4 DS4Windows (se intendete usare un DualShock 4 come il sottoscritto, altrimenti basta un qualunque controller compatibile con Windows)
  3. BIOS originale della PS2 da utilizzare su PSCX2 (rimando a internet su come procurarselo)
  4. File ISO del gioco. Se avete il gioco su DVD come il sottoscritto, potete masterizzare un file ISO direttamente dal computer inserendo il gioco nel lettore.

Prima di cominciare scarichiamo ed installiamo il PCSX2.

Possiamo lasciare tutte le impostazioni sui parametri predefiniti, finché non si arriverà alla scelta del BIOS della PS2. A quel punto selezioniamo la cartella dove abbiamo il file del BIOS e scegliamo la versione che preferiamo, io ho quella Europea naturalmente.

A questo punto configuriamo l’emulatore con i parametri riportati di seguito.

Anzitutto andiamo su Configurazione > Impostazioni emulazione > Speed Hack

image.png

Qui spuntiamo la voce MTVU (microVU1 multi-threaded).

Andiamo su Configurazione > Video (GS) > Impostazioni plugin… e configuriamo i parametri nel modo seguente:

image.png

Clicchiamo su Advanced Settings and Hacks e modifichiamo i parametri come i seguenti:

image.png

A questo punto andiamo su Configurazione > Audio (SPU2) > Impostazioni plugin… ed impostiamo i parametri come quelli di seguito:

image.png

Fatto questo possiamo caricare la ISO ed avviare il gioco.

Se state usando un controller PS4 consiglio di avviare DS4Windows prima dell’emulatore, per far sì che lo veda come un controller standard di Windows.

[excel] Sommare tariffe giornaliere diverse in base alla data utilizzando le matrici in Excel

Obiettivo: Immaginiamo di voler calcolare il costo dei pernottamenti in un albergo dove le tariffe variano in base alla stagione (nello specifico in base ai mesi) e si ha una data di ingresso e il numero di notti.

Una soluzione a questo esercizio l’ho già proposta sul blog di Mummu Academy, giocando un po’ con le matrici: [EXCEL] SOMMARE TARIFFE GIORNALIERE DIVERSE PER DATA USANDO LE MATRICI IN EXCEL

La soluzione che propongo qui è più semplice e sintetica e fa uso sempre del calcolo matriciale in Excel.

Come nel suddetto esercizio la nostra base di partenza è un foglio in Excel contenente i seguenti dati:

I dati che vogliamo generare sono quelli dell’intervallo G2:G6.

Anzitutto vogliamo ottenere una matrice contenente tutte le date di pernottamento. Per farlo prenderemo ciascuna data di partenza e sommeremo i giorni corrispondenti. Se dobbiamo sommare 5 notti allora alla data di partenza dovremo sommare il vettore [0, 1, 2, 3, 4]. Faccio notare come il vettore parta da 0. Questo perché, nel caso di Mario Rossi, i pernottamenti li avremo nei giorni [21/06/2019, 22/06/2019, 23/06/2019, 24/06/2019, 25/06/2019]. La prima data deve essere anche quella di arrivo.

Generiamo quindi anzitutto il vettore dei giorni come detto prima, sfruttando RIF.RIGA e INDIRETTO nel modo seguente:

Questo genererà un vettore simile a questo:

Adesso possiamo sommare a questo vettore la data di partenza:

Il vettore che potremo vedere a schermo (grazie anche alle nuove funzionalità di espansione di Excel) sarà come il seguente:

Dall’elenco delle date vogliamo adesso estrarre il mese corrispondente utilizzando la funzione MESE.

Il risultato dell’operazione sarà simile a questo:

Il numero 6 rappresenta il mese di giugno. Se applicassimo questa formula a Chiara Celesti vedremmo un risultato simile a questo:

Faccio notare come alla fine del mese di dicembre si passi da 12 a 1, ovvero a gennaio.

A questo punto possiamo usare il CERCA.VERT su ciascuno di questi valori per ricavare la tariffa che ci interessa. La formula diventerà dunque:

In questo modo otterremo un vettore contenente la tariffa per ogni singolo giorno. Non ci resta che usare la SOMMA.

La formula diventerà quindi:

A questo punto possiamo espandere la formula da G2 a G6. Se abbiamo fatto tutto correttamente otterremo i seguenti risultati: