IT Egzaminai/2022

Iš Pitonas.
16:34, 26 gegužės 2023 versija, sukurta Admin (aptarimas | indėlis)
(skirt) ← Ankstesnė versija | Dabartinė versija (skirt) | Vėlesnė versija → (skirt)

1 užduotis. Programavimo konkursas

Maksimalus vertinimas – 25 taškai

Į Lietuvos programavimo konkurso finalą pateko penki mokiniai, kurių rezultatai atrankos etape buvo geriausi. Finale mokiniams buvo pateiktos įvairaus sudėtingumo programavimo užduotys. Buvo nurodytas joms atlikti skirtas laiko limitas minutėmis ir jų maksimalus vertinimas taškais. Dalyviai programų failus kėlė į automatinio vertinimo sistemą, kuri tikrino, ar programos teisingos. Kai dalyvio programa pateikdavo teisingus visų testų rezultatus, sistema užfiksuodavo užduoties atlikimo laiką minutėmis. Jei dalyvis išsprendė uždavinį teisingai ir neviršijo tam uždaviniui skirto laiko limito, jis už tą uždavinį gavo maksimalų taškų skaičių; jeigu išsprendė teisingai, bet viršijo laiko limitą, gavo pusę maksimalaus taškų skaičiaus (rezultatas skaičiuojamas sveikaisiais skaičiais; pavyzdžiui, jei maksimalus užduoties vertinimas yra 3 taškai, tai už teisingą užduoties sprendimą, viršijus laiko limitą, dalyvis gavo 1 tašką); jeigu dalyvis uždavinio nesprendė arba išsprendė klaidingai, už jį gavo 0 taškų.

Parašykite programą, kuri rastų didžiausią finale surinktų taškų skaičių ir sudarytų dalyvių, surinkusių daugiausia taškų, sąrašą.

Pradiniai duomenys

Duomenys pateikiami tekstiniame faile U1.txt.

  • Pirmoje eilutėje užrašytas finale pateiktų uždavinių skaičius u (1 ≤ u ≤ 12).
  • Antroje eilutėje iš eilės nurodytas kiekvienam uždaviniui spręsti skirtas laiko limitas minutėmis. Duomenys atskirti vienu tarpo simboliu.
  • Trečioje eilutėje iš eilės nurodytas kiekvieno uždavinio maksimalus vertinimas taškais. Duomenys atskirti vienu tarpo simboliu.
  • Tolesnėse eilutėse užrašyti penkių finalo dalyvių duomenys: vardas (10 simbolių) ir kiekvienam uždaviniui spręsti sugaištas laikas minutėmis, užfiksuotas sistemos. Duomenys atskirti vienu tarpo simboliu. Buvo bent vienas dalyvis, kuris teisingai išsprendė bent vieną uždavinį.

Rezultatai

Rezultatus pateikite tekstiniame faile U1rez.txt.

  • Pirmoje eilutėje pateikite didžiausią finale surinktų taškų skaičių.
  • Tolesnėse eilutėse pateikite dalyvių, surinkusių didžiausią taškų skaičių, sąrašą: dalyvio vardas, jo teisingai išspręstų uždavinių skaičius ir šiems uždaviniams spręsti sugaištas laikas minutėmis. Duomenys atskirti vienu tarpo simboliu. Sąrašas surikiuotas pagal teisingai išspręstų uždavinių skaičių mažėjančiai.

Nurodymai

  • Sukurkite ir parašykite vieną funkciją, kuri apskaičiuoja dalyvio surinktų taškų skaičių, teisingai išspręstų uždavinių skaičių ir šiems uždaviniams spręsti sugaištą laiką minutėmis.

Duomenų ir rezultatų pavyzdžiai

Duomenų failo pavyzdys Paaiškinimai
6
10 10 20 15 15 20
2 2 5 3 3 5
Ignas      12 22 0 10 12 17
Skirmantas 5 12 0 40 12 30
Milda      10 10 20 22 31 23
Asta Ieva  5 0 17 10 23 23
Rima       8 0 14 23 12 23
  • Finale pateiktų uždavinių skaičius.
  • Kiekvienam uždaviniui spręsti skirtas laiko limitas minutėmis.
  • Kiekvieno uždavinio maksimalus vertinimas taškais.
  • Penkių finalo dalyvių duomenys:
    dalyvio vardas; kiekvienam uždaviniui spręsti sugaištas laikas minutėmis,
    užfiksuotas sistemos.
  • Skaičius 0 rodo, jog dalyvis to uždavinio nesprendė arba išsprendė klaidingai.
Rezultatų failo pavyzdys Paaiškinimai
13
Milda      6 116
Ignas      5 73
Asta Ieva  5 78
Rima       5 80
  • Didžiausias finale surinktų taškų skaičius.
  • Dalyvių, surinkusių didžiausią taškų skaičių, sąrašas:
    vardas; teisingai išspręstų uždavinių skaičius; šiems
    uždaviniams spręsti sugaištas laikas minutėmis.
  • Sąrašas surikiuotas pagal teisingai išspręstų uždavinių
    skaičių mažėjančiai

1 užduotis. Sprendimas

ĮVESTIS = "U1.txt"
IŠVESTIS = "U1rez.txt"

# funckiją failo skaitymui
# grąžina rezultatą: surinkti duomenys iš failo
def skaityk_failą():
  rezultatai = []

  with open(ĮVESTIS, "rt") as skaitomas_failas:
    uždavinių_skaičius = int(skaitomas_failas.readline())
    laiko_limitai = skaitomas_failas.readline().split()
    maks_balai = skaitomas_failas.readline().split()

    while True:
      duomenys = skaitomas_failas.readline()
      if not duomenys: break
      
      rezultatai.append(skaičiuok_rezultatą(duomenys, uždavinių_skaičius, laiko_limitai, maks_balai))

  return rezultatai

def skaičiuok_rezultatą(duomenys, uždavinių_skaičius, laiko_limitai, maks_balai):
  # pirmi 10 simbolių yra vardas
  rezultatas = {
    'vardas': duomenys[:10],
    'balai': 0,
    'laikas': 0,
    'išspręsta': 0
  }
  # po vardo yra išvardinti laikai praleisti sprendžiant užduotis. išskaidom į sąrašą
  trukmės = duomenys[11:].split()


  for i in range(uždavinių_skaičius):
    trukmė = int(trukmės[i])
    # jeigu 0, reiškias neišspręsta užduotis. nutraukiam darbą.
    if trukmė == 0: continue

    # pridedam reikšmes
    rezultatas['laikas'] += trukmė
    rezultatas['išspręsta'] += 1
    # paskaičiuojam ar maksimaliai balų gauta, ar tik puse
    if trukmė <= int(laiko_limitai[i]):
      rezultatas['balai'] += int(maks_balai[i])
    else:
      rezultatas['balai'] += int(maks_balai[i]) // 2

    # grąžinam suskaičiuota rezultatą
  return rezultatas

def atrink(rezultatai):
  atsakymas = {'balai': "0", "sąrašas": []}
  duomenys = []
  maks_taškų = 0

  # pereinam per sąrašą ir atrenkam, kiek yra daugiausiai surinkta taškų
  for r in rezultatai:
    if (r['balai'] > maks_taškų): maks_taškų = r['balai']
  
  atsakymas['balai'] = str(maks_taškų)

  # atrenkame sarašą dalyvių, su maksimaliai surinkta taškų
  for r in rezultatai:
    if (r['balai'] < maks_taškų): continue
    duomenys.append(r)

  # išrūšiuojame pagal išspręsta balų mažėjančia tvarka ir pagal užtrukta laiką didėjančia
  duomenys.sort(key=lambda x: (-x['išspręsta'], x['laikas']))

  # surenkame viską į atsakymą
  for d in duomenys:
    atsakymas["sąrašas"].append({
      "vardas": d['vardas'],
      "išspręsta": str(d['išspręsta']),
      "laikas": str(d['laikas'])
    })

  return atsakymas

def rašyk_į_failą(atsakymas):
  with open(IŠVESTIS, 'wt') as rašomas_failas:
    # pirmoje eilutėje atspausdiname maksimalų surinktą balų
    rašomas_failas.write(atsakymas['balai'])
    # kitose eilutėse išvedame išrikiuota sąrašą dalyvių surinkusių maks balus.
    for d in atsakymas['sąrašas']:
      rašomas_failas.writelines([
        '\n',
        d['vardas'],
        ' ',
        d['išspręsta'],
        ' ',
        d['laikas']
      ])

# pagrindinė programa
if (__name__ == "__main__"):
  # skaitome failą
  rezultatai = skaityk_failą()
  # atrenkame tik sąlygą atitinkamus rezultatus
  atsakymas = atrink(rezultatai)
  # surašome viską į failą
  rašyk_į_failą(atsakymas)

2 užduotis. Sportas namuose

Maksimalus vertinimas – 25 taškai

Juozas dirba namuose. Norėdamas daugiau judėti, jis nusprendė sausio mėnesį pradėti sportuoti – pagal galimybes atlikti namuose penkis įvairius pratimus. Juozas užrašuose žymėdavosi sportavimo duomenis: kiek kartų sportavo tam tikrą dieną, pratimų pavadinimus, kuriuo dienos metu juos atliko ir kiek laiko minutėmis skyrė nurodytiems pratimams atlikti.

Parašykite programą, kuri apskaičiuotų ir išvestų Juozo sausio mėnesį atliktų pratimų statistiką.

Pradiniai duomenys

Duomenys pateikiami tekstiniame faile U2.txt.

  • Pirmoje eilutėje užrašyta, kiek dienų d (1 ≤ d ≤ 31) sausio mėnesį sportavo Juozas.
  • Tolesnėse eilutėse užrašyti Juozo sportavimo duomenys: kiek kartų jis sportavo tam tikrą dieną s (1 ≤ s ≤ 7) ir pratimų duomenys: pratimo pavadinimas (14 simbolių), dienos metas (žodis Rytas, Diena, Vakaras; 7 simboliai) ir kiek laiko minutėmis Juozas sugaišo, atlikdamas nurodytą pratimą. Juozas gali tą patį pratimą atlikti tą pačią dieną daugiau negu vieną kartą ir bet kuriuo dienos metu. Duomenys atskirti vienu tarpo simboliu. Buvo bent viena diena, kai Juozas atliko bent vieną pratimą.

Rezultatai

Rezultatus pateikite tekstiniame faile U2rez.txt.

  • Įrašykite pratimų pavadinimus, dienų, kai Juozas atliko nurodytus pratimus, skaičių ir kiek iš viso laiko minutėmis sugaišo šiems pratimams atlikti. Pratimų sąrašą surikiuokite abėcėliškai. Duomenis eilutėje atskirkite vienu tarpo simboliu.
  • Po kiekvieno pratimo pavadinimo atskirose eilutėse parašykite žodžius Rytas, Diena, Vakaras ir nurodykite, kiek kartų sausio mėnesį Juozas nurodytu dienos metu atliko nurodytą pratimą. Duomenis eilutėje atskirkite vienu tarpo simboliu. Jeigu kurio nors pratimo kuriuo nors dienos metu nebuvo atlikta nė karto, duomenų apie šį dienos metą pateikti nereikia.

Nurodymai

  • Programoje naudokite struktūros duomenų tipo masyvą sportavimo duomenims saugoti.
  • Sukurkite ir parašykite funkciją, kuri sudarytų pratimų unikalių (nepasikartojančių) pavadinimų sąrašą. Python programavimo kalboje naudokite žodyno duomenų struktūrą arba struktūrą sudarykite, naudodami klases.

Duomenų ir rezultatų pavyzdžiai

Duomenų failo pavyzdys
8
2 Atsilenkimai   Rytas   10 Prisitraukimai Rytas   8
3 Atsispaudimai  Diena   8 Tempimas       Vakaras 8 Atsilenkimai   Vakaras 9
1 Svarmenys      Vakaras 11
3 Svarmenys      Diena   10 Svarmenys      Diena   12 Atsilenkimai   Diena   15
2 Atsilenkimai   Vakaras 22 Svarmenys      Vakaras 10
3 Svarmenys      Diena   15 Atsispaudimai  Diena   15 Atsispaudimai  Diena   5
2 Svarmenys      Rytas   23 Svarmenys      Vakaras 13
3 Atsispaudimai  Rytas   10 Atsispaudimai  Diena   12 Tempimas       Vakaras 10
Paaiškinimai
  • Kiek dienų sausio mėnesį sportavo Juozas.
  • Kiek kartų Juozas sportavo tam tikrą dieną; pratimų duomenys:
  • pratimo pavadinimas;
  • dienos metas (Rytas, Diena, Vakaras);
  • kiek laiko minutėmis sugaišta, atliekant nurodytą pratimą.
Rezultatų failo pavyzdys Paaiškinimai
Atsilenkimai   4 56
Rytas   1
Diena   1
Vakaras 2
Atsispaudimai  3 50
Rytas   1
Diena   4
Prisitraukimai 1 8
Rytas   1
Svarmenys      5 94
Rytas   1
Diena   3
Vakaras 3
Tempimas       2 18
Vakaras 2
  • Pratimo pavadinimas; dienų, kai Juozas atliko
    nurodytą pratimą, skaičius; kiek iš viso laiko
    minutėmis sugaišta šiam pratimui atlikti.
  • Dienos metas, kai buvo atliktas nurodytas
    pratimas; kiek kartų sausio mėnesį nurodytu dienos
    metu buvo atliktas nurodytas pratimas.
  • Sąrašas surikiuotas pagal pratimų pavadinimą
    abėcėliškai.

2 užduotis. Sprendimas

# Konstantos kurias naudosime programoje
DUOMENŲ_FAILAS = "U2.txt"
REZULTATŲ_FAILAS = "U2rez.txt"
PRATIMO_PAVADINIMO_ILGIS = 14
DIENOS_METO_ILGIS = 7
DIENOS_METAS_RYTAS = "Rytas  "
DIENOS_METAS_DIENA = "Diena  "
DIENOS_METAS_VAKARAS = "Vakaras"

# Klasė skirta konkretaus pratimo atlikimo duomenims saugoti
# Pratimo pavadimas bus naudojamas kaip raktas žodyne, tad jo saugoti klasėje papildomai nebereikia
class Sportavimas:
    def __init__(self):
        # Dienų kuriomis buvo atliktas pratimas indekasai
        self.dienos = []
        # Pratimo atlikimo bendra trukmė
        self.trukmė = 0
        # Kiek kartų pratimas atliktas konkrečiu dienos metu
        self.rytas = 0
        self.diena = 0
        self.vakaras = 0
    
    # Pridedamas naujas konkretaus pratimo atlikimo įrašas
    def pridėk_pratimą (self, diena, trukmė, dienos_metas):
        # Jeigu šią dieną pratimo dar nebuvo daryta, tai pažymime dienų sąraše, jog pratimas buvo atliktas
        if diena not in self.dienos:
            self.dienos.append(diena)
        self.trukmė += trukmė
        if dienos_metas == DIENOS_METAS_RYTAS:
            self.rytas += 1
        elif dienos_metas == DIENOS_METAS_DIENA:
            self.diena += 1
        elif dienos_metas == DIENOS_METAS_VAKARAS:
            self.vakaras += 1
            
    # Funkcija dienų skaičiui gauti
    def gauk_dienų_skaičių(self):
        return len(self.dienos)

# Funcija gražinanti uniklų pratimų sąrašą, kaip reikalaujama egazmino sąlygoje
def gauk_unikalų_pratimų_sąrašą(duomenys):
    return list(duomenys.keys());


# Funkcija nuskaitanti faile esančius duomenis
def skaityk_failą():
    sportavimas = {}
    with open(DUOMENŲ_FAILAS, "r") as skaitomas_failas:
        d = int(skaitomas_failas.readline())
        for i in range(0,d):
            # Nuskaitome s, kartu ir po jo einantį tarpą (1 ≤ s ≤ 7)
            s = int(skaitomas_failas.read(2))

            for _ in range(0,s):
                pratimas = skaitomas_failas.read(PRATIMO_PAVADINIMO_ILGIS)
                # Praleidžiame tarpą skiriantį pratimo pavadinimą ir dienos metą
                skaitomas_failas.read(1)
                dienos_metas = skaitomas_failas.read(DIENOS_METO_ILGIS)
                
                # Praleidžiame tarpą skiriantį pratimo pavadinimą ir dienos metą
                skaitomas_failas.read(1)                
                
                # Skaitom atlikimo laiką iki aptinkame tarpą
                perskaitytas_simobolis = skaitomas_failas.read(1)
                trukmė = 0

                # Skaitome po simbolį ir "sulipdome" trukmės skaičių
                while perskaitytas_simobolis.isdigit():
                    # Skaitome laiką po simbolį ir verčiame į skaičių
                    trukmė = trukmė * 10 + int(perskaitytas_simobolis)
                    perskaitytas_simobolis = skaitomas_failas.read(1)
                
                # Jeigu pratimas sutinkamas pirmą kartą - sukuriame naują `Sportavimas` tipo objektą
                if pratimas not in sportavimas:
                    sportavimas[pratimas] = Sportavimas()
                sportavimas[pratimas].pridėk_pratimą(i, trukmė, dienos_metas)

    return sportavimas

# Pagalbinė funkcija, skirta dienos meto duomenų įrašymui į failą
def rašyk_dienos_meto_duomenis_į_failą(rašomas_failas, dienos_metas, pratimų_kiekis):
    rašomas_failas.write(dienos_metas)
    rašomas_failas.write(" ")
    rašomas_failas.write(str(pratimų_kiekis))
    rašomas_failas.write("\n")


def rašyk_failą(duomenys):
    # Pasiimame žodyno raktus kad juos galėtume išrūšiuoti kaip sąrašą
    pratimai = gauk_unikalų_pratimų_sąrašą(duomenys)
    # Rūšiuojame pavadinimus
    pratimai.sort()
    with open(REZULTATŲ_FAILAS, "w") as rašomas_failas:
        for pratimas in pratimai:
            rašomas_failas.write(pratimas)
            rašomas_failas.write(" ")
            rašomas_failas.write(str(duomenys[pratimas].gauk_dienų_skaičių()))
            rašomas_failas.write(" ")
            rašomas_failas.write(str(duomenys[pratimas].trukmė))
            rašomas_failas.write("\n")
            if duomenys[pratimas].rytas > 0:
                rašyk_dienos_meto_duomenis_į_failą(rašomas_failas, DIENOS_METAS_RYTAS, duomenys[pratimas].rytas)
            if duomenys[pratimas].diena > 0:
                rašyk_dienos_meto_duomenis_į_failą(rašomas_failas, DIENOS_METAS_DIENA, duomenys[pratimas].diena)
            if duomenys[pratimas].vakaras > 0:
                rašyk_dienos_meto_duomenis_į_failą(rašomas_failas, DIENOS_METAS_VAKARAS, duomenys[pratimas].vakaras)

if __name__ == '__main__':
    duomenys = skaityk_failą()    
    rašyk_failą(duomenys)