De bitcoin11 is een digitale munteenheid waarvan de koers van dag tot dag sterk kan fluctueren. Van een goede vriend met voorspellende gaven heb je een tabel gekregen met de koers van de bitcoin (in euro) voor de komende $$n \in \mathbb{N}_0$$ dagen. Je vriend daagt je uit om met deze informatie zoveel mogelijk winst te proberen maken met het verhandelen van bitcoins tijdens deze periode. Daarbij gelden de volgende regels:
aan het begin van de periode heb je geen bitcoin
aan het einde van de periode heb je ook geen bitcoin
je mag nooit meer dan één bitcoin tegelijkertijd in je bezit hebben
elke dag van de periode kan je ofwel één bitcoin kopen als je er geen in je bezit hebt, of de bitcoin die je in bezit hebt verkopen, of helemaal niets doen (op dezelfde dag mag je dus niet én de bitcoin die je hebt verkopen én een nieuwe bitcoin kopen)
Het doel is om op het einde van de periode zoveel mogelijk winst te maken. Voor grote waarden van $$n$$ wordt het al snel onmogelijk om alle mogelijkheden voor het verhandelen van bitcoins te evalueren, om te zien welke van deze mogelijkheden de maximale winst oplevert. We kunnen de maximale winst echter op een veel snellere manier bepalen door bitcoins te kopen als die lokaal het goedkoopst zijn, en terug te verkopen als die lokaal het duurst zijn. Deze strategie wordt grafisch voorgesteld in onderstaande figuur.
Concreet bestaat deze gretige strategie erin om op elke dag — behalve de laatste dag — de volgende beslissingen te nemen:
als je geen bitcoin hebt en morgen worden bitcoins duurder, koop dan vandaag een bitcoin
als je wel een bitcoin hebt en morgen worden bitcoins goedkoper, verkoop dan vandaag je bitcoin
De laatste dag verkoop je je bitcoin als je er één hebt, om zo nog wat extra winst op te strijken.
Als we deze strategie toepassen op het voorbeeld in bovenstaande figuur, dan kopen we de eerste dag een bitcoin aan €5 omdat bitcoins op dag 2 duurder zullen worden (€11) en we nog geen bitcoin hadden bij de start van de periode. Op de tweede dag verkopen we onze bitcoin terug aan €11 omdat bitcoins op dag 3 goedkoper zullen worden (€4). Op de derde dag kopen we geen bitcoin omdat bitcoins op dag 4 nog goedkoper zullen worden (€2). Als we op die manier verdergaan, dan maken we uiteindelijk €17 winst met het verhandelen van bitcoins.
De koers van de bitcoin (in euro) doorheen een periode van $$n \in \mathbb{N}_0$$ opeenvolgende dagen stellen we voor als een reeks (een lijst of een tuple) met $$n$$ positieve integers.
De acties die we uitvoeren tijdens zo een periode waarin we bitcoins verhandelen, stellen we voor als een string van $$n$$ karakters. Hierbij kunnen enkel de volgende karakters voorkomen:
een hoofdletter K stelt voor dat we op die dag één bitcoin kopen
een hoofdletter V stelt voor dat we op die dag één bitcoin verkopen
een koppelteken (-) stelt voor dat we op die dag geen bitcoins verhandelen
Uiteraard moeten deze acties voldoen aan de regels rond het kopen en verkopen van bitcoins zoals gesteld in de inleiding. Gevraagd wordt:
Schrijf een functie winst waaraan twee argumenten moeten doorgegeven worden: i) de koers $$k$$ van de bitcoin (in euro) doorheen een periode van $$n \in \mathbb{N}_0$$ opeenvolgende dagen en ii) de acties $$a$$ die we uitvoeren tijdens die periode van $$n$$ dagen. De functie moet de winst (in euro) teruggeven die we opstrijken als we tijdens die periode van $$n$$ dagen bitcoins verhandelen volgens de gegeven acties, rekening houdend met de gegeven koers van de bitcoin tijdens die periode. Voor de acties $$a$$ die aan de functie doorgegeven worden moet de functie expliciet controleren dat:
$$a$$ een string is
$$a$$ evenveel karakters telt als het aantal elementen van $$k$$
$$a$$ enkel geldige karakters bevat (K, V of -)
$$a$$ geen ongeldige acties uitvoert: een bitcoin kopen als je er al één hebt of een bitcoin verkopen als je er geen hebt
Indien aan minstens één van deze voorwaarden niet voldaan is, dan moet de functie de string 'ongeldige input' retourneren.
Schrijf een functie maximaliseer_winst waaraan de koers van de bitcoin (in euro) doorheen een periode van $$n \in \mathbb{N}_0$$ opeenvolgende dagen moet doorgegeven worden. De functie moet een tuple retourneren waarvan het eerste element de maximale winst is, en het tweede element de optimale acties om tot deze maximale winst te komen.
Deze functies mogen ervan uitgaan dat het eerste argument dat aan de functie wordt doorgegeven een geldige voorstelling is van de koers van de bitcoin (in euro) doorheen een periode van $$n \in \mathbb{N}_0$$ opeenvolgende dagen, zonder dat dit expliciet moet gecontroleerd worden.
>>> winst([4915, 4962, 4816, 4964,4886, 4937, 4969], 'KV-KVKV') 1 >>> winst([4915, 4962, 4816, 4964,4886, 4937, 4969], 'KVKVK-V') 278 >>> winst([5, 11, 4, 2, 8, 10, 7, 4, 3, 6], 'KV-K-V--KV') 17 >>> winst((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11), '-K-V-KV-KVKV') 31 >>> winst([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10], '-K-V--K-VK--V') 16 >>> winst((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10), '-KVK----VKV') 14 >>> winst([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], '----------') 0 >>> winst((10, 4, 2, 4, 8, 12), 'K---VV') 'ongeldige input' >>> maximaliseer_winst([4915, 4962, 4816, 4964,4886, 4937, 4969]) (278, 'KVKVK-V') >>> maximaliseer_winst([5, 11, 4, 2, 8, 10, 7, 4, 3, 6]) (17, 'KV-K-V--KV') >>> maximaliseer_winst((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11)) (31, '-K-V-KV-KVKV') >>> maximaliseer_winst([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10]) (16, '--K-V-K-VK--V') >>> maximaliseer_winst((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10)) (14, '-KVK----VKV') >>> maximaliseer_winst([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]) (0, '----------') >>> maximaliseer_winst((10, 4, 2, 4, 8, 12)) (10, '--K--V')