Pages: [1]   Go Down
Print
Author Topic: esercizio Erlang  (Read 427 times)
0 Members e 1 Utente non registrato stanno visualizzando questa discussione.
Franco Barbanera
Moderator
Forumista Eroico
*****
Offline Offline

Posts: 3.072



WWW
« on: 20-01-2014, 15:45:26 »

A lezione abbiamo considerato il seguente problema

Si hanno due
contenitori per liquidi,
uno da cinque litri
completamente pieno d'acqua e uno da due litri vuoto.

Vogliamo ottenere precisamente un litro d'acqua nel contenitore
da due litri.

Possiamo trasferire acqua da un contenitore all'altro, o buttarla,
ma non ottenerne di nuova.

Abbiamo risolto il problema in Erlang tramite il seguente programma.
(la realizzazione del predicato reachable non e' il massimo. Se qualcuno
ne ha una migliore...)

Code:
-module(bucketsPuzzle).
-export([solution/0,solver/2,admissibleMoves/2,reachable/2,getAndSendSolution/2]).


solution() -> spawn(bucketsPuzzle,solver,[[{5,0}],self()]),
              receive
                     abort     -> nosolution;
                     Solution  -> lists:reverse(Solution)
                     
              end.

solver(PartialSol,PIDfather) ->
               [{N,M}|_] = PartialSol,
               case {N,M} of
                    {_,1}  -> PIDfather!PartialSol;
                    {_,_}   ->
                            Solvers =
                            [spawn(bucketsPuzzle,solver,[[{P,Q}|PartialSol],self()]) || {P,Q} <- admissibleMoves({N,M},PartialSol)],
                            getAndSendSolution(Solvers,PIDfather),
                            true
               end.
                                       

admissibleMoves({N,M},PartialSol) -> States = [{R,S} || R <-[0,1,2,3,4,5], S<-[0,1,2] ],
                                    [{P,Q} || {P,Q}<-States, reachable({P,Q},{N,M}), not(lists:member({P,Q},PartialSol))].

reachable({R,S},{N,M}) -> P = (M+N),
                          Q = (M+N),
                          ( ( ((P div 5) == 1) and (R==5) and (S==0)         
                             )
                            or
                            ( (not((P div 5) == 1)) and (R==P) and (S==0)
                             )
                            or
                            ( ((Q div 2) >= 1) and ( ((S==2) and (R==0))
                                                     or
                                                     ((S==2) and (R==(Q - 2)))
                                                    )
                             )
                            or
                            ( not((Q div 2) >= 1) and (S==Q) and (R==0)
                            )
                            or ((R==N) and (S==0)) 
                            or ((R==0) and (S==M))   
                           ) 
                          and
                          not({R,S}=={N,M}).




getAndSendSolution([],PIDfather) -> PIDfather!abort;

getAndSendSolution([_|Rest],PIDfather) -> receive
                                              abort -> getAndSendSolution(Rest,PIDfather);
                                              Solution -> PIDfather!Solution
                                          end.

Questa programma pero' restituisce la prima soluzione trovata da uno dei processi.

Modificare il codice in modo che anziche' ottenere una sola soluzione come lista di
coppie, si ottenga una lista di liste di coppie che rappresenti tutte le possibili soluzioni.

FB
Logged
Pages: [1]   Go Up
Print
Jump to: