| | |
| | |
| | ok, ik ben niet bijster slim, maar heb wel wat geprobeerd: |
| | |
| 1 | *****wijnandsnoep.pl***** |
| 2 | #!/usr/bin/perl |
| 3 | |
| 4 | # yes this is BSD licensed. Everyone may do what they want with it, I only want my name in the credits :-) |
| 5 | |
| 6 | #Copyright (c) 2005, Wijnand Wiersma |
| 7 | #All rights reserved. |
| 8 | |
| 9 | #Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
| 10 | |
| 11 | #Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.#Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
| 12 | |
| 13 | #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ORBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 14 | |
| 15 | # thanks to Wouter ( http://wdeboer.nl) for thinking with me. |
| 16 | |
| 17 | use warnings; |
| 18 | use strict; |
| 19 | |
| 20 | my $clear = `clear`; # bewaar de output van clear zodat wij hiermee telkens opnieuw het scherm kunnen clear'en. Zie perlcookbook hoofdstuk 15.3 |
| 21 | |
| 22 | my @toegestanemunten = qw ( 2.00 1.00 0.50 0.20 0.10 0.05 ); |
| 23 | @toegestanemunten=sort{$b <=> $a } @toegestanemunten; # Moet altijd aflopend zijn, zorg ervoor dat dat ook zo is. |
| 24 | my $defaultmuntenaantal=15; |
| 25 | |
| 26 | my %muntjes; # hash waarin de muntjes worden bijgehouden, we gaan uit van een vers gevulde automaat |
| 27 | foreach my $munt (@toegestanemunten ) |
| 28 | { $muntjes{$munt}=$defaultmuntenaantal; } |
| 29 | |
| 30 | my %produkten; # hash voor de aanwezige produkten. We gaan weer uit van een net gevulde automaat. |
| 31 | $produkten{'1'}='rolletje drop'; |
| 32 | $produkten{'2'}='zakje katjesdrop'; |
| 33 | $produkten{'3'}='zakje engelse drop'; |
| 34 | $produkten{'4'}='rolletje pepermunt'; |
| 35 | $produkten{'5'}='reep chocolade'; |
| 36 | |
| 37 | my $defaultvoorraad=10; |
| 38 | my %voorraad; # hierin hou ik bij hoeveel er van ieder produkt nog in de automaat zit. |
| 39 | $voorraad{'1'}=$defaultvoorraad; |
| 40 | $voorraad{'2'}=$defaultvoorraad; |
| 41 | $voorraad{'3'}=$defaultvoorraad; |
| 42 | $voorraad{'4'}=$defaultvoorraad; |
| 43 | $voorraad{'5'}=$defaultvoorraad; |
| 44 | |
| 45 | my %prijzen; # hash waarin bijgehouden wordt wat ieder produkt kost. |
| 46 | $prijzen{'1'}='0.75'; |
| 47 | $prijzen{'2'}='1.25'; |
| 48 | $prijzen{'3'}='1.50'; |
| 49 | $prijzen{'4'}='0.75'; |
| 50 | $prijzen{'5'}='1.00'; |
| 51 | |
| 52 | # Hierbij de main loop, deze wacht iedere keer op een aktie en roept de bijbehorende functies aan. |
| 53 | sub main |
| 54 | { |
| 55 | my $exit=undef; |
| 56 | while ( ! $exit ) |
| 57 | { |
| 58 | print $clear; |
| 59 | print "Welkom bij de snoepautomaat\n"; |
| 60 | print "Maak uw keuze:\n"; |
| 61 | print "\t1) Produkt kopen\n"; |
| 62 | print "\t2) Automaat bijvullen\n"; # just for fun ;-) |
| 63 | print "\t3) Automaat afsluiten\n"; |
| 64 | print "\nuw keuze? "; |
| 65 | my $input=; |
| 66 | chomp $input; |
| 67 | if ( $input eq '3' ) { $exit='1';} |
| 68 | elsif ( $input eq '1' ) { koop(); } |
| 69 | elsif ( $input eq '2' ) { bijvullen(); } |
| 70 | else { print "\nOngeldige invoer!\n"; } |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | # Deze functie handeld de aankoop van een produkt af |
| 75 | sub koop |
| 76 | { |
| 77 | print $clear; |
| 78 | my $done=undef; # hiermee kijken we of we klaar zijn met inwerpen of kiezen. |
| 79 | my $betaald=0.00; # nu nog niks, komt nog wel |
| 80 | my $moetgepast=moetgepast(); # checken voor de eerste inworp |
| 81 | while ( ! $done ) |
| 82 | { |
| 83 | print "Werp geld in\n"; |
| 84 | print "Gepast betalen svp\n" if $moetgepast; # als er gepast betaald moet worden kunnen we alleen waarschuwen, eigen risico gebruiker (net als echte automaten). |
| 85 | printf ("Ingegooid bedrag: %.2f\n\n",$betaald); # printf gebruik ik om de precisie aan te kunnen geven. |
| 86 | my $muntcount=0; # dit is voor de indexes in het menu |
| 87 | my %geldigemunten; # ook handig voor het menu |
| 88 | foreach my $munt ( sort (keys ( %muntjes ))) # Laat de toegestane munten in oplopende volgorde zien |
| 89 | { |
| 90 | $muntcount++; # we voegen een munt toe |
| 91 | $geldigemunten{$muntcount}=$munt; # |
| 92 | print "\t$muntcount) $munt\n"; |
| 93 | } |
| 94 | print "\t0) Klaar met inwerpen\n"; |
| 95 | my $inworp=; |
| 96 | chomp $inworp; |
| 97 | if ( $inworp ne '0' && exists $geldigemunten{$inworp}) # controleer of een munt geldig is en of er geen 0 is getypt |
| 98 | { |
| 99 | $betaald+=$geldigemunten{$inworp}; # dit is er tot nu toe betaald |
| 100 | $muntjes{$geldigemunten{$inworp}}++; # en we hebben er een munt bij in het buisje |
| 101 | } |
| 102 | elsif ( $inworp eq '0' ) { $done=1; } # ok, klaar met ingooien. |
| 103 | else { print "Ongeldige invoer!\n"; } # sukkel, dit mag je niet typen |
| 104 | } |
| 105 | |
| 106 | print $clear; |
| 107 | $done=undef; # reset |
| 108 | while ( ! $done ) # en weer checken we deze variabele om te kijken of er al iets goeds is gekozen |
| 109 | { |
| 110 | print "Kies het gewenste produkt\n\n"; |
| 111 | foreach my $produkt ( sort (keys ( %produkten ))) # laat ieder produkt zien in een menu |
| 112 | { |
| 113 | print "\t$produkt) $produkten{$produkt}\n"; # hmm, is dit lekker? |
| 114 | } |
| 115 | print "\t0) Geld terug\n"; # kan gebeuren he |
| 116 | my $produktkeuze=; |
| 117 | chomp $produktkeuze; |
| 118 | if ( $produktkeuze ne '0' && exists $produkten{$produktkeuze}) # ok, er is voor een bestaand produkt gekozen |
| 119 | { |
| 120 | if ( $voorraad{$produktkeuze} eq 0 ) # tja, wat er niet is kunnen we ook niet verkopen |
| 121 | { |
| 122 | print "Helaas, dit produkt is uitverkocht\n"; |
| 123 | } |
| 124 | elsif ( $prijzen{$produktkeuze} > $betaald ) # tja, dat snap je toch zelf wel he :-) |
| 125 | { |
| 126 | print "Onvoldoende geld ingeworpen\n"; |
| 127 | } |
| 128 | else # ok, niks mis met de keuze van de gebruiker, dus we kunnen leveren en wisselgeld teruggeven |
| 129 | { |
| 130 | $done=1; # We kunnen maar 1 produkt kiezen, net als bij iedere andere automaat dus we springen er hier uit. |
| 131 | $voorraad{$produktkeuze}--; |
| 132 | geefwisselgeld($betaald, $produktkeuze); |
| 133 | } |
| 134 | } |
| 135 | else # ah, de gebruiker wil zijn geld terug ( ik kan het begrijpen ) |
| 136 | { |
| 137 | geefwisselgeld($betaald); # dat wordt dokkuh |
| 138 | $done=1; |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | # Kijk wat de gebruiker aan wisselgeld moet terugkrijgen. |
| 144 | sub geefwisselgeld |
| 145 | { |
| 146 | my $betaald=shift; |
| 147 | my $produktkeuze=shift || 0; # als er geen produkt is gekocht moet de gebruiker alles terugkrijgen. |
| 148 | my $betaalterug=$betaald - ( $prijzen{$produktkeuze} || 0 ); # als er geen produkt is zal hier ook geen bedrag uitkomen en dus is $betaalterug het volledige bedrag |
| 149 | printf ("ik moet %.2f terugbetalen\n",$betaalterug); # printf gebruik ik om de precisie aan te kunnen geven. |
| 150 | |
| 151 | foreach my $munt ( @toegestanemunten ) |
| 152 | { |
| 153 | for ( my $i = 50 ; ( !minderdan5sensor($munt)) && ( $betaalterug > 0 && ( $i >= 0 )) ; $i--) # 50 is een absurd grote waarde, maar geeft genoeg ruimte. we gaan door zolang er nog meer dan 5 van een munt zijn zodat we altijd wisselgeld kunnen blijven geven. |
| 154 | { |
| 155 | my $waarde = $i * $munt; # betere leesbaarheid |
| 156 | if ( ( $waarde eq $betaalterug) || ( $waarde <= $betaalterug) ) # raar dat ik eq moest gebruiken, maar ik had problemen om anders de 0.05 cent te matchen. |
| 157 | { |
| 158 | $betaalterug -= $waarde; # we gaan uitbetalen, dus we trekken dit van het nog te betalen bedrag af |
| 159 | $muntjes{$munt} -= $i; # en dus ook minder munten |
| 160 | print "Ik geef $i munt(en) van $munt terug\n" if $i > 0; # wel zo netjes om even te melden wat je teruggeeft |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | # spreekt voor zich, als een munt minder dan 5 in de buis heeft zitten geeft deze true terug. |
| 167 | sub minderdan5sensor |
| 168 | { |
| 169 | my $munt=shift; |
| 170 | if ( $muntjes{$munt} < 5 ) { return 1; } #minder dan 5, dus waar |
| 171 | else { return undef; } # dus vals |
| 172 | } |
| 173 | |
| 174 | # spreekt voor zich, als een munt meer dan 10 in de buis heeft zitten geeft deze true terug. |
| 175 | # momenteel niet in gebruik, misschien in latere versie |
| 176 | sub meerdan10sensor |
| 177 | { |
| 178 | my $munt=shift; |
| 179 | if ( $muntjes{$munt} > 10 ) { return 1; } # ja, van deze munt hebben we er minimaal 10 |
| 180 | else { return undef; } # dus vals |
| 181 | } |
| 182 | |
| 183 | # van de laagste 3 soorten munten kunnen we heel veel combinaties maken, zorg er dus altijd voor dat daar minimaal 5 van aanwezig zijn. |
| 184 | sub moetgepast |
| 185 | { |
| 186 | foreach my $munt ( @toegestanemunten ) |
| 187 | { |
| 188 | next if $munt eq '2.00'; |
| 189 | next if $munt eq '1.00'; |
| 190 | next if $munt eq '0.50'; |
| 191 | return 1 if minderdan5sensor($munt); #ja, van deze munt hebben we er minder dan 5 |
| 192 | } |
| 193 | return undef; |
| 194 | } |
| 195 | |
| 196 | sub bijvullen |
| 197 | { |
| 198 | # aanvullers hebben een sleutel, deze moeten ze nu tikken. |
| 199 | my $sleutel=; |
| 200 | chomp $sleutel; |
| 201 | return if $sleutel ne 'blah blah blah'; |
| 202 | # zet de muntjes weer op hun plek |
| 203 | foreach my $munt (@toegestanemunten ) |
| 204 | { $muntjes{$munt}=$defaultmuntenaantal; } |
| 205 | |
| 206 | # en zet alle produkten weer in hun standaard hoeveelheid |
| 207 | foreach my $produkt ( keys ( %produkten )) |
| 208 | { |
| 209 | $voorraad{$produkt}= $defaultvoorraad; |
| 210 | } |
| 211 | print "De automaat is weer aangevuld, druk op enter om door te gaan\n"; |
| 212 | my $nietnuttig=; |
| 213 | } |
| 214 | |
| 215 | # roep main hier aan |
| 216 | main(); |
| 217 | |
| | Mijn commentaar
|
| | Wijnand, |
| | Een interesante benadering van het probleem. |
| | Helaas maak je geen duidelijk onderscheid tussen het simulatie gedeelte, |
| | en het deel dat (jouw) besturing voorstelt. |
| | Dat maakt het implementeren van jouw software in een echte automaat lastig ! |
| | Daar staat tegenover dat je uitvoerig uitlegt wat je doet en waarom. |
| | Voor een profesionele situatie waar je met colega's moet samen werken wel zo prettig. |
| | Mij is onduidelijk waarom je zo zuinig bent met nieuwe regels, zoals op #169 en #178, Dat komt de leesbaarheid niet ten goede. |
| | Mooi is dat je ondanks dat dit niet in de opdracht gevraagd wordt aangeeft waneer een produkt is uitverkocht. |
| | Dit deel kan niet gesimuleerd worden omdat er geen sensors voor zijn. |
| | jij houd het dan ook keurig zelf bij. |
| | Je keuze voor de merkwaardige combinatie van hashes en arrays gaat me even te boven, |
| | maar dat zal ongetwijfeld aan mij liggen. |
| | Ook van je je clear oplossing is mij het doel niet duidelijk, zal het eens in het genoemde boek opzoeken ;) |
| | Hoop dat je bij de volgende opdracht net zo creatief bent ! |