In deze oefening beschouwen we een reeks personen die schulden of tegoeden aan elkaar hebben. We proberen vervolgens een 2-tal algoritmen uit om deze schulden met een beperkt aantal transacties (betalingen van schuldenaars aan personen die een tegoed hebben) te vereffenen. De groep personen is niet vast en kan te allen tijde wijzigen.

We bouwen 3 klassen in deze opgave, namelijk:

In deze oefening worden personen door strings voorgesteld (hun naam). Deze strings zijn uniek (er zijn geen 2 verschillende personen met dezelfde naam).

Opmerking: bij de opsomming van methoden in een klasse, wordt het argument self in de opgave nooit expliciet vermeld. Wanneer er dus aangegeven wordt dat een methode geen argumenten heeft, wordt eigenlijk bedoeld dat de methode enkel self als argument heeft. Wanneer vermeld wordt dat een methode 2 argumenten heeft, wordt bedoeld dat de methode naast het self-argument nog 2 bijkomende argumenten heeft.

Klasse Schulden

LET OP: Bij aanmaak van een object, gebruiken we een lijst van triplets (een tuple met drie elementen). Elk triplet bestaat uit:

Je mag aannemen dat een persoon geen schulden bij zichzef aangaat. Bij de aanmaak van een schuldobject, geeft het triplet ('A', 'B', 20) aan dat persoon A een schuld heeft van 20 aan persoon B.

Een betaling wordt eveneens door een triplet vastgelegd, namelijk:

Je mag hierbij aannemen dat een persoon geen betalingen aan zichzelf uitvoert. Bij het uitvoeren van een betaling, geeft het triplet ('C', 'D', 50) aan dat persoon C het bedrag 50 betaalt aan persoon D.

Programmeer in deze klasse:

Voorbeeld

s = Schulden([('D', 'B', 50), ('B', 'D', 40), ('B', 'A', 80), ('A', 'C', 100), ('A', 'C', 40)])
print(s) #[('A', 'C', 40), ('A', 'C', 100), ('B', 'A', 80), ('B', 'D', 40), ('D', 'B', 50)]
print(s.tegoed()) #{'B': -70, 'A': -60, 'D': -10, 'C': 140}
s.vereenvoudig()
print(s) #[('A', 'C', 140), ('B', 'A', 80), ('D', 'B', 10)]
s += ('B', 'A', 20)
print(s.tegoed()) #{'B': -50, 'A': -80, 'D': -10, 'C': 140}
s += ('D', 'B', 60)
print(s.tegoed()) #{'B': -110, 'A': -80, 'D': 50, 'C': 140}
s += [('B', 'D', 10), ('C', 'A', 30), ('B', 'D', 100)]
print(s.tegoed())
{'A': -110, 'D': -60, 'C': 170}
t = s.transacties()
s += list(t)
print(s.tegoed()) #{}

Klasse SchuldenCentralePot

Deze klasse erft over van de klasse Schulden en implementeert een beter algoritme om de schulden te vereffenen, namelijk

Programmeer dit algoritme in de methode transacties() (zonder argumenten). Voer de betalingen NIET uit in deze methode, maar geef een verzameling van transactietriplets conform met deze aanpak.

Voorbeeld

s = SchuldenCentralePot([('D', 'B', 50), ('B', 'D', 40), ('B', 'A', 80), ('A', 'C', 100), ('A', 'C', 40)])
print(isinstance(s, Schulden)) #True
print(s.tegoed()) #{'B': -70, 'A': -60, 'D': -10, 'C': 140}
t = s.transacties()
print(t) #{('B', 'C', 70), ('D', 'C', 10), ('A', 'C', 60)}
s += list(t)
print(s.tegoed()) #{}

Klasse SchuldenPaar

Ook deze klasse erft over van de klasse Schulden. We programmeren hier een vereffening tussen koppels personen (en niet met een centrale persoon). Ga als volgt tewerk:

Herhaal tot alle schulden betaald
        Bepaal A, de persoon met de grootste schuld S
        Bepaal B, de persoon met het grootste tegoed V
        Indien S ≤ V: A betaalt S aan B
        Indien S > V: A betaalt V aan B

Indien je bij het bepalen van persoon A meerdere personen zou vinden, neem dan de persoon die eerst komt in de standaardsortering. Analoog voor persoon B.

Programmeer dit algoritme in de methode transacties() (zonder argumenten). Voer de betalingen NIET uit in deze methode, maar geef een verzameling van transactietriplets conform met deze aanpak.

Voorbeeld

s = SchuldenPaar([('D', 'B', 50), ('B', 'D', 40), ('B', 'A', 80), ('A', 'C', 100), ('A', 'C', 40)])
print(isinstance(s, Schulden)) #True
print(s.tegoed()) #{'D': -10, 'B': -70, 'A': -60, 'C': 140}
t = s.transacties()
print(t) #{('B', 'C', 70), ('D', 'C', 10), ('A', 'C', 60)}
s += list(t)
print(s.tegoed()) #{}
s = SchuldenPaar([('I', 'G', 90), ('C', 'G', 40), ('B', 'H', 80), ('A', 'F', 100), ('I', 'H', 100)])
print(isinstance(s, Schulden)) #True
print(s.tegoed()) #{'B': -80, 'C': -40, 'I': -190, 'H': 180, 'F': 100, 'A': -100, 'G': 130}
t = s.transacties()
print(t) #{('B', 'F', 80), ('I', 'F', 10), ('A', 'G', 100), ('C', 'F', 10), ('C', 'G', 30), ('I', 'H', 180)}
s += list(t)
print(s.tegoed()) #{}