Ana in Berta se neizprosno spopadata na dražbi. Izklicnih cen ni. Dražba poteka tako, da najprej da ponudbo Ana (ker je starejša), nato Berta, pa spet Ana, ... dokler ena od njiju ne odneha.
In še eno (za reševalce dobrodošlo pravilo): Ana mora vedno dati ponudbo. (Pravilo si je izmislil lastnik dražbe, ki ima rad tarok in ga jezi, da obvezna 3 v resnici ni obvezna, temveč le povzroča klope, ki jih osebno ne mara, ker ima takrat vedno najboljše karte.)
Dogajanje je popisano v datoteki takšne oblike.
11
17
24
30
-1
13
27
33
-1
12
27
34
40
-1
9
-1
8
20
30
31
-1
Tule se je prodajalo pet predmetov.
Vidimo torej:
Napiši program, ki prebere datoteko in izračuna ter izpiše dejstva do točke 3.
Dodaj še točki 4 in 5.
Podatki so v datotekah drazba.txt (gornji primer) in drazba-dolga.txt, pri kateri je rezultat
Prodanih predmetov: 42
Najvišja cena: 266
Skupna cena: 4736
Ana: 19 predmetov za 2217
Berta: 23 predmetov za 2519
Da bo rešitev priznana za pravilno, mora izpisati pravilne rezultate (besedilo ni pomembno, pomembne so številke) za obe datoteki.
Če bomo reševali naloge v ločenih zankah (in ne vseh v eni sami
veliki), bomo v vsaki, vedno znova, klicali funkcijo open
.
Da ne bo potrebno vedno spreminjati open("drazba.txt")
v
open("drazba-dolga.txt")
najprej definirajmo spremenljivko
ime_dat
z imenom datoteke, potem pa vedno kličimo kar
open(ime_dat)
.
= "drazba.txt" ime_dat
Da izvemo število prodanih predmetov, preprosto preštejemo,
kolikokrat se v datoteki pojavi "cena" -1
.
= 0
predmetov for cena in open(ime_dat):
if int(cena) == -1:
+= 1
predmetov print("Prodanih predmetov:", predmetov)
Prodanih predmetov: 5
Lahko bi pisali tudi
for vrstica in open(ime_dat):
cena = int(vrstica)
if cena == -1:
...
vendar ceno tako ali tako uporabimo le enkrat, torej je vseeno, če jo
pretvorimo v število kar znotraj if
-a.
Morda se je komu zahotelo pisati
for vrstica in open(ime_dat):
if vrstica == -1:
to ne deluje, ker je vrstica niz in ne število, torej ni enaka
(int
-u) -1
temveč nizu "-1"
. To
ni isto.
Ako bi dotični odkril, kaj je narobe bi to morda hotel popraviti v
for vrstica in open(ime_dat):
if vrstica == "-1":
tudi to ne deluje, ker je na koncu vrstice še znak za konec vrstice
\n
, ki smo ga (ali pa tudi ne) omenili na predavanju,
omenjen pa je v zadnji
nalogi za vaje.
Delovalo bi
= 0
predmetov for cena in open(ime_dat):
if cena == "-1\n":
+= 1
predmetov print("Prodanih predmetov:", predmetov)
Prodanih predmetov: 5
ali
= 0
predmetov for cena in open(ime_dat):
if cena.strip() == "-1":
+= 1
predmetov print("Prodanih predmetov:", predmetov)
Prodanih predmetov: 5
To pa ni že nič preprosteje od int
. Pravzaprav je slabše
kot int
. Vrstice datoteke vsebujejo števila, torej jih
pretvarjajmo v števila.
Ta naloga je preprostejša, kot se je morda komu zdelo. Ko beremo cene, nam je vseeno, kdo je reč kupil in, sploh, ali je določena pravkar prebrana cena zadnja ali ne. Da rešimo nalogo, je dovolj, da poiščemo najvišje število v datoteki. To pa je naloga, ki smo jo reševali na predavanju (najvišja napovedana temperatura v Radovljici) in na vajah.
Po zgledu prejšnje rešitve lahko napišemo
= 0
najvisja for cena in open(ime_dat):
if int(cena) > najvisja:
= int(cena)
najvisja print("Najvišja cena:", najvisja)
Najvišja cena: 40
Ker tule dvakrat pokličemo int(cena)
, pa se počasi
spodobi, da v število pretvorjeno vrstico shranimo v novo spremenljivko.
Lepše je torej
= 0
najvisja for vrstica in open(ime_dat):
= int(vrstica)
cena if cena > najvisja:
= cena
najvisja print("Najvišja cena:", najvisja)
Najvišja cena: 40
Tu pa se stvari zapletejo. Potrebno je sešteti vse cene, ki se
pojavijo pred ceno -1
. Torej: ko naletimo na ceno
-1
, moramo k skupni vrednosti prodanih izdelkov prišteti
ceno, ki se je pojavila predtem. Tega (za zdaj) ne znamo storiti
drugače, kot da si jo zapomnimo.
= 0
prej = 0
skupno for cena in open(ime_dat):
= int(cena)
cena if cena == -1:
+= prej
skupno = cena
prej print("Skupna cena:", skupno)
Skupna cena: 143
Trik je na koncu zanke. Zadnja stvar, ki jo naredimo, je
prej = cena
. Na ta način bo trenutna cena
v
naslednjem krogu zanke dostopna v spremenljivko prej
.
Z vsemi tremi točkami lahko opravimo tudi v eni zanki.
= 0
prodanih = 0
najvisja = 0
prej = 0
skupno for cena in open(ime_dat):
= int(cena)
cena if cena == -1:
+= 1
prodanih if prej > najvisja:
= prej
najvisja += prej
skupno = cena
prej
print("Prodanih predmetov:", predmetov)
print("Najvišja cena:", najvisja)
print("Skupna cena:", skupno)
Prodanih predmetov: 5
Najvišja cena: 40
Skupna cena: 143
Preostali točki rešimo kar v enem zamahu. Bistvo naloge ni v tem, da znamo šteti in seštevati, kot v prvih dveh točkah, temveč v tem, da vemo, kdo je tisti, ki je na koncu koncev kupil nek predmet. Eden od načinov - za nas trenutno morda najpreprostejši - je, da štejemo, koliko višanj cene je doživel nek predmet. Če jih je liho, ga je kupila Ana, sicer Berta.
= berta = 0
ana = berta_skupno = 0
ana_skupno = 0
visanj = -1
prej for cena in open(ime_dat):
= int(cena)
cena if cena != -1:
+= 1
visanj else:
if visanj % 2 == 1:
+= 1
ana += prej
ana_skupno else:
+= 1
berta += prej
berta_skupno = 0
visanj = cena
prej
print("Ana:", ana, "predmetov za", ana_skupno)
print("Berta:", berta, "predmetov za", berta_skupno)
Ana: 2 predmetov za 42
Berta: 3 predmetov za 101
Tako kot prej imamo še vedno cena
in prej
.
Nova spremenljivka je število visanj
, ki je v začetku
0
. Vsakič, ko preberemo ceno, ki ni -1
, gre za
višanje, torej k visanj
prištejemo 1. Sicer pa je bil
izdelek pravkar (no, v prejšnji vrstici) prodan. Če je število višanj
liho, povečamo število predmetov in skupno ceno za Ano, sicer za Berto.
V obeh primerih pa (ne spreglejmo!) nastavimo visanj
nazaj
na 0.
Komur je ta naloga na robu tistega, kar razume, naj bo pozoren
predvsem na to, kje v strukturi teh if
-ov in
else
-ov se pojavita vrstici visanj = 0
in
prej = cena
. Prva je znotraj else
-a, ki
pokrije primer, ko je izdelek prodan. Tako "resetiramo" število višanj
za naslednji izdelek. Druga, prej = cena
je izven pogojev,
vendar v zanki, saj se mora zgoditi vedno. (Glede na to, da na dražbi
vedno prodamo vse izdelke, ker Ana mora predlagati ceno, nikoli
ne bomo naleteli na dve -1
zapored, tako da bi bilo vseeno,
če bi bila vrstica prej = cena
znotraj prvega
if
, torej pod visanj += 1
. Vendar takšna
rešitev zahteva malo dodatnega razmisleka, struktura programa je bolj
zoprna, pridobimo pa (skoraj) ničesar, zato raje napišimo, kot smo
napisali. Naloga programerja je napisati pravilen program, ne pa
dokazovati zvitosti z nepotrebnimi časovnimi optimizacijami ali
kratkostjo programa na račun razumljivosti.)
Če želimo vse rešiti v eni zanki, imamo v gornjem programu pravzaprav že skoraj vse, kar potrebujemo. Skupno število in cena prodanih predmetov je pač vsota cen in predmetov, ki sta jih (ločeno) kupili Ana in Berta. Le še najvišjo ceno si moramo zapomniti.
= 0
najvisja = berta = 0
ana = berta_skupno = 0
ana_skupno = 0
visanj = -1
prej for cena in open(ime_dat):
= int(cena)
cena if cena == -1:
if prej > najvisja:
= prej
najvisja if visanj % 2 == 1:
+= 1
ana += prej
ana_skupno else:
+= 1
berta += prej
berta_skupno = 0
visanj else:
+= 1
visanj = cena
prej
print("Prodanih predmetov:", ana + berta)
print("Najvišja cena:", najvisja)
print("Skupna cena:", ana_skupno + berta_skupno)
print("Ana:", ana, "predmetov za", ana_skupno)
print("Berta:", berta, "predmetov za", berta_skupno)
Prodanih predmetov: 5
Najvišja cena: 40
Skupna cena: 143
Ana: 2 predmetov za 42
Berta: 3 predmetov za 101
Če želite preveriti, ali vse deluje tudi za daljšo dražbo, se vrnite
nekaj celic višje, spremenite ime_dat
v
ime_dat = "drazba-dolga.txt"
in s Shift-Enter izvajajte
celico za celico.