Robitex's Blog
Ideas in the web
Numeri in lettere con Python
Pubblicato da su 24/12/2011
Scarica l’articolo nel formato PDF per la stampa
Sommario
L’articolo presenta il codice nel linguaggio Python per convertire un numero in parole nel comune formato ‘finanziario’.
Il codice
Avevamo già risolto questo problema prima con Java e poi con Lua. Lua è un linguaggio di scripting assai simile a Python e non è stato difficile convertire il listato. Ho dapprima effettuato su una copia del listato in Lua, una serie di sostituzioni: then con :, function con def per esempio. Come secondo passo ho poi sistemato con precisione l’identazione del codice poiché in Python è il mezzo per individuare i blocchi di istruzioni.
Terminate queste due operazioni, mi sono ritrovato con un codice Python quasi del tutto completo. Mancava trovare il sostituto per alcune funzioni di libreria Lua, risolte con lo slicing e con alcune funzioni di base matematiche. Infine ho migliorato la funzione di wrapper della funzione ricorsiva in una versione più completa e razionale rispetto all’originale Lua. Ecco il risultato:
#!/usr/bin/python
# script di traduzione di numeri in lettere
# nella lingua italiana
# traduce un numero in lettere
# funzione ricorsiva
def NumberToTextInteger(n):
if n == 0:
return ""
elif n <= 19:
return ("uno", "due", "tre", "quattro", "cinque",
"sei", "sette", "otto", "nove", "dieci",
"undici", "dodici", "tredici",
"quattordici", "quindici", "sedici",
"diciassette", "diciotto", "diciannove")[n-1]
elif n <= 99:
decine = ("venti", "trenta", "quaranta",
"cinquanta", "sessanta",
"settanta", "ottanta", "novanta")
letter = decine[int(n/10)-2]
t = n%10
if t == 1 or t == 8:
letter = letter[:-1]
return letter + NumberToTextInteger(n%10)
elif n <= 199:
return "cento" + NumberToTextInteger(n%100)
elif n <= 999:
m = n%100
m = int(m/10)
letter = "cent"
if m != 8:
letter = letter + "o"
return NumberToTextInteger( int(n/100)) + \
letter + \
NumberToTextInteger(n%100)
elif n<= 1999 :
return "mille" + NumberToTextInteger(n%1000)
elif n<= 999999:
return NumberToTextInteger(int(n/1000)) + \
"mila" + \
NumberToTextInteger(n%1000)
elif n <= 1999999:
return "unmilione" + NumberToTextInteger(n%1000000)
elif n <= 999999999:
return NumberToTextInteger(int(n/1000000))+ \
"milioni" + \
NumberToTextInteger(n%1000000)
elif n <= 1999999999:
return "unmiliardo" + NumberToTextInteger(n%1000000000)
else:
return NumberToTextInteger(int(n/1000000000)) + \
"miliardi" + \
NumberToTextInteger(n%1000000000)
# funzione wrapper
def NumberToText(x, pos=2):
""" Ritorna un numero tradotto in lettere
secondo un formato 'finanziario'
"""
sign = ""
if x<0:
sign = "meno"
x = abs(x)
x = round(x, pos)
n = int(x)
frmt = "{0:0."+"{0:d}".format(pos)+"f}"
spic = frmt.format(x-n)[2:]
if n == 0:
num = "zero"
else:
num = NumberToTextInteger(n)
return sign+num+"/"+spic
# prelevo il valore numerico
value = input("Valore: ")
print("il numero {0} in lettere =".format(value))
print("{0}".format(NumberToText(value)))
Test (note tecniche)
Per testare il codice occorre aver installato un interprete Python. Avviate una finestra di console e scrivete il nome che avete dato al file contenente il codice (confrontate l’immagine sottostante presa da un sistema Ubuntu 10.04).
Auguri
Un Augurio di Buon Natale e per uno splendido nuovo anno 2012!
Il computo metrico con Lua
Pubblicato da su 12/12/2011
Scarica l’articolo in formato PDF per la stampa
Sommario
Certi tipi di opere edili possono essere così articolate da mettere in difficoltà l’utente che intendesse gestirle con un tradizionale software di computazione.
In questo post si svilupperà un’idea che può risolvere il problema di efficienza, secondo la quale i dati sono descritti da un opportuno linguaggio così da esprimere in modo diretto e concettuale le particolarità dell’opera edilizia.
Computi metrici
Un computo metrico di un opera consiste in una serie di voci che definiscono i singoli componenti edilizi quantificate secondo una specifica unità di misura. Inserire le misure è una di quelle attività leggermente noiose e poco attraenti…
Con un linguaggio specifico è possibile rendere efficiente l’inserimento manuale di queste quantità, in particolare se si desidera che i dati siano raggruppati in livelli strutturati.
Il linguaggio dei solai
Se l’opera in progetto è composta da diversi edifici a più piani, dovremo calcolare le superfici dei solai raggruppando i dati secondo la doppia classificazione piano/edificio. Saremo così in grado di fornire le superfici di solaio per ciascun piano, quelle totali per singolo edificio e quelle complessive per piano.
Un linguaggio semplice che descrive questa struttura informativa potrebbe essere questo:
solaio{
edificio = "A",
piano = 1,
superficie = 4.50*3.25,
}
La sintassi che riscontriamo leggendo il frammento di codice, si basa su un costrutto chiave = valore ciascuno separato con una virgola e racchiuso in un coppia di parentesi graffe.
I valori testo sono racchiusi tra doppi apici mentre i valori numerici utilizzano il punto e non la virgola per separare la parte decimale.
Vi anticipo che il codice precedente corrisponde alla sintassi di Lua, un linguaggio di programmazione libero e multi-piattaforma, più volte trattato sul blog.
Continuando a tagliare su misura il codice per renderlo perfettamente adatto ad esprimere le quantità che vorremmo computare, osserviamo che non ci occorre identificare i singoli solai di uno stesso piano di uno stesso edificio. Alla chiave superficie assegniamo allora non un singolo valore o espressione, ma un elenco di espressioni corrispondenti alla geometria dell’impalcato, per esempio (possiamo commentare il codice inserendo due trattini):
-- cambiamo nome all'oggetto :-)
solaiDiPiano{
edificio = "A",
piano = 1,
superficie = {
2*4.50*3.25, -- qui due solai uguali
3.80*3.25,
4.64*4.20 - 0.40*0.70, -- qui una detrazione di una botola!
4.24*(4.20 + 3.50),
5.50*3.60, -- la virgola finale è opzionale
}, -- ma rende più comode successive
} -- aggiunte di valori
Osservazioni operative
L’ambiente in cui si memorizza il codice è un editor di testo ASCII. La comodità sta nel fatto che i dati sono immediatamente disponibili su qualsiasi sistema operativo per eventuali modifiche o verifiche, e possiamo eseguire le operazioni con poca fatica.
Nel frattempo ho aggiunto altri dati come potete vedere dal prossimo frammento di codice:
solaiDiPiano{edificio="A", piano=1,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="A", piano=2,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="A", piano=3,
superficie = {
2*(1.65+3.60+2.12)*(4.42+4.32),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="B", piano=1,
superficie = {
2*(2.54+2.54+2.56+2.545)*(4.345+4.245),
2*1.00*2.64
}
}
solaiDiPiano{edificio="B", piano=2,
superficie = {
2*(2.54+2.54+2.56+2.545)*(4.345+4.245),
2*1.00*2.64
}
}
solaiDiPiano{edificio="C", piano=1,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="C", piano=2,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="C", piano=3,
superficie = {
2*(1.65+3.60+2.12)*(4.42+4.32),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
Elaborare i dati
Ma come si elaborano i dati?
Il codice scritto corrisponde esattamente ad una serie di chiamate alla funzione Lua solaiDiPiano() a cui passiamo una tabella.
Eseguendo il codice, verranno calcolate le espressioni delle superfici e le istruzioni contenute nella funzione.
Elaborazione diretta
Proviamo a scrivere la funzione in modo da ottenere la superficie totale dei solai:
-- superficie totale
local totsup = 0
-- definizione della funzione
function solaiDiPiano(s)
-- campi in s:
-- s.superficie -> array di valori
-- sommo tutti i valori in s.superficie
-- e li inserisco nel totale
for _, val in ipairs(s.superficie) do
totsup = totsup + val
end
end
-- carico il file dati
dofile("solai.lua")
-- stampo il risultato
print(string.format("Superficie totale : %0.3f",totsup))
Una volta installato sul sistema Lua, inseriamo i dati dei solai così come si è deciso di descriverli nel file testo “solai.lua”. Salviamo in un secondo file il codice che li elabora “calcsuptot.lua”, ed infine apriamo il terminale o la console ed eseguiamo il comando:
> lua calcsuptot.lua
Fatto! La schermata rappresentativa dell’operazione in Windows è la seguente, dove si può notare l’uso del comando cd per spostarsi nella directory dove avevo salvato i due file.
Elaborazione strutturata
Diamo una definizione strutturata della funzione solaiDiPiano() in modo da costruire una tabella dati chiamata Solai che potremo leggere in modi diversi. Questa è la via sicuramente più flessibile e potente.
-- serve un contenitore per i dati:
local Solai = {}
-- creazione della tabella dati
function solaiDiPiano(s)
-- ricordiamo i nomi dei campi in s
-- s.edificio := nome edificio
-- s.piano := numero di piano
-- s.superficie := array di valori
-- se non esiste ancora creiamo
-- una tabella per edificio
-- rispetto al nome
-- es.: Solai.A
if not Solai[s.edificio] then
Solai[s.edificio] = {}
end
-- prendiamoci un riferimento più comodo
-- alla singola tabella edificio
local edificio = Solai[s.edificio]
-- calcoliamo la somma delle superfici
local suppiano = 0
for _, val in ipairs(s.superficie) do
suppiano = suppiano + val
end
-- intenderemo la tabella edificio
-- come un array dove l'indice sarà
-- il numero di piano ed il valore
-- corrispondente, la superficie
if edificio[s.piano] then
edificio[s.piano] = edificio[s.piano] + suppiano
else
edificio[s.piano] = suppiano
end
end
Fatto questo, potremo elaborare decine od anche migliaia di elementi si solaio. Tutti i dati saranno memorizzati nella tabella Solaio Solaio.
A questo punto scriviamo la funzione di reporting che opererà in lettura. Vogliamo stampare per esempio i totali di piano per edificio:
-- report piano/edificio
function reportPianoEdificio()
-- Solai contiene i dati in modo strutturato
-- Al primo livello ci sono le tabelle edificio
local totsup = 0
for nomeEd, arraysup in pairs(Solai) do
print(string.format("Edificio %s: --------------------", nomeEd))
-- stampiamo le superfici piano per piano
local totsupEd = 0
for level, sup in pairs(arraysup) do
totsupEd = totsupEd + sup
print(string.format("Piano %2d, superficie %10.3f", level, sup))
end
totsup = totsup + totsupEd
print("--------------------------------")
print(string.format("Tot. sup. edificio %s: %10.3f", nomeEd, totsupEd))
print("--------------------------------")
end
print("--------------------------------")
print(string.format("Tot. superfici %10.3f", totsup))
print("--------------------------------")
end
In console ottengo questo:
Se volessimo stampare le superfici piano per piano dovremo costruire una funzione in lettura di questo tipo:
-- report per piani
function reportPiani()
-- una tabella per le sup di piano
local suppiani = {}
-- ciclo per singolo edificio
-- primo livello della struttura dati Solaio
for nomeEd, arraySup in pairs(Solai) do
-- ciclo interno di lettura delle sup
for piano, sup in pairs(arraySup) do
if suppiani[piano] then
suppiani[piano] = suppiani[piano] + sup
else
suppiani[piano] = sup
end
end
end
-- stampa
local ts = 0
for level, sup in pairs(suppiani) do
ts = ts + sup
print(string.format("Livello %2d: sup = %10.3f",level,sup))
end
print("--------------------------")
print(string.format("Totale sup = %10.3f",ts))
end
--[[
-- l'output con i soliti dati è questo
Livello 1: sup = 463.233
Livello 2: sup = 463.233
Livello 3: sup = 290.833
--------------------------
Totale sup = 1217.299
--]]
Conclusioni
L’idea proposta è originale? No! Volendo, si possono fare molti esempi tratti dal mondo dell’informatica dove un linguaggio testuale descrive dati strutturati. Con Lua è semplice creare il proprio linguaggio ed elaborare i dati, pensiamo per esempio al caso più complesso riguardante la costruzione dei libretti dei ferri…
Naturalmente, potremo preparare report molto più professionali che non un semplice output in console, per esempio compilando un opportuno sorgente LaTeX per l’uscita in PDF, direttamente con le funzioni Lua di reporting.
Uno svantaggio consiste nella necessità di scrivere qualche linea di codice Lua, ma del resto questo consente la massima libertà di cucire la soluzione sul problema e non è poi così terribilmente difficile. A voi dunque l’onore e l’onere di rendere un po’ più attraente la stesura dei computi metrici!
Note tecniche
Il software occorrente per utilizzare la procedura è il seguente: un editor di testi, consiglio SciTE perché in grado di far eseguire il codice premendo semplicemente il tasto F5, e l’interprete Lua, quindi tutto software libero, gratuito e legalmente installabile anche in ambito professionale, infine un pizzico di fantasia.
Per imparare Lua non vi è niente di meglio del PiL.
Un saluto.
Gli oggetti di Lua
Pubblicato da su 12/10/2011
Click to download the article in the PDF file format
Sommario
Il linguaggio Lua è fondato sull’essenzialità tanto che supporta la programmazione ad oggetti utilizzando quasi esclusivamente le risorse di base e senza mettere a disposizione specifici costrutti. In questa introduzione vedremo come ciò sia stato effettivamente implementato utilizzando l’unica struttura dati disponibile in Lua: la tabella.
Per la comprensione del testo occorre una conoscenza di base sia di Lua, sia dei concetti del paradigma di programmazione ad oggetti, utile per introdurre nei programmi un più elevato livello d’astrazione.
Un rettangolo
Come esempio costruiremo un oggetto per rappresentare un rettangolo, un ente geometrico definibile con due parametri, le lunghezze dei lati, e dotato di una proprietà calcolabile chiamata area. Gli elementi semplici che memorizzano i valori dei lati sono detti campi mentre la proprietà dell’area che ne dipende è detta metodo.
Gli oggetti in Lua si rappresentano con le tabelle che possono contenere valori come numeri ed anche funzioni. Un primo tentativo potrebbe essere questo (sperimentatelo in modo interattivo al terminale per rendervi meglio conto del codice):
-- prima implementazione
Rettangolo = {} -- creazione tabella (oggetto)
-- creazione di due campi
Rettangolo.a = 12
Rettangolo.b = 7
-- un metodo
function Rettangolo.area ()
-- accesso alla variabile 'Rettangolo'
return Rettangolo.a * Rettangolo.b
end
-- primo test
print(Rettangolo.area()) --> stampa 84, OK
print(Rettangolo.a) --> stampa 12, OK
Ci accorgiamo presto che questa implementazione basata sulle tabelle è difettosa in quanto non rispetta l’indipendenza degli oggetti rispetto al loro nome, ed infatti il prossimo test fallisce:
-- ancora la prima implementazione
Rettangolo = {a=12, b=7}
-- un metodo
function Rettangolo.area ()
-- accesso alla variabile 'Rettangolo'
return Rettangolo.a * Rettangolo.b
end
-- secondo test
r = Rettangolo -- creiamo un secondo riferimento
Rettangolo = nil -- distruggiamo il riferimento originale
print(r.a) --> stampa 12, OK
print(r.area()) --> errore!
Il problema sta nel fatto che nel metodo area() compare un particolare riferimento che invece deve poter essere qualunque. La soluzione è introdurre il riferimento all’oggetto come parametro esplicito nel metodo stesso, che chiameremo self, così da poter generalizzarne la validità. Questa idea è quella utilizzata dai linguaggi di programmazione che supportano gli oggetti.
Secondo questo nuovo schema, dovremo riscrivere il metodo area() in questo modo:
-- seconda implementazione
Rettangolo = {a=12, b=7}
-- il metodo diviene indipendente dal particolare
-- riferimento all'oggetto:
function Rettangolo.area ( self )
return self.a * self.b
end
-- ed ora il test
myrect = Rettangolo
Rettangolo = nil -- distruggiamo il riferimento
print(myrect.a) --> stampa 12, OK
print(myrect.area(myrect)) --> stampa 84, OK
Fino ad ora abbiamo costruito l’oggetto sfruttando le caratteristiche della tabella e la particolarità che consente di assegnare una funzione ad una variabile, ma da questo momento entra in scena l’operatore due punti (:), nella chiamata di funzione permettendo di passare il riferimento implicitamente.
Questo operatore è il primo nuovo elemento di Lua inteso per supportare la programmazione orientata agli oggetti, ed eccone una descrizione:
Se si accede ad un metodo memorizzato in una tabella con l’operatore due punti ‘:‘ anziché con l’operatore ‘.‘, sarà aggiunto implicitamente un primo parametro con il riferimento alla tabella stessa chiamato self.
Le seguenti due espressioni sono perfettamente equivalenti per risultato pratico, ma hanno due differenti punti di vista concettuali:
-- operatore punto -- dobbiamo inserire il riferimento -- come primo parametro della funzione print(myrec.area(myrec)) --> stampa 84, OK -- operatore due punti -- il riferimento 'myrec' viene -- passato implicitamente print(myrec:area()) --> stampa 84, OK
Prima classe
Il salto definitivo nella programmazione OOP (Object Oriented Programming) è la costruzione di una classe. Dovremo infatti poter costruire nuovi oggetti senza ogni volta assemblare i campi ed i metodi, insomma serve un qualcosa che faccia da stampo.
Per mantenere la filosofia di essenzialità, Lua non implementa, come invece troviamo in altri linguaggi simili, per esempio Python, una nuova parola chiave class con cui si definisce un prototipo ma, ancora una volta, propone una soluzione basata sulle tabelle, anzi sulle metatabelle.
Metatabelle
Una metatabella è una tabella che contiene funzioni dai nomi prestabiliti che vengono eseguiti quando si verificano particolari eventi, come la richiesta di somma tra due tabelle. Ogni tabella può essere associata ad una propria metatabella e questo consente di creare degli insiemi di tabelle che condividono una stessa aritmetica, giusto per rimanere in nell’esempio precedente.
I nomi di queste funzioni particolari iniziano tutti con un doppio trattino basso, per esempio nel caso della somma sarà richiesta la funzione __add() della metatabella associata, e vengono chiamati metametodi.
Il metametodo più semplice di tutti è __tostring(), che viene chiamato quando alla funzione print() viene data una tabella. In una sessione di terminale scriviamo:
-- un numero complesso
complex = {real = 4, imag=-9}
print(complex) --> stampa: 'table: 0x9eb65a8'
-- un qualcosa di più utile:
function printComplex( c )
local r = string.format("%0.2f",c.real)
if c.imag == 0 then -- numero reale
return "("..r..")"
end
-- numero complesso
local i = string.format("%0.2f",c.imag)
return "("..r..","..i..")"
end
-- creo la metatabella
mt = {}
mt.__tostring = printComplex
setmetatable(complex, mt)
-- riprovo la stampa
print(complex) --> stampa '(4.00,-9.00)'
Il metametodo __index()
Il ‘metametodo’ che interessa per la OOP in Lua è __index(). Esso interviene quando chiamiamo un componente di una tabella che non esiste e che normalmente restituirebbe il valore nil.
Ecco un esempio di codice (nell’immagine la relativa sessione al terminale):
-- una tabella con un campo 'a'
t = {a = 'Campo A'}
print(t.a) --> stampa 'Campo A'
print(t.b) --> stampa 'nil'
Costruiamo invece la funzione __index() e vediamo che succede:
t = {a='Campo A'}
mt = {} -- la metatabella
-- creazione del metametodo
function idx()
return 'Attenzione: campo inesistente!'
end
-- inseriamolo nella tabella mt
mt.__index = idx
-- assegnamo 'mt' come metatabella di 't'
setmetatable(t, mt)
-- adesso riproviamo ad accedere al metodo b
print(t.b) --> stampa 'Attenzione: campo inesistente!'
Di nuovo un rettangolo
Torniamo adesso all’oggetto Rettangolo e creiamo una tabella che fungerà da classe per gli oggetti, assegnando campi e metodi. Per creare nuovi oggetti, creeremo un metodo new() che esaudirà la richiesta assumendo il ruolo di costruttore.
-- il nuovo oggetto Rettangolo
-- campi
Rettangolo = {a=10, b=10}
-- metodo
function Rettangolo:area()
return self.a * self.b
end
-- creazione metametodo
Rettangolo:__index = Rettangolo
-- il costruttore
function Rettangolo:new( o )
-- creazione nuova tabella
-- se non ne viene fornita una
o = o or {}
-- assegnazione metatabella
setmetatable(o, self)
-- restituzione riferimento oggetto
return o
end
-- test ---------------------------
-- rettangolo 10 x 10
r1 = Rettangolo:new()
print(r1.a) --> stampa 10 OK
print(r1:area()) --> stampa 100 OK
-- rettangolo 200 x 10
r2 = Rettangolo:new{a=200}
print(r2.a) --> stampa 200 OK
print(r2:area()) --> stampa 2000 OK
-- rettangolo 12 x 7
r3 = Rettangolo:new{a=12,b=7}
print(r3:area()) --> stampa 84 OK
Come funziona?
Il ‘costruttore’ accetta una tabella che gli viene passata dall’utente, altrimenti ne crea una vuota e la restituisce non appena ne abbia assegnato la metatabella che non è altro che l’oggetto Rettangolo stesso visto che l’operatore due punti passa a new il riferimento implicito a Rettangolo, per cui self punta a Rettangolo.
Nel primo caso del test, viene chiamato il campo a dell’oggetto r1 che non esiste, allora Lua, poiché invece esiste una metatabella associata ad r1, ne chiama il metodo __index, che restituisce semplicemente la tabella Rettangolo stessa. Alla fine viene restituito il campo a di Rettangolo che vale 10.
Stessa cosa succede quando viene chiamata la funzione area con la tecnica dell’operatore due punti, ovvero la funzione chiamata è quella del corrispondente campo in Rettangolo poiché non esiste un campo simile in r1.
Analoghe spiegazioni valgono quando al costruttore viene passata una tabella con un unico campo oppure con tutti e due i campi a e b. Questa volta l’oggetto possiede effettivamente campi propri per i lati ed il metametodo __index non viene considerato.
Questa volta un cerchio
Costruiamo un oggetto Cerchio che consenta di aggiungere una quantità al raggio. Ci renderemo meglio conto di come funziona il meccanismo nascosto ed automatico delle metatabelle:
Cerchio = {radius=0}
Cerchio.__index = Cerchio
function Cerchio:area()
return math.pi*self.radius^2
end
function Cerchio:addToRadius(v)
self.radius = self.radius + v
end
function Cerchio:__tostring()
local frmt = 'Io sono un cerchio di raggio %0.2f.'
return string.format(frmt, self.radius)
end
function Cerchio:new(r)
-- il costruttore attende l'eventuale
-- valore del raggio del cerchio
local o = {}
if r then
o.radius=r
end
setmetatable(o, self)
return o
end
-- test ----------------------
o = Cerchio:new()
print(o)
o:addToRadius(12.345)
print(o)
print(o:area())
Come funziona?
Vorrei soffermarmi su quanto accade nel codice di test. Abbiamo creato un cerchio senza fornire alcun valore per il raggio. Ciò significa che quando lo stampiamo con la successiva istruzione, il raggio è quello dell’oggetto Cerchio, configurato al valore di default nullo, per effetto della chiamata ad __index della metatabella.
Fino a questo momento la tabella dell’oggetto o non contiene alcun campo radius. Cosa succede allora quando viene lanciato il comando o:addToRadius(12.345)?
Il metodo addToRadius() contiene una sola espressione. Come da regola viene prima valutata la parte a destra self.radius + v, dunque il primo termine assume il valore previsto in Cerchio grazie al metametodo, ed alla fine viene creato anche per l’oggetto o il campo radius.
Conclusioni
Non tratteremo in questo post il meccanismo peraltro semplice dell’ereditarietà degli oggetti in Lua. Ciò detto possiamo renderci conto che in Lua si possono implementare strutture con il paradigma della OOP. Lo scopo è quello di fornire all’utente funzionalità più facili da utilizzare e contemporaneamente razionalizzare il codice che dovrebbe essere più facile da gestire nel tempo.
Una volta compreso il meccanismo basato sulle metatabelle, possiamo ideare facilmente e con una certa flessibilità classi di oggetti, ponendo l’attenzione sui metodi e sui campi. In ultimo vi faccio osservare che in Lua non è previsto nessun meccanismo da parte del linguaggio per rendere privati metodi e campi. Scelta coerente per un linguaggio di scripting che mira ad essere essenziale, quindi non ci rimane semplicemente non accedere ai campi, e sarà mantenuta la privacy degli oggetti.
Note tecniche
Per le note tecniche sottolineo che Lua è un software libero multi-piattaforma pertanto è liberamente installabile su sistemi meno diffusi e, ovviamente, anche in Windows, Linux e Mac.
Per sapere qualcosa di più sulle tabelle potete consultare i post di questo stesso Blog, in particolare questo dove trovate un introduzione alle tabelle di Lua.
Per la comprensione dei meccanismi di Lua per la OOP è caldamente consigliato ripetere gli esempi proposti, eventualmente utilizzando la modalità interattiva al terminale (è sufficiente digitare alla linea di comando lua per entrarvi) o lavorando con i file, proponendo altri esempi interessanti (postateli nei commenti mi raccomando…).
Happy Lua!
Collage di precisione di PDF
Pubblicato da su 04/08/2011
Download the article in the pdf file format
Sommario
Con gli strumenti a disposizione di una distribuzione TeX è possibile ottenere un pdf unendo vari pdf di partenza per di più posizionandoli geometricamente nel modo voluto.
I pacchetti LaTeX utilizzati allo scopo sono il potente PGF, forse il pacchetto dall’implementazione più complessa, e il pacchetto graphicx. Con essi non serve altro che decidere la posizione sul foglio bianco degli singoli oggetti pdf contenuti nei rispettivi file.
Giocando giocando
Un altro esempio di utilizzo di LaTeX come strumento di manipolazione di file PDF è l’opposto dell’idea di estrazione dei contenuti di cui ci siamo occupati nel post precedente: a partire da due o più file PDF se ne vuole fare un collage in un nuovo file PDF.
Come per gli altri collage la cosa si prospetta divertente ma già intravedo dei possibili usi nella pratica professionale. Per il nostro esempio ho dapprima costruito due file pdf contenenti un rettangolo blu ed un rettangolo rosso di date dimensioni, e poi li ho uniti sulla stessa pagina ciascuno in una data posizione.
L’esempio è del tutto generale sia nel numero di pdf da unire sia nel loro contenuto.
Nelle immagini seguenti cliccabili per scaricarne il corrispondente file pdf, vi riporto come appaiono i rettangoli d’esempio e come appare il risultato finale dell’unione secondo posizioni geometriche stabilite.
Passiamo la parola quindi al codice, e… buon divertimento!!!
Rettangolo blu
Utilizziamo il potentissimo pacchetto grafico PGF per generare il rettangolo blu, diciamo di 70 x 35 mm con linea a spigoli arrotondati di 5 punti di spessore (in TeX le unità di misura delle lunghezze sono molte e sono tutte interscambiabili):
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz[line width=5pt,color=blue,rounded corners]
\draw (0,0) rectangle (70mm,35mm);
\end{document}
Ecco fatto (inserite il codice in un file di testo, per esempio con Blocco Note, salvatelo su disco e compilatelo con pdflatex, oppure semplicemente caricate il file nell’editor TeXWorks e premete Control+T), sono in tutto sei righe di codice LaTeX che esprimono in maniera diretta esattamente quello che abbiamo descritto in apertura di paragrafo.
Rettangolo rosso
Per il rettangolo rosso semplicemente cambiamo i parametri di colore e dimensione e ripetiamo la veloce procedura di compilazione per generare il secondo pdf che andremo ad unire in un (primordiale) collage.
Un solo nuovo commento al codice ed è questo: vi segnalo l’uso della classe di documento standalone (ringrazio il Professor Enrico Gregorio per avermi segnalato l’esistenza di questa classe sul forum del GuIT), che genera il file pdf nelle esatte dimensioni di pagina necessarie a contenere gli oggetti che creiamo.
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz[line width=5pt,color=red,rounded corners]
\draw (0,0) rectangle (32mm,88mm);
\end{document}
Collage!
Per unire due file pdf l’idea è quella di inserirli in un documento LaTeX attraverso il pacchetto graphicx, come semplici immagini. Tuttavia in questo modo i rettangoli verrebbero inseriti uno sopra l’altro e noi vogliamo qualcosa di più, vogliamo specificarne la posizione geometricamente.
Bene, ricorriamo ancora al pacchetto PGF in combinazione con graphicx, inserendo i file dei rettangoli come fossero il materiale da comporre di un oggetto nodo.
Un nodo PGF può contenere qualsiasi materiale e quindi anche un immagine intera, ed è caratterizzato da un punto di posizionamento (x,y) e da un riferimento di ancoraggio. In questo caso ho scelto l’ancoraggio in basso a sinistra. In altre parole il punto in cui localizziamo il nodo tramite coordinate sul foglio, sarà il punto in cui si troverà la posizione dell’angolo in basso a sinistra dell’immagine (in singolo file pdf).
Ancora, si noti come l’argomento del comando \includegraphics è il nome del file da includere e che questo normalmente va indicato privo di estensione, e che volendo potremo sia ruotare che scalare il pdf da inserire tramite le opzioni angle e scale del comando.
Per quanto riguarda la posizione dei file nell’albero del file system, nell’esempio si è lavorato con i file sorgenti .tex ed il materiale .pdf posizionati tutti nella stessa directory.
Ecco il codice che produrrà il collage di unione rappresentato nell’immagine.
Mi raccomando scaricate i pdf con un click sulle immagini soprastanti per rendervi conto meglio del carattere vettoriale, cioè di massima qualità, dei contenuti grafici.
\documentclass{standalone}
\usepackage{tikz}
\usepackage{graphicx}
\begin{document}
\begin{tikzpicture}[every node/.style={anchor=south west}]
% disegnamo un circoletto di posizionamento delle coordinate
% dell'origine del sistema di riferimento
\draw (0,0) node[circle, draw] {};
\draw (10mm,95mm) node {\includegraphics{blue}}; % insert blue.pdf file
\draw (0,0) node {\includegraphics{red}}; % insert red.pdf file
\end{tikzpicture}
\end{document}
Per oggi mi fermo qui, alla prossima!
Aprire finestre sul PDF
Pubblicato da su 02/08/2011
Sommario
Lavoreremo con i linguaggi Lua e LaTeX per estrarre finestre da un qualsiasi file in formato PDF.
Capita infatti di voler riportare in un nostro documento una tabella, un grafico, un immagine o qualsiasi altro materiale contenuto in un secondo file PDF.
In questo post impareremo ad estrarre rettangoli qualsiasi da una qualsiasi pagina PDF, e l’utilità sta nel fatto che possiamo ottenere le “finestre” nello stesso formato pdf mantenendo la qualità vettoriale dell’originale.
Finestre
Vogliamo ritagliare una finestra rettangolare da un file pdf (che chiameremo originale.pdf). Per esempio, a pagina 21 è riportata una tabella che vogliamo inserire in una presentazione o in un nostro articolo senza perdere in qualità rispetto all’originale.
L’idea per estrarre il contenuto così definito, si basa sulle abilità di manipolazione dei file pdf del sistema TeX che, grazie al pacchetto graphicx, è in grado di ritagliare rispetto alla pagina la finestra voluta.
Dobbiamo quindi avere a disposizione il file pdf contenente quell’unica pagina in cui si trova il materiale da ritagliare e per far questo, ancora una volta ci rivolgeremo ad un pacchetto LaTeX chiamato pdfpages.
L’idea di estrarre la particolare pagina e ritagliarla successivamente, comporta quindi la scrittura e la compilazione di due file sorgenti LaTeX. Ed ecco che entra in scena Lua che ci facilita questo compito.
Estrarre una pagina
Assumendo i dati espressi precedentemente, lo script Lua seguente crea un file .tex opportuno, lo compila con il programma pdflatex e cancella i file temporanei lasciando nella cartella, accanto al file pdf originale (che viene soltanto utilizzato in lettura), il file tmppage21.pdf.
Da notare l’uso del delimitatore di stringa delle doppie parentesi quadre e l’uso della funzione string.format() della libreria standard di Lua, con cui creiamo il sorgente attraverso gli opportuni segnaposto (il numero della pagina ed il nome del file pdf originale).
#!/usr/bin/lua
-- script di estrazione pagina da un file pdf
-- dati
local page = 21
local pdffile = "originale"
-- contenuto del sorgente LaTeX
local extractpage = [[
\documentclass{minimal}
\usepackage{pdfpages}
\begin{document}
\includepdf[pages=%s]{%s}
\end{document}
]]
-- creo il file sorgente tex che estrae
-- la pagina voluta in un secondo file pdf
local pg = tostring(page)
local fn = "tmppage"..pg
local fl = assert(io.open(fn..".tex", "w"))
fl:write(string.format(extractpage, pg, pdffile))
fl:close()
-- compilazione file tex
os.execute("pdflatex -interaction=nonstopmode "..fn)
-- cancellazione file temporanei
os.remove(fn..".log")
os.remove(fn..".aux")
os.remove(fn..".tex")
Ritagliare una pagina
Ecco il secondo passaggio: ritagliare dalla pagina una finestra pdf. Si può risolvere con un secondo script Lua, simile al precedente, a cui stavolta occorre passare le coordinate x ed y dell’angolo in basso a sinistra e quelle dell’angolo in alto a destra del box (il sistema di riferimento ha l’origine nell’angolo inferiore sinistra del foglio).
Per fare un esempio, immaginiamo di voler estrarre il box della metà superiore di una pagina A4 (210mm x 297mm): le coordinate saranno per il vertice inferiore sinistro ll=(x=0mm, y=148.5mm) e per il vertice in alto a destra ur=(x=210mm, y=297mm).
Questa volta faremo uso della classe standalone, che ha il pregio di produrre una pagina della stessa dimensione del contenuto, e del pacchetto graphicx con cui si inserisce l’immagine che andremo a ritagliare con le coordinate (notate l’opzione viewport):
#!/usr/bin/lua
-- script di ritaglio finestra pdf
-- posizione angoli della finestra
local ll = {x="15mm", y="35mm"} -- ll=lower/left
local ur = {x="195mm", y="72mm"}-- ur=up/right
local page = 21
local ritpage = [[
\documentclass{standalone}
\usepackage{graphicx}
\begin{document}
\includegraphics[viewport=%s %s %s %s]{%s}
\end{document}
]]
-- creo il file sorgente tex di ritaglio
local pg = tostring(page)
local fn = "tmppage"..pg
-- creo il secondo file LaTeX per il ritaglio
local fnrit = "page"..pg..pdffile
local flrit = assert(io.open(fnrit..".tex", "w"))
flrit:write(string.format(ritpage, ll.x, ll.y, ur.x, ur.y, fn))
flrit:close()
os.execute("pdflatex -interaction=nonstopmode "..fnrit)
-- cancellazione file
os.remove(fn..".pdf")
os.remove(fnrit..".log")
os.remove(fnrit..".aux")
os.remove(fnrit..".tex")
Linguaggio
Fino ad ora la cosa è stata abbastanza rudimentale, almeno come interfaccia utente, infatti i precedenti paragrafi spiegano i concetti ed un implementazione di base, ma siamo in grado di lavorare con un linguaggio più ad alto livello creando una piccola libreria Lua.
Con essa potremo ritagliare oggetti da più file pdf o da più pagine dello stesso documento.
Per il momento tuttavia, lasceremo questa libreria ad un prossimo futuro, cominciando il divertimento dalla costruzione del linguaggio. Non vi rimane che sperimentare questa soluzione e fare le vostre considerazioni.
Note tecniche
Per svolgere le procedure indicate è necessario aver un po’ di dimestichezza con LaTeX (in particolare con i concetti di base dei pacchetti e con il meccanismo di compilazione), ed almeno saper eseguire sul sistema uno script in Lua.
Se siete alle prime armi la prima cosa da fare è installare una distribuzione TeX e leggere una guida di base.
Alla prossima, Ciao.
Il declino di TeX e LaTeX
Pubblicato da su 28/06/2011
Note alla lettura:
l’analisi dei dati su cui si basa questo post (che comunque non verrà modificato) non è corretta. Leggere i commenti per scoprire l’approccio corretto.
Scende nel mondo la diffusione di TeX e LaTeX
Consultando il volume in ricerche che si svolgono nel mondo attraverso Google si nota un costante calo di interesse dal 2004 ad oggi. Il dato sembra essersi stabilizzato in una lenta ed inesorabile discesa a partire dalla metà del 2005, come dimostra il grafico sottostante:
Naturalmente il volume delle ricerche non è equamente distribuito nel mondo ma si concentra in alcuni paesi come Repubblica Ceca, Giappone e Germania, come possiamo costatare nella mappa, mentre è vistosa la diminuzione dei volumi proprio nella patria di TeX, ovvero gli Stati Uniti.
Conclusioni
I volumi di ricerca nel web sono indicatori indiretti ma visto l’importanza del web nella diffusione di TeX e compagni e l’aumento della diffusione di internet e quindi degli utenti potenziali, se ne deduce che siamo di fronte ad un dato assai rivelatore.
Potrei anche banalmente aver sbagliato ad utilizzare il servizio di Google Insights, ma l’impressione è un inarrestabile declino di questi strumenti di tipografia digitale.
La causa principale credo sia la quantità di tempo per imparare LaTeX e scrivere un documento LaTeX, rispetto ad altri programmi, che fa diminuire gli utilizzatori e questo produce un ulteriore effetto negativo poiché così diminuisce la qualità tipografica dei documenti e quindi aumenta nel mondo l’accettazione di un minor livello qualitativo della documentazione che incentiva a sua volta l’abbandono di TeX e LaTeX.
Il tempo disponibile per la redazione dei documenti è sempre meno e questo gioca a mio avviso un ruolo fondamentale per spiegare la tendenza registrata che può essere almeno contenuta solo se LaTeX sarà capace di evolvere in un linguaggio molto più potente. Gli sviluppatori di TeX e LaTeX possono trarne le loro conclusioni…
Plot della funzione Gamma con matplotlib
Pubblicato da su 26/05/2011
Scarica l’articolo in formato pdf
Abstract
Utilizzando alcune librerie Python di calcolo numerico utilizzeremo il pacchetto matplotlib per disegnare il grafico della funzione Gamma di Eulero. Questa infatti è la funzione scelta per introdurre questo interessante ambiente di computazione e visualizzazione, integrato e circoscritto all’interno del linguaggio Python.
Lo scopo è quello di mostrare le capacità di questo software libero e dare un idea delle caratteristiche di un linguaggio testuale basato su Python per il calcolo e la visualizzazione tecnico-scientifica.
Numeri, numeri ed ancora numeri per Python
Il linguaggio Python è particolarmente portato per i numeri. Lo dimostra questo piccolo e classico esempio in cui si calcola il fattoriale di un numero intero elevato.
Il fattoriale non è altro che il prodotto di tutti i numeri da 1 ad n e può essere calcolato da una funzione ricorsiva. Ecco l’esempio di codice:
def fact(n):
if n==1:
return 1
return n * fact(n-1)
print(fact(100))
Salvato il file contenente il codice con il nome fact.py , per eseguirlo aprire una finestra di terminale e digitare $ python fact.py. Sarà immediatamente mostrato a video un numero di 158 cifre. Nello screenshot seguente vi ho riportato l’esecuzione di fact.py posizionato nel mio caso nella cartella Scrivania:
È preferibile riscrivere il codice senza copiarlo per rendersene meglio conto, inoltre ricordatevi che se non vogliamo digitare il percorso completo del nome del file da eseguire, la directory di lavoro del terminale o della console di Windows, deve essere la stessa di quella in cui si trova il file. Per settare la directory di lavoro, e quindi spostarsi nell’albero del file system, basta usare il comando cd (che sta per change directory) seguito dal nome della directory.
Ultima cosa da ricordare, questa volta agli utenti Linux, è l’assegnazione agli script Python dei permessi di esecuzione, per esempio semplicemente spuntando il flag Esecuzione nella scheda Permessi del dialogo Proprietà del file stesso.
Preparazione del sistema
In Ubuntu installare i file necessari per svolgere l’esercizio proposto è semplice perché l’interprete Python è pre-installato di default mentre le librerie matplotlib e scipy si installano sul sistema con i due comandi (la libreria numerica numpy è una dipendenza obbligatoria del pacchetto python-matplotlib e non è necessario richiederne l’installazione esplicitamente):
$ sudo apt-get install python-matplotlib $ sudo apt-get install python-scipy
Per gli utenti Windows serve un po’ più di tempo ma mutatis mutandis, non è difficile seguire le procedure d’installazione di Python e delle librerie numeriche indicate. La documentazione è ottima.
matplotlib plotting example
La libreria matplotlib funziona allo stesso modo di Matlab: la curva di una funzione è disegnata unendo un insieme di punti del piano le cui coordinate sono definite da un set di valori del dominio della funzione e dai corrispondenti valori calcolati nel codominio.
Quello che dobbiamo fare è scrivere un programma in Python che utilizzi motori numerici e di visualizzazione sotto forma di librerie
Consideriamo un esempio di plot di funzione per . Il set di valori sull’asse x saranno i 100 punti egualmente intervallati da 0 a
: setx = np.linspace(0, 2*np.pi, 100), dove np è l’oggetto che fa riferimento alla libreria numpy definito con un precedente import numpy as np (il nome assegnato è una sorta di scorciatoia).
Il plottaggio avviene utilizzando il metodo plot dell’oggetto matplotlib.pyplot, a cui passiamo il set di valori sull’asse x ed i corrispondenti ordinate sull’asse y calcolate con la funzione seno al quadrato: plt.plot(setx, np.sin(setx)**2) dove plt è l’oggetto che fa riferimento alla libreria matplotlib.pyplot definito con import matplotlib.pyplot as plt.
Non rimane che esercitarci sul codice completo del programma che genererà un file pdf, quindi un file di qualità vettoriale che scalato non perderà risoluzione:
#!/usr/bin/python
import numpy as np
import matplotlib.pyplot as plt
setx = np.linspace(0.0, 2*np.pi, 100)
plt.plot(setx, np.sin(setx)**2)
plt.savefig('sen2plt.pdf')
Sul manuale troverete le usuali proprietà per personalizzare il grafico come etichette compreso testo in codice LaTeX per il typesetting matematico, spessori e colori, griglie, ecc. Le lavorazioni sui sorgenti assomigliano operativamente a quelle degli altri tool di visualizzazione come Matlab stesso o Gnuplot, ma con i vantaggi di un linguaggio ad oggetti intuitivo. Occorre solo l’abitudine ad orientarsi tra i moduli delle librerie.
Esiste anche la possibilità di visualizzare il grafico in una finestra grafica. Non seguiremo questa strada perché interattiva per l’utente e quindi poco adatta ad essere descritta in una guida. Dico solo che per usufruire di questa modalità basta sostituire nell’ultima istruzione il metodo savefig(‘nomefile’) con show().
The Gamma function
La funzione fu trovata da Eulero su sollecitazione di Christian Goldbach e rappresenta il fattoriale di un numero reale (od anche complesso). Si tratta quindi di una sorta di estensione del calcolo del fattoriale di un numero intero infatti per essi sussiste la seguente relazione:
La definizione standard della funzione Gamma di Eulero è la seguente:
Per conoscere ulteriori dettagli matematici visitate la classica pagina di Wikipedia o quella di MathWorld.
matplotlib plots Gamma
La funzione è stata implementata nel modulo speciale della libreria scipy. Il nostro obbiettivo meno ambizioso quanto a visualizzazioni 3D nel piano complesso, è tracciare il grafico per un dominio reale ed evidenziare i punti sulla curva corrispondenti ai fattoriali dei numeri interi.
Ma la funzione non si domina facilmente. Giustamente matplotlib non disegna punti a distanza infinita, quindi occorre gestire le discontinuità ovvero i valori infiniti che essa assume per 0 e per i numeri interi negativi, appiattendo i valori della funzione quando superano un range scelto opportunamente e molto al di fuori dei limiti del grafico (questo per la verità va fatto per qualsiasi altra funzione con asintoti verticali nell’intorno dei quali i valori diventano ovviamente elevatissimi).
Poi occorre infittire molto i punti in cui calcolare altrimenti nel grafico compariranno dei rami parassiti nei pressi degli asintoti verticali.
Passo infine la parola al codice:
#!/usr/bin/python
# import delle librerie necessarie
import numpy as np
from scipy.special import gamma as Gamma
import matplotlib.pyplot as plt
# definizione dei limiti del grafico
# per il facile 'aggiustamento'
x0, x1 = -5.0, 5.2
y0, y1 = -6.5, 7.0
# dominio lineare sull'asse x
x = np.linspace(x0, x1, 50000)
# dominio numeri interi
xx = [2,3,4]
# creazione dei vettori di ordinata
y = Gamma(x)
yy = Gamma(xx)
# 'gestione' delle discontinuita
ulim = 100*y1
llim = 100*y0
y[y>ulim] = np.inf
y[y<llim] = -np.inf
# plottaggio della Gamma
plt.plot(x, y)
# aggiunta dei punti notevoli del fattoriali
# l'opzione 'ro' si riferisce a singoli caratteri:
# r = red , o = pallino
plt.plot(xx, yy , 'ro')
# limiti sugli assi
plt.axis([x0, x1, y0, y1])
# tracciamento di una griglia base
plt.grid()
# creazione del file pdf con il grafico
plt.savefig('gammaplt.pdf')
Conclusioni
Secondo me bene si fa a tener conto delle librerie Python introdotte in questo post. Basta dare un occhiata ai numerosi talk ai meeting europei di Scipy.
Impara l’arte e mettila da parte…
Inviare pdf in modo sicuro
Pubblicato da su 22/05/2011
Attenzione: la procedura di messa in sicurezza di un pdf utilizzando la cifratura interna sembra essere non molto sicura.
Provvederò quindi ad aggiornare il post. Grazie.
Scarica l’articolo nel formato pdf per la stampa
Il problema
Con la diffusione di internet lo scambio di documenti avviene sempre più spesso tramite il servizio base della posta elettronica. Tuttavia i messaggi e-mail non sono sicuri ed i documenti che un tempo venivano consegnati o ritirati a mano con la sicurezza della fisicità, oggi possono essere letti da terzi con la violazione dei messaggi digitali che transitano su connessioni internet non protette.
Pensiamo al caso di una piccola azienda od un artigiano che ogni mese riceve nel formato PDF i moduli di pagamento F24 od i cedolini delle buste paga dei propri dipendenti dall’ufficio del commercialista.
Quasi sicuramente il testo del messaggio e-mail conterrà la classica dicitura sulla protezione dei dati personali secondo la legge sulla privacy, ma i documenti PDF allegati saranno invariabilmente in chiaro!!!
Cosa possiamo fare? Tornare a visitare i vari uffici per raccogliere di persona i documenti cartacei? Saremo costretti a prendere l’auto impiegando tempo ed inquinando ulteriormente l’ambiente urbano, anche se ne gioverebbero i rapporti interpersonali (il computer ci fa vivere in un mondo cerebrale…).
Una soluzione
La soluzione più robusta è quella di blindare il messaggio di posta elettronica garantendo non solo l’integrità dell’e-mail ma anche la sicurezza sull’identità del mittente. Ci si può rivolgere per esempio a software come GNUPG che fa esattamente quello che serve e di cui potete trovare una splendida guida in italiano di Mario Pascucci sempre valida e completa sia per Windows che per Linux.
Per usare GNUPG è necessario creare una coppia di chiavi, quella pubblica e quella privata, creare una password phrase per la sicurezza locale del sistema, utilizzare il sistema di server per l’upload della chiave pubblica, ed accertarsi fisicamente che la chiave pubblica del proprio corrispondente appartenga effettivamente a lui. Da quel momento sarà possibile crittografare i messaggi e pure firmarli digitalmente.
Tuttavia questo sistema mi sembra un po’ troppo. Direi quindi di sacrificare un po’ di sicurezza ma di acquistare semplicità concettuale rinunciando alla certezza del mittente del messaggio.
Una soluzione più comoda
Assumendo di voler trasmettere solo file PDF, li blinderemo con l’utility libera pdftk. Ecco quel che dovremo fare: preparare i due PC di mittente e destinatario e costruire una password robusta nota solo ad entrambi e cifrare/decifrare i documenti.
Se solo al mittente ed al destinatario è nota la password e se il destinatario riesce a decifrare correttamente il file pdf contenuto nel messaggio, allora possiamo ragionevolmente supporre che solamente i due soggetti hanno avuto accesso al messaggio (e quindi la comunicazione è sicura), e che il nostro mittente sia effettivamente colui che ha spedito il messaggio.
Diversamente vorrà dire che la password sarà stata violata in qualche modo. Dunque è essenziale che la password sia robusta e nota solo agli interessati, altrimenti tutta la procedura verrà inficiata.
Preparare il PC
Per preparare il PC basta installare pdftk. Assumendo che il sistema sia un pc Ubuntu è sufficiente digitare il comando:
sudo apt-get install pdftk
Anche per gli utenti Windows l’installazione è semplice: è sufficiente seguire la procedura descritta alla pagina ufficiale del pacchetto (si tratta di scaricare un file e scompattarlo in una cartella opportuna).
Scambiarsi la password
Una volta costruita una password robusta, per esempio ‘g456Wsa+dh’, annotatela su un foglio e recatevi di persona dal vostro corrispondente. Questo passaggio è essenziale perché come già detto, dalla sicurezza di questa password dipenderà la sicurezza di tutti i vostri documenti contenuti nei messaggi e-mail.
Se il corrispondente è geograficamente lontano potreste ricorrere al telefono od alla posta, con le modalità fantasiose che si possono inventare divertendosi (per esempio una specie di caccia al tesoro in cui la password viene suddivisa in due o tre tronconi e trasmessa con mezzi fisici diversi assieme alle istruzioni di montaggio, ma solo se il corrispondente mostra spirito goliardico).
Procedura operativa: cifratura
Sia mydoc.pdf il file pdf da trasmettere allora per cifrarlo a 128 bit aprite il Terminale (o la finestra di console di Windows) e digitate il comando:
pdftk mydoc.pdf output cryptmydoc.pdf owner_pw g456Wsa+dh user_pw IlMioNome
Fatto.
Si tratta di una normale sintassi per utility a linea di comando dove gli argomenti separati da spazi seguono il nome del comando da lanciare e sono strutturati in un primo gruppo costituito dal file di input e da un secondo gruppo composto dal nome da dare al file di output con le opzioni, separati dalla con la chiave ‘output’. Volendo elencare la sintassi potremo costruire l’elenco degli argomenti:
1 – il nome del file pdf da cifrare (nel nostro esempio mydoc.pdf);
2 – la chiave ‘output’;
3 – il nome del file cifrato (tipo ‘crypt_mydoc.pdf’) al quale va applicata la protezione con password (opzione owner_pw seguita dalla password) e l’attribuzione all’utente (opzione ‘user_pw’ seguita dal nome utente).
Procedura operativa: decifratura
Dal punto di vista del destinatario, una volta ricevuta l’e-mail con il documento pdf cifrato, potrà o aprirlo direttamente inserendo la password o riportarlo in chiaro per un utilizzo successivo più agevole, con il comando:
pdftk cryptmydoc.pdf input_pw g456Wsa+dh output mydoc.pdf
Finito.
Anche per questo comando un commento: il primo gruppo di argomenti è costituito dal file da decifrare seguito dall’opzione ‘input_pw’ a cui far seguire la password (altrimenti pdftk non potrà operare sul documento), mentre il secondo gruppo sempre separato dal primo con la chiave ‘output’, è semplicemente il nome da dare al pdf decifrato.
Alcuni screenshot dell’operazione
Ecco cosa viene mostrato se apriamo con Evince, il lettore di pdf predefinito in Ubuntu, un file pdf cifrato:
Nel seguente screenshot potete osservare una sessione di terminale per la cifratura ed una decifratura di un file pdf in Linux Ubuntu:
Nell’immagine seguente invece vi ho riportato il dialogo di proprietà di Acrobat Reader relativo ad un file cifrato con pdftk dove è chiaramente leggibile che ci troviamo davanti un documento blindato con cifratura a 128bit.
Evoluzione
Naturalmente vi sono modi di rendere il processo più comodo ed user friendly che convengono solo se si hanno un gran numero di file da gestire con destinatari diversi ognuno con password distinte. Penso per esempio ad un utility di spedizione ad interfaccia grafica che sfrutti un database, cifri i pdf, esegua gli invii dei documenti per e-mail e registri le trasmissioni. Con qualcosa del genere l’intera procedura diventerebbe non solo molto più sicura e professIonale ma anche molto più rapida ed efficiente rispetto alle soluzioni manuali caso per caso in chiaro.
Per approfondimenti sulle opzioni di cifratura offerte da pdftk consultate il suo manuale, mentre per il resto potete commentate il post per riportare esperienze e suggerimenti.
Bene, direi che siamo giunti al termine per cui vi saluto augurandovi buon lavoro!!!
Un brindisi matematico…
Pubblicato da su 21/05/2011
Una risposta estremamente difficile
Ecco la domanda:
Se brindano n persone quanti cin faranno i loro bicchieri?
Una domanda certamente fondamentale per il proseguo la cui risposta necessita di impegno estremo.
Sia la funzione che fornisce il risultato, allora considerando il punto di vista di un singolo partecipante al brindisi, egli effettuerà un cin cin con tutti gli altri ovvero
tocchi e lui potrà dirsi soddisfatto. Rimarranno allora i brindisi seguenti:
Applicando lo stesso ragionamento al gruppo rimanente, di fatto un ragionamento ricorsivo, dovranno essere ancora compiuti brindisi.
Si finirà di brindare quando rimarranno due sole persone che faranno un unico tocco, allora:
Il risultato è che il numero dei brindisi in un gruppo di n persone è la somma dei numeri da 1 a . Per esprimere la somma con una semplice espressione seguiamo il ragionamento del giovanissimo Gauss.
Su n, sommiamo il primo termine, ovvero il numero 1 e l’ultimo termine quindi n ed otteniamo naturalmente . Così facciamo per il secondo ed il penultimo termine della somma
. Alla fine la somma è sempre il termine
moltiplicato per le coppie il cui numero è
ovvero:
Tornando al numero dei brindisi fra n persone, dovremo sostituire alla relazione precedente ad il termine
ottenendo il risultato tanto atteso:
Altro percorso di dimostrazione
La cosa si fa più interessante se immaginiamo i brindisi tra le persone come rami di relazioni. questo punto di vista non si riferisce alla singola persona come quello precedente ma all’insieme intero delle relazioni.
Tutte le relazioni tra n persone, possono essere rappresentate in una griglia quadrata dove le righe e le colonne sono riferite a tutte le singole persone.
Così per esempio la cella della riga relativa alla persona A e della colonna relativa alla persona B, rappresenta il brindisi tra la A e B.
Ogni cella rappresenta una relazione di brindisi ma dobbiamo escludere quelle che si trovano sulla diagonale principale della griglia (quelle in cui la persona sulla riga è la stessa di quella della colonna) perché è escluso che si possa contare anche il brindisi con se stessi.
Delle celle rimanenti ne possiamo considerare tuttavia solo la metà perché se esiste la relazione di brindisi esisterà anche la relazione
sulla griglia ma delle due ne possiamo conteggiare solo una perché si tratta delle stesso brindisi (ramo di relazione non orientato).
Una rappresentazione grafica della griglia è riportatata di seguito per 5 persone denominate da A a E, dove col pallino rosso sono evidenziate le celle di auto-relazione mentre con i quadratini verdi e blu sono evidenziate le relazioni doppie da contare solo una volta.
Alla fine ritroviamo elegantemente la relazione per il conteggio dei brindisi tra n persone:
Con questo punto di vista il numero dei brindisi non è altro che il numero delle celle della griglia che si trovano sotto oppure sopra alla diagonale principale (il numero dei quadratini di uno stesso colore se ci riferiamo all’immagine presentata che potete scaricare nel formato pdf da qui, se invece vi interessa il codice che l’ha generata consultare questo post sul forum del GuIT).
Epilogo
Se alla prossima festa siete in 12 preparatevi dunque a 66 rintocchi di bicchieri!
Alla salute!!!






















Recent comments