Approfittando della giornata innevata e di un po’ di relax ecco un piccolo esercizio in bash per “disegnare” su terminale utilizzando semplicemente spazi e cancelletti (#).
Anzitutto creiamo una serie di funzioni che ci consentano di disegnare come se si stesse lavorando su un piano cartesiano. A tale proposito cerchiamo di disegnare una parabola con la seguente funzione:
Prima di proseguire installiamo il basic calculator, che ci permetterà di effettuare calcoli matematici elementari in bash (non è indispensabile, né l’unico modo, ma per quello che vogliamo fare dovrebbe essere sufficiente):
1 |
sudo apt-get install bc |
Una volta installato creiamo un file parabola.sh
1 |
sudo nano parabola.sh |
Ed inseriamo dentro il seguente codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#!/bin/bash # puliamo il terminale clear # stabiliamo il centro degli assi cartesiani Cx=30 Cy=30 # disegna in posizione x, y accetta due parametri disegna() { # moltiplichiamo la x per 2 per compensare la dimensione # dei font del terminale X=$(($Cx*2+$1*2)) Y=$(($Cy-$2)) Xmax=$(($Cx*4)) Ymax=$(($Cy*2)) # stampiamo a video nella posizione x, y # un carattere asterisco * se si trova entro i limiti del grafico if [ $X -ge 0 ] && [ $X -le $Xmax ] && [ $Y -ge 0 ] && [ $Y -le $Ymax ]; then echo -ne "\e[${Y};${X}H${3}" fi } echo echo echo # disegniamo per primo l'asse y, in modo che eventuali punti # sovrascrivano i simboli dell'asse for((y=-$Cy; y<$Cy; y++)); do disegna 0 $y "." done # percorriamo adesso tutti i valori interi di x for((x=-$Cx; x<$Cx; x++)); do dx=$(($x)) #calcoliamo y = x*x - 5 dy=$(($x*$x-5)) # già che ci siamo disegniamo l'asse x disegna $dx 0 "." # disegniamo la funzione disegna $dx $dy "#" done # aggiungiamo degli spazi alla fine for((i=0; i<$Cy; i++)); do echo done |
Ricordiamoci di rendere lo script eseguibile digitando:
1 |
sudo chmod a+x parabola.sh |
Ed eseguiamolo:
1 |
./parabola.sh |
Il risultato di questa operazione dovrebbe dare qualcosa di simile a questo:
Faccio notare che la funzione disegna accetta come terzo parametro il tipo di carattere che vorremo utilizzare.
Adesso che abbiamo verificato che il disegno sul piano cartesiano funziona possiamo scrivere la serie di istruzioni necessarie a generare il nostro simpatico fiocco di neve. Le funzioni matematiche necessarie le ho prese da qui: Snowflake Math.
Inutile dire che si potrebbero usare moltissime altre funzioni, oppure divertirci con un calcolo frattale. Notiamo però che il disegno accetterà solo valore naturali interi, quindi il risultato sarà comunque un po’ impreciso. Infatti non possiamo aumentare la densità di caratteri sul terminale, potendo così apprezzare altri dettagli. Lo script sarà dunque questo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
#!/bin/bash clear # stabiliamo il centro degli assi cartesiani per il # disegno della funzione neve Cx=30 Cy=30 # disegna in posizione x, y # accetta due parametri disegna() { # moltiplichiamo la x per 2 per compensare # la dimensione dei font del terminale X=$(($Cx*2+$1*2)) Y=$(($Cy-$2)) Xmax=$(($Cx*4)) Ymax=$(($Cy*2)) # stampiamo a video nella posizione x, y # un carattere asterisco * se si trova entro # i limiti del grafico if [ $X -ge 0 ] && [ $X -le $Xmax ] && [ $Y -ge 0 ] && [ $Y -le $Ymax ]; then echo -ne "\e[${Y};${X}H#" fi } # equazione, x, min, max # 1 2 3 4 fiocco() { if [ $2 -ge $3 ] && [ $2 -le $4 ]; then dy=0 dy=$(bc -l <<< $1) dy=${dy%%.*} if [ -z "${dy// }" ]; then dy=0 fi disegna $2 $dy fi } echo echo echo for((y=-$Cy; y<$Cy; y++)); do dy=$(($y)) if [ $y -ge -3 ] && [ $y -le 0 ]; then dx=-21 disegna $dx $dy fi done for((x=-$Cx; x<$Cx; x++)); do dx=$(($x)) fiocco "-7/4*($x-3)+8" $x -1 3 # 1 fiocco "3/2*($x-3)+8" $x 3 5 # 2 fiocco "-8/5*($x-5)+11" $x 0 5 # 3 fiocco "19" $x 0 3 # 4 fiocco "-5/3*($x-6)+14" $x 3 6 # 5 fiocco "5/3*($x-6)+14" $x 6 9 # 6 fiocco "-1/2*($x-9)+19" $x 9 11 # 7 fiocco "5/3*($x-11)+18" $x 8 11 # 8 fiocco "13" $x 8 15 # 9 fiocco "3/2*($x-13)+10" $x 13 15 # 10 fiocco "10" $x 7 13 # 11 fiocco "3/2*($x-5)+7" $x 5 7 # 12 fiocco "7" $x 5 12 # 13 fiocco "6/3*($x-9)+1" $x 9 12 # 14 fiocco "1" $x 9 12 # 15 fiocco "7/4*($x-16)+8" $x 12 16 # 16 fiocco "-2/2*($x-8)+16" $x 16 18 # 17 fiocco "5/3*($x-15)+1" $x 15 18 # 18 fiocco "1" $x 15 21 # 19 fiocco "21" $x -2 1 # 20 fiocco "-2" $x 16 21 # 21 fiocco "-5/3*($x-16)-2" $x 16 19 # 22 fiocco "1/3*($x-19)-7" $x 16 19 # 23 fiocco "-6/3*($x-16)-8" $x 13 16 # 24 fiocco "-2" $x 9 13 # 25 fiocco "-6/4*($x-9)-2" $x 9 13 # 26 fiocco "-8" $x 5 13 # 27 fiocco "-3/3*($x-5)+8" $x 5 8 # 28 fiocco "-11" $x 8 14 # 29 fiocco "-3/2*($x-14)-11" $x 14 16 # 30 fiocco "-14" $x 9 16 # 31 fiocco "-4/3*($x-9)-14" $x 9 12 # 32 fiocco "$x-12+18" $x 10 12 # 33 fiocco "-7/3*($x-7)-13" $x 7 10 # 34 fiocco "7/3*($x-7)-13" $x 4 7 # 35 fiocco "-20" $x 2 4 # 36 fiocco "7/3*($x-5)-13" $x 2 5 # 37 fiocco "-6/2*($x-3)-7" $x 3 5 # 38 fiocco "9/3*($x-3)-7" $x 0 3 # 39 fiocco "-6/4*($x+4)-10" $x 9 13 # 40 fiocco "3*($x+4)-10" $x -5 -4 # 41 fiocco "-6/3*($x+5)-13" $x -5 -2 # 42 fiocco "3/2*($x+2)-19" $x -4 -2 # 43 fiocco "-6/3*($x+7)-16" $x -7 -4 # 44 fiocco "5/2*($x+7)-16" $x -9 -7 # 45 fiocco "-1/2*($x+11)-20" $x -11 -9 # 46 fiocco "5/2*($x+9)-15" $x -11 -9 # 47 fiocco "-15" $x -14 -9 # 48 fiocco "-3*($x+15)-12" $x -15 -14 # 49 fiocco "-12" $x -15 -8 # 50 fiocco "4/3*($x+5)-8" $x -8 -5 # 51 fiocco "-1/8*($x+13)-7" $x -13 -5 # 52 fiocco "4/3*($x+10)-3" $x -13 -10 # 53 fiocco "-3" $x -13 -10 # 54 fiocco "4/3*($x+13)-3" $x -16 -13 # 55 fiocco "-7" $x -19 -16 # 56 fiocco "4/3*($x+16)-3" $x -19 -16 # 57 fiocco "-3" $x -21 -16 # 58 fiocco "0" $x -21 -16 # 59 fiocco "-5/3*($x+19)+5" $x -19 -16 # 60 fiocco "2/4*($x+19)+5" $x -19 -15 # 61 fiocco "-7/4*($x+15)+7" $x -15 -11 # 62 fiocco "0" $x -11 -7 # 63 fiocco "-6/4*($x+13)+6" $x -13 -9 # 64 fiocco "6" $x -13 -6 # 65 fiocco "-4/2*($x+6)+6" $x -8 -6 # 66 fiocco "1/8*($x+16)+9" $x -16 -8 # 67 fiocco "3*($x+16)+9" $x -16 -15 # 68 fiocco "12" $x -15 -9 # 69 fiocco "-5/3*($x+9)+12" $x -12 -9 # 70 fiocco "$x+29" $x -12 -10 # 71 fiocco "-5/3*($x+7)+14" $x -10 -7 # 72 fiocco "6/2*($x+7)+14" $x -7 -5 # 73 fiocco "-3/2*($x+3)+17" $x -5 -3 # 74 fiocco "6/3*($x+6)+11" $x -6 -3 # 75 fiocco "-3/2*($x+4)+8" $x -6 -4 # 76 fiocco "7/3*($x+4)+8" $x -4 -1 # 77 fiocco "-4/3*($x-2)+5" $x -1 2 # 78 fiocco "3/2*($x-2)+5" $x 0 -2 # 79 fiocco "-3/3*($x+3)+5" $x -3 0 # 80 fiocco "4/2*($x+3)+5" $x -3 -1 # 81 fiocco "-3/2*($x+2)+1" $x -4 -2 # 82 fiocco "1/5*($x+2)+1" $x -7 -2 # 83 fiocco "-3/2*($x+9)+3" $x -9 -7 # 84 fiocco "1/5*($x+4)+4" $x -9 -4 # 85 fiocco "4/2*($x-4)+4" $x 2 4 # 86 fiocco "4" $x 4 7 # 87 fiocco "3*($x-7)+4" $x 6 7 # 88 fiocco "1/4*($x-6)+1" $x 2 6 # 89 fiocco "-2" $x 2 6 # 90 fiocco "-3/2*($x-6)-2" $x 6 8 # 91 fiocco "-5" $x 4 8 # 92 fiocco "-3/2*($x-2)-2" $x 2 -4 # 93 fiocco "2*($x-2)-7" $x 0 2 # 94 fiocco "4/2*($x+2)-7" $x -2 0 # 95 fiocco "-2*($x+2)-7" $x -2 0 # 96 fiocco "-2*($x-2)-7" $x 0 2 # 97 fiocco "3*($x+3)-3" $x -4 -3 # 98 fiocco "-6" $x -8 -4 # 99 fiocco "3*($x+7)-3" $x -8 -7 # 100 fiocco "-3" $x -7 -3 # 101 done for((i=0; i<$Cy; i++)); do echo done |
Il risultato dovrebbe essere qualcosa di simile a questo:
Non è bellissimo, ma è quello che stavamo cercando di fare. Perfezionando le equazioni probabilmente si può ottenere di meglio.