Esercizio Caml

Dadde11
Salve ho trovato questo esercizio.

Si definisca la funzione sumsqrs che prende come argomenti tre interi e restituisce la somma dei quadrati dei due piµu grandi.

Io l'ho risolto cosi, ma non torna:

# let sumsqrs (x:int) (y:int) (z:int)= if x>y>z then (square x+square y) else if x>z>y then (square x+square z) else if y>z>x then (square y+square z);;

Perche non va bene???? qualcuno sa aiutarmi?

Risposte
vict85
Dati 3 elementi ci sono 6 ordini possibili. Quindi è evidente che tu stai ignorando dei casi.

A>B>C
A>C>B
B>A>C
B>C>A
C>A>B
C>B>A

In ogni caso penso che si possano fare meno di 6 casi. Anche perché una volta trovato il più piccolo dei 3 allora non ha importanza sapere l'ordine che hanno gli altri 2.

Probabilmente è possibile usare un solo caso ma non conosco Caml quindi non saprei come scrivertelo.

hamming_burst
con il consiglio di vict si possono ridurre i casi, e considerare solo di trovare il minimo.
es. si può utilizzare la funzione di libreria
min
'a -> 'a -> 'a

presi due tipi uguali restituisce il minimo tra i due. senza star li a scrivere il codice.

tipo una funzione con tre elementi può essere così (notazione O'Caml):
let three_min x y z = min (min x y) z;;


ora basta filtrare il risultato ed applicarlo alla funzione che devi implementare, scegli:
- tre if-then-else
- un pattern matching con guardia

nel secondo caso consiglio l'utilizzo dell'in per compattare il codice.

apatriarca
L'espressione x > z > y non fa quello che ti immagini. In effetti, provandolo su ocaml mi restituisce errore. Infatti l'espressione x > z è un valore booleano e quindi x > z > y = (x > z) > y ha senso solo quando y è un valore booleano. In ogni caso, non è necessario stabilire esattamente l'ordine dei tre valori interi, ma è sufficiente trovare l'elemento più piccolo dei tre e prendere gli altri due. Si può fare usando la funzione min o gli altri metodi già descritti.

Si può alternativamente osservare che il valore da trovare è il più alto tra tutte le somme di quadrati possibili. Ce ne sono solo 3: $x^2 + y^2$, $x^2 + z^2$ e $y^2 + z^2$.

Dadde11
Non per levarmi la briga di farlo, ma visto che i vostri consigli mi portano ad ottenere errori di vario genere, qualcuno puo postare un codice corretto?!?

apatriarca
Perché non provi a postare questi codici che hai provato invece?

vict85
In realtà si può fare senza distinguere in casi (in notazione matematica):

\(\displaystyle f(x,y,z) = \max(x,y)^2 + \max(\min(x,y), z)^2\)

Riguardo invece al commento di mio fratello (apatriarca) vale solo nel caso in cui gli elementi sono ordinati anche in valore assoluto. Mentre non vale, in generale, quando si considerano numeri anche negativi.

vict85
Indicativamente penso che in Caml sia qualcosa del tipo

let sumsqrs x y z = square (max x y) + square (max (min x y) z);;


Immagino che le parentesi non siano necessarie (un computer non ne ha bisogno, anche se gli ideatori di lisp non sembra ne fossero consapevoli :D).

hamming_burst

Immagino che le parentesi non siano necessarie (un computer non ne ha bisogno, anche se gli ideatori di lisp non sembra ne fossero consapevoli :D).

Un computer no di sicuro, ma il nostro cervello esploderebbe senza :D

cmq il discorso è lunghetto, ma dipende dal linguaggio la necessità sintattica (e semantica) o meno. Una su tutti è per non creare ambiguità.
Le parentesi fanno parte della sintassi come un qualunque altro operatore. In alcuni casi sono superflui (come la precedenza), in altri fanno parte della grammatica di un operatore (un es. che mi viene in mente è il while( in alcuni linguaggi, la seconda parentesi sarebbe superflua, ma viene inserita per la corrispondenza).
Poi per linguaggi funzionali serve per la precedenza, se ci sono funzioni anonime, se siamo nel caso HOFL...

vict85
"hamming_burst":

Immagino che le parentesi non siano necessarie (un computer non ne ha bisogno, anche se gli ideatori di lisp non sembra ne fossero consapevoli :D).

Un computer no di sicuro, ma il nostro cervello esploderebbe senza :D

cmq il discorso è lunghetto, ma dipende dal linguaggio la necessità sintattica (e semantica) o meno. Una su tutti è per non creare ambiguità.
Le parentesi fanno parte della sintassi come un qualunque altro operatore. In alcuni casi sono superflui (come la precedenza), in altri fanno parte della grammatica di un operatore (un es. che mi viene in mente è il while( in alcuni linguaggi, la seconda parentesi sarebbe superflua, ma viene inserita per la corrispondenza).
Poi per linguaggi funzionali serve per la precedenza, se ci sono funzioni anonime, se siamo nel caso HOFL...


In Caml noto che le operazioni sono nella forma usuale. Ma in lisp no. In lisp l'operazione è sempre all'inizio.

Per intenderci a + b si scrive (+ a b) se tutte le operazioni sono scritte così le parentesi non sono necessarie e tutte le scritture hanno un'unico modo di essere letti (anche se per un uomo sono scomodi). Il lisp invece ti costringe ad inserirle tutte (ma proprio tutte!); una cosa che fortunatamente è stata tolta in altri lunguaggi.

La mia era una battuta sul lisp ;)

hamming_burst
[OT]
"vict85":
In Caml noto che le operazioni sono nella forma usuale. Ma in lisp no. In lisp l'operazione è sempre all'inizio.

Per intenderci a + b si scrive (+ a b) se tutte le operazioni sono scritte così le parentesi non sono necessarie e tutte le scritture hanno un'unico modo di essere letti (anche se per un uomo sono scomodi). Il lisp invece ti costringe ad inserirle tutte (ma proprio tutte!); una cosa che fortunatamente è stata tolta in altri lunguaggi.

certo certo è la notazione infissa, per quello ho detto che dipende dal linguaggio se le parentesi sono superflue per il significato, per via che la sintassi può utilizzare accrocchi diversi per la precedenza. Ma devo dire non sapevo che lisp facesse parte proprio di questo caso :)
E' in effetti un linguaggio vetusto, che si studia solo come linguaggio storico (almeno da me) per via della sua introduzione di semantiche particolari che ad ora non sono più utilizzate (se non in minima parte per compatibilità).
Posso chiederti come mai conosci la programmazione proprio di Lisp (come linguaggio funzionale) e non qualcosa di più moderno?

La mia era una battuta sul lisp ;)

opsete non l'avevo capita :)

[/OT]

vict85
"hamming_burst":
[OT]
[quote="vict85"]In Caml noto che le operazioni sono nella forma usuale. Ma in lisp no. In lisp l'operazione è sempre all'inizio.

Per intenderci a + b si scrive (+ a b) se tutte le operazioni sono scritte così le parentesi non sono necessarie e tutte le scritture hanno un'unico modo di essere letti (anche se per un uomo sono scomodi). Il lisp invece ti costringe ad inserirle tutte (ma proprio tutte!); una cosa che fortunatamente è stata tolta in altri lunguaggi.

certo certo è la notazione infissa, per quello ho detto che dipende dal linguaggio se le parentesi sono superflue per il significato, per via che la sintassi può utilizzare accrocchi diversi per la precedenza. Ma devo dire non sapevo che lisp facesse parte proprio di questo caso :)
E' in effetti un linguaggio vetusto, che si studia solo come linguaggio storico (almeno da me) per via della sua introduzione di semantiche particolari che ad ora non sono più utilizzate (se non in minima parte per compatibilità).
Posso chiederti come mai conosci la programmazione proprio di Lisp (come linguaggio funzionale) e non qualcosa di più moderno?

La mia era una battuta sul lisp ;)

opsete non l'avevo capita :)

[/OT][/quote]

Perché qualche anno fa (beh, saranno almeno 5 penso) mi ero messo a vedermi scheme (un dialetto lisp). Insieme ad Ada è uno di quei linguaggi che ho visto molto (ma proprio molto) superficialmente. La voglia di guardarmeli è finita presto...

Ho usato questo, se a qualcuno interessa http://plt-scheme.org/

Se avrò voglia di vedermi un funzionale penso che mi guarderò Haskell.

hamming_burst
"vict85":
Perché qualche anno fa (beh, saranno almeno 5 penso) mi ero messo a vedermi scheme (un dialetto lisp). Insieme ad Ada è uno di quei linguaggi che ho visto molto (ma proprio molto) superficialmente.

Scheme ne ho sentito parlare, Ada è un altro con un certo numero di anni...

La voglia di guardarmeli è finita presto...

questo è lo spirito :-D

Se avrò voglia di vedermi un funzionale penso che mi guarderò Haskell.

E' parecchio utilizzato in alcuni ambienti. Ma i principi funzionali son quelli, perciò uno vale l'altro :)

::::::::
@Dadde11:
tornando al tuo codice, noto diversi errori (oltre quelli di apatriarca). Un codice sintatticamente corretto sarebbe tipo questo (tralasciando il triplo confronto):
let sumsqrs x y z = 
  if x>y
  then (square x) + (square y) 
  else (if x>z 
       then (square x) + (square z) 
      else (if y>z then 1 else 2));;


cose da notare:
- la tipizzazione MAI forzarla con i costutti (x:int), ci son casi che è ininfluente,, ma per utilizzare tutta la potenza del linguaggio interpretato che è la tipizzazione, ti consiglio di non farlo. Se non metti questi costrutti, ti puoi accorgere dove stanno gli errori dato dall'analizzatore semantico dei tipi, cosa fondamentale.
- le parentesi (dove ne abbiam parlato all'incira) sono da mettere per non creare ambiguità e per scoping della funzione:
square si aspetta un solo parametro il + potrebbe creare problemi (dipende poi ma è per farti un'idea).
. il costrutto if-then ha ben altro tipo unit(). Quello che devi utilizzare è if-then-else il secondo ramo lo puoi inventare con un valore a caso per mantenere la tipizzazione ad int.

visto che la soluzione è stata data, ti mostro una possibike variante utilizzando l'in e il pattern matching:

let sumsqrs x y z =
  let three_min x y z = min (min x y) z 
      in let sumsqrs' x y z m =
	match m with
	| x' when x'=x -> y*y + z*z
	| y' when y'=y -> x*x + z*z
	| z' when z'=z -> x*x + y*y
	| _ -> 0
      in sumsqrs' x y z (three_min x y z);;

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.