LinuxLudus: Pytoni e bottiglie

Daniele Zambelli daniele.zambelli@inwind.it
Sab 7 Giu 2008 10:03:25 CEST


Ho sentito parlare da diverso tempo del LinuxLudus, io frequento il LugVr, 
quando un amico mi ha segnalato che da voi c'è qualcuno che gioca con Python, 
non ho resistito e mi sono iscritto alla ML.

Interessante il programma sul problema dei 3 contenitori... Io ho trovato una 
soluzione in 8 mosse, è possibile dividere il liquido con meno travasi?

Ho modificato un po' il programma semplificandolo (o per lo meno accorciandolo 
un po'). Di seguito riporto la mia versione:

# ---8<--- inizio programma
class Pot:

    def __init__(self,name,capacity,volume=0):
        self._capacity=capacity
        self._volume=volume
        self._name=name

    def __str__(self):
        return "%s: %s" % (self._name, self._volume)

    def pour_into(self, other):
        #Le situazioni sono 2: o si riesce a versare solo una parte del
        #contenuto, oppure lo si versa tutto
        if self._volume==0:
            print messages["vuoto"]
        elif other._volume==other._capacity:
            print messages["pieno"]
        else:
            if self._volume > (other._capacity - other._volume):
                self._volume -= (other._capacity - other._volume)
                other._volume=other._capacity
            else:
                other._volume += self._volume
                self._volume = 0

def print_volumes():
    print ("situazione attuale\t\t%s\t%s\t%s\n" %
           (pots['A'], pots['B'], pots['C']))

def control_input(pots):
    print "inserisci i contenitori",
    while True:
        pot_name=raw_input()
        if pot_name.lower() == "quit":
            return None, None
        if len(pot_name) != 2:
            print messages["lettere_numero"]
        else:
            p0, p1 = pot_name[0].upper(), pot_name[1].upper()
            if p0==p1:
                print messages["lettere_uguali"]
            elif not (p0 in pots and p1 in pots):
                print messages["lettere_sbagliate"]
            else:
                return pots[p0], pots[p1]

def instructions():
    print '''Hai tre contenitori A, B, C che possono contenere rispettivamente
80, 50, 30 litri. Non ci sono misure intermedie, quindi non puoi versare
con esattezza metà  del contenuto. Inizialmente hai il primo contenitore
da 80 litri pieno e gli altri due vuoti.
Lo scopo del gioco è, tramite una serie di travasi, arrivare ad avere
esattamente 40, 40 e 0 litri nei rispettivi contenitori A, B ,C.

Per indicare il travaso semplicemente scrivi la lettera del
contenitore da cui vuoi versare e la lettere del contenitore
in cui vuoi versare.
Ad esempio:
AB
AC
e premi invio.
Per interrompere il gioco digita 'quit'"

'''
    print "\t\t\tA\tB\tC"
    print "capienza\t\t80\t50\t30"
    print ""

#---SI COMINCIA---

messages ={
"lettere_uguali": "non puoi inserire due lettere uguali",
"lettere_numero": "devi inserire due lettere, né più né meno",
"lettere_sbagliate": "devi inserire solo A, B o C",
"vuoto": "Il contenitore da cui vuoi versare è vuoto! Scegline un'altro",
"pieno": "il contenitore in cui vuoi versare è pieno! Scegline un altro",
"quit": "Gioco interrotto",
"vinto": "\n\nHai vinto!",
"tentativi": "Hai fatto %s tentativi\n"}

pots = {"A": Pot("A",80,80), "B": Pot("B",50), "C": Pot("C",30)}

#Dà le informazioni all'utente
instructions()
print_volumes()

#Avvio il CICLO PRINCIPALE
tentatives=0
while True:
    if (pots["A"]._volume == 40 and pots["B"]._volume == 40): break
    p0, p1 = control_input(pots)
    if p0==None: break
    p0.pour_into(p1)
    print_volumes()
    tentatives += 1

if p0!=None:
    print messages['vinto']
    print messages['tentativi'] % tentatives
else:
    print messages["quit"]

# --->8--- fine programma

La modifica principale riguarda la funzione control_input che viene 
semplificata. In particolare le viene tolta la responsabilità di controllare 
se i contenitori sono pieni o vuoti. Questo controllo viene svolto dalla 
funzione che deve eseguire il travaso. control_input ora restituisce o una 
coppia di oggetti vuoti (None) o due contenitori.

I contenitori, invece di essere associati a identificatori separati, vengono 
messi dentro un dizionario.

Ho modificato il programma in modo che sia il ciclo principale a gestire la 
fine del programma anche quando è l'utente a voler terminare 
scrivendo "quit".

Qualche altra modifica sulla gestione delle stringhe...

Ringrazio per lo spunto interessante.

Ciao

-- 

Daniele                        www.fugamatematica.blogspot.com

                          giusto!
  _o)  (o_       (o_ _o)  nel verso
-./\\  //\.-     //\ /\\  forse è perché non guardiamo le cose
 _\_V  V_/_      V_/ \_V  Quando non ci capiamo,


Maggiori informazioni sulla lista linuxludus