1.naloga-programiranje

1.naloga-programiranje

Avtor: Lea Ostanek

RAZRED LETALO

BESEDILO NALOGE

Sestavi razred Letalo, ki naj vsebuje naslednje privatne lastnosti: doseg (int), maxVisina (int), maxHitrost (int), tip (string) in nosilnost (int). Sestavite tabelo objektov tipa Letalo z naključnimi, a smiselnimi podatki. Rešite naslednje naloge:

Razred naj bo opremljen s konstruktorjem, ki sestavi novo letalo danega dosega, maksimalne višine, maksimalne hitrosti, tipa in nosilnosti.

Izpiši tipe vseh letal, s katerimi se lahko odpravimo na polet, dolg 1500 km.

  • Ugotovili so, da so pri vnosu podatkov vsem letalom katerih tip se začne na črke od 'A' do 'M', vnesli za 500m prenizko maksimalno višino. Popravi podatke za vsa taka letala v tabeli.
  • Izpiši tipe tistih letal s katerimi lahko kar se da hitro prepelješ m ton tovora. Pri odločanju katera letala boš uporabil, uporabi naslednji postopek: najprej vzamemo najhitrejše letalo in ga polno naložimo. Če je ostalo še kaj tovora, vzamemo naslednje najhitrejše letalo. Če še ni ves tovor naložen, vsemi naslednje najhitrejše letalo …
  • Za polet od Brnika do Muenchna bo potrebno preleteti Alpe. Zaradi varnostnih predpisov mora letalo leteti vsaj na višini 3000m. Koliko letal imamo na izbiro, če moramo prepeljati 5 potnikov s prtljago vred. Letalska družba, lastnica letal v tabeli, ki je parameter metode, za težo letala s potnikom vzame 105kg.

Vsi razredi naj obvezno vsebujejo naslednji dve metodi (torej jih morate obvezno napisati!

  • DodajNaDatoteko(self, imeDatoteke), ki objekt self zapiše (doda – glej domačo nalogo 6) vrstico, kjer doda vse podatke objekta, med sabo ločene z znakom ';'
  • PreberiZDatoteke(self, imeDatoteke), ki vrne tabelo objektov, kjer posamezni objekt vsebuje podatke, ki so zapisani v posamezni vrstici datoteke, med sabo ločeni z znakom '; (torej v obliki, kot jih zapiše prejšnja metoda).

Python datoteka:

Tu je datoteka v kateri se nahaja program razreda Letalo: razred Letalo

REŠEVANJE

Opis problema

Naloga zahteva, da sestavimo razred Letalo, opremiti pa ga moramo s konstruktorjem, ki sestavi letalo iz danega dosega, maksimalne višine, maksimalne hitrosti, tipa letala in nosilnosti. Za reševanje problema je potrebno najprej ustvariti smiselno tekstovno datoteko, v kateri so po vrsticah zapisani podatki, kot jih zahteva konstruktor.

Razlaga algoritma

V konstruktorju je potrebno podati tudi stavke assert , ki nam bodo sprožili napako, če kateri od podatkov ne bo podan pravilno. Lahko ustvarimo tudi get in set metode, ki iz konstruktorja dobijo določene podatke ali pa jih popravijo, ter metodi str in repr, ki poskrbita za ustrezen izpis.


import types

class Letalo:
    ''' Ustvarimo razred Letalo s konstruktorjem, ki določa doseg,
        višino, hitrost, tip in nosilnost letala.'''

    def __init__(self, doseg, visina, hitrost, tip, nosilnost): # konstruktor
        assert type(doseg) == int, 'Doseg letala mora biti podan kot število.'
        self.doseg = doseg
        assert type(visina) == int, 'Višina mora biti podana kot število.'
        self.maxVisina = visina
        assert type(hitrost) == int, 'Hitrost mora biti podana kot število.'
        self.maxHitrost = hitrost
        assert type(tip) == str, 'Tip letala mora biti podan kot niz.'
        self.tip = tip
        assert type(nosilnost) == int, 'Nosilnost mora biti podana kot število.'
        self.nosilnost = nosilnost

 def getDoseg(self):
        return self.doseg

    def setDoseg(self, doseg):
        assert type(doseg) == int, 'Doseg letala mora biti podan kot število.'
        self.doseg = doseg

    def getVisina(self):
        return self.maxVisina

    def setVisina(self, visina):
        assert type(visina) == int, 'Višina mora biti podana kot število.'
        self.maxVisina = visina

    def getHitrost(self):
        return self.maxHitrost

    def setHitrost(self, hitrost):
        assert type(hitrost) == int, 'Hitrost mora biti podana kot število.'
        self.maxHitrost = hitrost

    def getTip(self):
        return self.tip

    def setTip(self, tip):
        assert type(tip) == str, 'Tip letala mora biti podan kot niz.'
        self.tip = tip

    def getNosilnost(self):
        return self.nosilnost

    def setNosilnost(self, nosilnost):
        assert type(nosilnost) == int, 'Nosilnost mora biti podana kot število.'
        self.nosilnost = nosilnost

    def __repr__(self):
        return str(self.doseg)+';'+str(self.maxVisina)+';'+str(self.maxHitrost)+';'+self.tip+';'+str(self.nosilnost)

    def __str__(self):
        return self.__repr__()

Metodo dodajNaDatoteko skonstruiramo tako, da najprej odpremo neko datoteko tako da lahko nanjo dodajamo vrstice na konec datoteke. To nam omogoča zapis with open(imeDatoteke, 'a') as datoteka (tak zapis avtomatsko datoteko po koncu izvajanja programa tudi zapre).

def dodajNaDatoteko(self, imeDatoteke):
        ''' Program na datoteko doda vrstico v kateri so vsi podatki objekta,
            ločeni pa so z znakom ; '''
        with open(imeDatoteke, 'a') as f1: # odpremo datoteko za dodajanje
            f1.write('\n' + self.__repr__()) # vrstico zapišemo na datoteko

Pri metodi preberiIzDatoteke moramo prav tako odpreti datoteko, le da tu uporabimo zapis 'r', ki nam omogoča samo branje podatkov iz datoteke. Seveda moramo predhodno ustvariti prazen seznam, s pomočjo katerega bomo potem vrnili zahtevane podatke. Nato za vsako vrstico v datoteki ustvarimo seznam s pomočjo ukaza append, v katerem z ukazom strip odstranimo preskoke v nove vrstice (zapis preskoka v novo vrstico v Pythonu: '\n'). Na koncu še vrnemo seznam.

def preberiIzDatoteke(self, imeDatoteke):
        ''' Program iz datoteke prebere vse podatke in jih zapiše v
            seznam, v katerem so podseznami ločeni z znakom ; '''
        sez = []
        with open(imeDatoteke, 'r') as f: # odpremo datoteko za branje
            for v in f:
                sez.append(v.strip('\n')) # seznamu dodajamo vrstice, ki jim
                                          # odstranimo skok v novo vrstico
            return sez # seznam vrnemo

Pri sestavljanju metode, ki nam bo izpisala tipe letal, s katerimi se lahko odpravimo na polet dolg 1500 km, ravno tako kot pri prejšnji metodi ustvarimo prazen seznam, odpremo datoteko samo za branje in na konec seznama dodamo vrstice datoteke, v katerih z ukazom strip odstranimo preskoke v nove vrstice in z ukazom split odstranimo podpičja. Nato gremo s for stavkom pregledati celoten seznam, ki smo ga ustvarili, pri čemer pregledujemo ali je doseg letala večji ali enak 1500 km, in če je to res potem izpišemo tip letala s katerim lahko preletimo 1500 km.

def polet1500(self, imeDatoteke):
        ''' Program izpiše tipe vseh letal, s katerimi se lahko odpravimo
            na polet dolg 1500 km. '''
        sez = []
        with open(imeDatoteke, 'r') as f: # odpremo datoteko za branje
            for v in f:
                sez.append(v.strip('\n').split(';')) # split --> odstranimo podpičja
            #return sez
            for i in sez:
                if int(i[0]) >= 1500:
                    print(i[3])

Metodo, ki nam bo popravila maksimalno višino, ki jo letalo doseže za 500m, skonstruiramo tako, da popravljene podatke zapišemo na novo datoteko, ki jo ustrezno poimenujemo. To storimo tako, da odpremo najprej datoteko na kateri so zapisani podatki o letalu, nato pa odpremo še eno datoteko, v katero se bodo zapisali popravljeni podatki. Pri tem moramo paziti, da popravimo višino samo letalom, katerih tip se začne na prvo črko med A in M, pri ostalih tipih pa višina ostane nespremenjena. Zapisovanje na novo datoteko nam omogoča ukaz write(), kjer v oklepajih podamo tisto kar želimo zapisati.


def popraviVisino(self, imeDatoteke, popravljenaDat, popravi = 500):
    ''' Popravimo višino vsem tipom letal, ki se začenjo na A do M,
    za 500, in popravljene podatke zapišemo na novo datoteko.'''
    sez = []
    with open(imeDatoteke, 'r') as f1:
        with open(popravljenaDat, 'a') as dat: # odpremo datoteko na katero
                                               # bomo zapisali popravljene
                                               # podatke
            for v in f1:
                sez.append(v.strip('\n').split(';'))
                    for i in sez:
                        # preverimo, če se tip letala prične na ustrezno črko
                        if i[3][0] == 'A' or i[3][0] == 'B' or i[3][0] == 'C' or i[3][0] == 'D' or i[3][0] == 'E' \
                          or i[3][0] == 'F' or i[3][0] == 'G' or i[3][0] == 'H' or i[3][0] == 'I' or i[3][0] == 'J' \
                          or i[3][0] == 'K' or i[3][0] == 'L' or i[3][0] == 'M':
                            i[1] = int(i[1]) + popravi # višino popravimo za ustrezno višino
                dat.writelines(sez + '\n') # na novo datoteko zapišemo popravljene podatke

V metodi, katera nam bo izpisala tipe letal s katerimi lahko prepeljemo m ton tovora, moramo podati stavek assert, ki nam bo, v primeru, da ne bomo vnesli pozitivnega celega števila za m, sprožil napako. Kot v vseh prejšnjih metodah ustvarimo prazen seznam, odpremo datoteko za branje in na konec seznama dodamo vrstice iz datoteke. Nato s for zanko preverjamo ali je katera od nosilnosti letala enaka teži tovora. Če se to zgodi kar izpišemo tip letala, sicer pa je potrebno izpisati najprej najhitrejše letalo, od m tovora, ki jo je potrebno prepeljati, odšteti nosilnost letala, in postopek ponavljati dokler ni ves tovor prepeljan.


    def prevoz(self, m, imeDatoteke):
        assert type(m) == int and m > 0, 'Teža mora biti podana kot celo število.'
        sez = []
        with open(imeDatoteke, 'r') as f2:
            for v in f2:
                sez.append(v.strip('\n').split(';'))
                for i in sez:
                    if int(i[4]) == m: # če je teža tovora enaka nosilnosti letala,
                                       # kar izpišemo tip letala
                        print(i[3])

TESTNI PROGRAM

Python datoteka:

Tu je datoteka v kateri se nahaja testni program: Testni program

S testnimi primeri preverjamo, ali program res vrača zahtevane vrednosti. To storimo tako, da najprej odpremo novo okno in vanj uvozimo imenik, ki ga želimo preverjati. Nato skonstruiramo neko letalo, ki vsebuje vse podatke, nato pa s stavki assert preverimo ali v programu res dobimo vrnjene želene podatke. Če jih dobimo, se testni program lepo izvede.


import letalo

letalo = letalo.Letalo(500, 150, 180, 'Mini', 380)
assert letalo.getDoseg() == 500
assert letalo.getVisina() == 150
assert letalo.getHitrost() == 180
assert letalo.getTip() == 'Mini'
assert letalo.getNosilnost() == 380

Nadaljnje testne primere skonstruiramo tako, da v podane parametre namesto tipov vrednosti, ki jih zahtevamo, podamo napačne in poskusimo, če deluje brez napak. V primeru, da program najde napake, se bodo le-te izpisale, sicer se ne bo zgodilo nič.


try:
    letalo = letalo.Letalo('500', 150, 180, 'Mini', 380) # doseg podamo v nizu
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo([456,456], 150, 180, 'Mini', 380) # doseg podamo v seznamu
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo(bla, 150, 180, 'Mini', 380) # doseg podamo s črkami
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo(500, '150', 180, 'Mini', 380) # višino podamo v nizu
    print('NAPAKA.')
except Exception: pass


try:
    letalo = letalo.Letalo(500, '150', 180, 'Mini', 380) # višino podamo v nizu
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo(500, [150], 180, 'Mini', 380) # višino podamo v seznamu
    print('NAPAKA')
except Exception: pass

try:
    letalo = letalo.Letalo(500, bla, 180, 'Mini', 380) # višino podamo s črkami
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo(500, 150, bla, 'Mini', 380) # hitrost podamo s črkami
    print('NAPAKA.')
except Exception: pass

try:
    letalo = letalo.Letalo(500, 150, '180', 'Mini', 380) # hitrost podamo v nizu
    print('NAPAKA.')
except Exception: pass

Wink

0%
0%