mercoledì 24 settembre 2008

Perl e lo zen

Di lavoro faccio il programmatore e ogni tanto mi balocco, nel tempo libero, con il mio coltellino svizzero: perl.

Oggi voglio mostrare come sia possibile con un istruzione piuttosto semplice fare una cosa che nei linguaggi tipo Java o C/C++ è molto tediosa.

Supponiamo di dover generare una sequenza di numeri del tipo

1 0
2 1500
3 3000
4 6000
5 15000
6 30000
7 50000
8 100000
9 200000
10 300000
11 400000
12 500000
13 600000
14 700000
15 800000
16 900000
17 1000000
18 1100000
19 1200000
20 1300000
21 1400000
22 1500000
23 1600000
24 1700000
25 1800000
26 1900000
27 2000000
28 2100000
29 2200000
30 2300000
31 2400000
32 2500000
33 2600000
34 2700000
35 2800000
36 2900000

(chi indovina cosa potrebbero rappresentare? )

cerchiamo di capire come potrebbe essere risolto. Innanzi tutto la struttura più adatta che viene in mente è quella di un array in cui in ogni posizione è occupata dal valore sulla seconda colonna.

Una soluzione banale è dichiarare un array che contenga tutti i valori.

@array=(0, 1500, 3000, 6000, 15000, 30000, 50000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000)

ma la cosa oltre che essere lunghina è poco perlosa.

Ecco come potremmo procedere dopo aver fatto la seguente osservazione: la sequenza che va da 0 fino al valore 100000 è irregolare mentre successivamente raddoppia sempre.

Dividiamo quindi il problema in 2 sotto problemi la prima e la seconda parte della stringa

@prima=(0, 1500, 3000, 6000, 15000, 30000, 50000)

e

@seconda=(100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000)

per la prima parte c'è poco da fare però può essere scritta nella forma

@prima=qw(0 1500 3000 6000 15000 30000 50000)

per risparmiare leggermente qualche digitazione (e per scriverla anche in modo un po più leggibile) altrimenti addirittura

@prima=map{$_*100} qw(0 15 30 60 150 300 500)

in cui si scrivono ancora meno caratteri grazie alla funzione map che consente di eseguire un'operazione su ogni elemento di una stringa e in questo caso moltiplica ogni elemento generato da qw(0 15 30 60 150 300 500) per 100.

Sfruttando quest'ultima peculiarità basta osservare che l'array @seconda non è altro che una successione di valori da 1 a 29 moltiplicati per 100000.
quindi posso scrivere

@secondo=map{$_*100_000} (1..29)

ed anche il secondo elemento è generato.

Quindi per concludere la lista dei valori viene generata da questa unica istruzione:

@array=(map{$_*100} qw(0 15 30 60 150 300 500),map{$_*100_000} (1..29))

un bel risparmio ...

Nessun commento: