domenica 5 aprile 2015

Che tipo di triangolo è? [Brevi Esercizi]

Salve!

È la vigilia di Pasqua, cosa faccio cosa non faccio, alla fine decido di scrivere uno script in bash.

Lo script chiede tre numeri interi, che sarebbero le misure dei lati di un triangolo, e restituisce il tipo del triangolo stesso, equilatero, isoscele, scaleno.

Può sembrare un'operazione semplice, ma in realtà non lo è. E non lo è per tutta una serie di ragioni. Anzitutto perché bash, confrontato con altri linguaggi, come Python ad esempio, non si presta molto a queste cose. Ed è proprio questo il bello. Spingersi oltre per vedere l'effetto che fa.

E poi, quando tutto sembra funzionare, vieni assalito da mille dubbi. E se al posto di un numero intero passi una stringa o un numero pari a zero o addirittura negativo? E poi bastano veramente tre lati per costruire un triangolo? Sì, bastano tre lati, ma non tre lati qualsiasi. Avete mai sentito parlare di disuguaglianza triangolare? La regola della disuguaglianza triangolare dice che ogni lato deve essere inferiore alla somma degli altri due. Vi faccio un esempio. Vi do la misura di tre lati, 1m, 2m, 80m, provate ora a costruire mentalmente un triangolo...Ecco, evidentemente un triangolo consta di tre lati, ma non basta, serve dell'altro.

E se passo allo script un numero decimale? Un casino, dovrei riscrivere alcune parti...magari lo lascio come esercizio, ci sarebbe bc... :)

Con Python è tutto più semplice, con bash mica tanto. Io ci ho provato. Sicuramente l'esercizio è migliorabile, perfezionabile e via dicendo.

#!/bin/bash

read -p "Digita la misura del primo lato: " a
read -p "Digita la misura del secondo lato: " b
read -p "Digita la misura del terzo lato: " c 


for i in $a $b $c; do
      if [ $i -gt 0 ] 2>/dev/null; then
             echo "" 
      else
             echo "devi immettere numeri interi e maggiori di zero" && exit 1
      fi
done


let d=$b+$c
let e=$a+$c
let f=$a+$b

if [[ $a -gt $d || $b -gt $e || $c -gt $f ]]; then
 clear
 echo -e "\nNon è stata rispettata la disuguaglianza triangolare\n" && exit 1
fi       


ordina=$( printf '%s\n' $a $b $c | sort -n )
risultato=$( uniq -c <<< "$ordina" | wc -l )

clear
case $risultato in
    1) echo -e "\nTRIANGOLO EQUILATERO\n" ;;
    2) echo -e "\nTRIANGOLO ISOSCELE\n"   ;;
    3) echo -e "\nTRIANGOLO SCALENO\n"    ;;
esac

Con read -p chiedo i tre lati. Poi il primo controllo. Se digito una stringa al posto di un numero intero oppure, se digito un numero non maggiore di zero, lo script mi ritorna exit 1. Ho usato un ciclo for, e il controllo lo fa l'operatore -gt che accetta solo numeri interi.
Poi il secondo controllo, quello della disuguaglianza triangolare, se ogni lato non è inferiore alla somma degli altri due, lo script mi ritorna un exit 1.

Passato questo secondo controllo, magari ne potremmo aggiungere altri, ma ora non mi viene niente, si passa all'elaborazione dei dati.

Printf mette in colonna i dati e sort -n li ordina. I dati ordinati vengono dati in pasto a uniq -c attraverso il "<<<", che si chiama here strings, e poi passati in input a wc -l.
P

Per capire che fa uniq -c dobbiamo fare un esempio. Poniamo che passi allo script i seguenti dati: 2 1 2

Questi tre dati vengono messi in colonna da printf:

2
1
2

Poi sort -n li ordina, dal più piccolo al più grande:

1
2
2

uniq -c conta quante volte compare un dato, in questo caso:

1 1
2 2

Infine wc -l conta quante righe ci sono. Se le righe sono 3, il triangolo è scaleno, se ce ne sono due, il triangolo è isoscele, se una, è equilatero.

Facciamo un altro esempio. Passo allo script i seguenti dati:  6, 4, 5;

printf li mette in colonna, sort -n li ordina, uniq -c conta le frequenze di ogni numero. In questo caso:

1 4
1 5
1 6

wc -l darà come risultato 3, che significa tre lati disuguali, quindi triangolo scaleno. E sarà il case a darci una risposta.


Alla prossima! E Buona Pasqua.

5 commenti:

  1. Bellissimo. & bravissimo.
    Però mi viene in mente una domanda, non nuova, anzi almeno anni '80 (per me).
    Perché farlo con Bash?
    Anzi la domanda è un altra: perché tutti quei linguaggi?
    Anzi, definitiva: quanti tipi di martelli ci sono a Birmingham?

    RispondiElimina
    Risposte
    1. Ciao Juhan! Faccio questi esercizi con bash perchè è un linguaggio che mi prende troppo. :))

      Elimina
    2. Per quanto riguarda il numero di martelli ti cito: "Marx ricorda che a Birmingham si costruivano cinquecento tipi di martelli diversi, diversamente configurati a seconda della particolarità dell’operazione a cui essi erano adibiti." :D Fonte: https://okpanico.wordpress.com/2014/03/31/octave-matlab-e-sympy/

      Elimina
  2. OK & OK. Pensa te le fonti alle volte. (O sono io che sono ripetitivo, come continuano a dirmi tutti?)

    RispondiElimina
    Risposte
    1. Ma no, che ripetitivo... ma stiamo scherzando? Presto scriverò un post sui martelli diBirmingham. Anche sulle falci, però :)))

      Elimina