Minta nagy NZH

Czirkos Zoltán · 2020.11.28.

Minta nagy ZH, néhány feladattal.

Minta nagy ZH. Tudnivalók a feladatsor felhasználásával kapcsolatban: lásd itt. Nem minden évben ugyanakkor van a NZH, nem minden évben pont ugyanaddig terjedt a NZH anyaga; ezzel kapcsolatban lásd az aktuális évi előadásanyagot és tájékoztatást.

Tizennégy betű, tizennégy osztó

Az 1245 szám számjegyeit betűkkel, magyarul kiírva összesen 3+5+4+2=14 betűt használunk fel: „egy kettő négy öt”. Írj programot, amelyben megkeresed a legnagyobb négyjegyű számot, amely osztóinak száma 14 (beleértve saját magát és az 1-et is), és a számjegyeit leírva 14 betűt kell felhasználni! Írd ki, melyik ez a szám, vagy ha nincs ilyen, akkor azt!

Ne írj felesleges kódot! Használj fentről lefelé tervezést, írj a két részfeladathoz függvényeket (hány betű, osztók száma)! Emlékeztető: egy szám utolsó számjegyét eldobni tízzel való egész osztás segítségével tudod, míg magát az utolsó számjegyet a tízzel osztás maradéka adja meg.

Megoldás
def osztokszama(n):
    db = 2
    for i in range(2, n//2 + 1):
        if n % i == 0:
            db += 1
    return db

def szamhossz(n):
    # nulla egy kettő három négy öt hat hét nyolc kilenc.
    # ha sztringek listáját használjuk, és len() mindig, az is jó.
    hosszak = [ 5, 3, 5, 5, 4, 2, 3, 3, 5, 6 ]
    
    osszeg = 0
    while n > 0:
        osszeg += hosszak[n % 10]
        n //= 10
    return osszeg

def main():
    megvan = False
    for i in range(9999, 1000-1, -1):
        if szamhossz(i) == 14 and osztokszama(i) == 14:
            megvan = True
            break

    if megvan:
        print('A keresett szam:', i)
    else:
        print('Nincs ilyen szam.')

main()

ProgAlap eredmények

1 3 ***
2 5 *****
3 7 *******
4 8 ********
5 6 ******
átment 26 fő
  0–39    1
 40–54    2
 55–69    3
 70–84    4
 85–100   5

Jobb oldalt a ProgAlap tárgy pontozási táblázatát látod: a félév végéig megszerzett pontokból kialakuló jegyet.

Írj függvényt, amely egy pontszámból jegyet csinál!

Erre építve egy olyan programot kell írnod, amelyik soronként beolvassa a hallgatók pontszámait, és statisztikát készít a jegyekről: hány jeles, hány jó, ... lett. A bemenet végét egy üres sor jelzi. A statisztikából kell a szintén jobb oldalt látható formában grafikont készíteni: minden sorban a jegy, a létszám, aztán annyi csillag, amennyi a létszám. Írd ki azt is a grafikon alá, hogy hányan teljesítették a tárgyat!

Legyen hatékony az adatszerkezeted, NE tárolj el feleslegesen adatsort!

Megoldás
def osztalyoz(pont):
    if pont <= 39:
        return 1
    if pont <= 54:
        return 2
    if pont <= 69:
        return 3
    if pont <= 84:
        return 4
    return 5

def main():
    db = [0] * 5
    sor = input()
    while sor != "":
        pont = int(sor)
        db[osztalyoz(pont) - 1] += 1
        sor = input()

    for jegy in range(1, 5 + 1):
        print('{} {:3} {}'.format(jegy, db[jegy - 1], '*' * db[jegy - 1]))
    # nem kötelező a format használata
    # a * karaktereket lehet ciklussal is

    print('átment {} fő'.format(sum(db[1:])))

main()

Útiterv

Egy kamionsofőr autópályán vezet, 100 km/h-val haladva. A benzinkutak egymástól való távolságát előre ismeri a térképről. Minden másfél órányi vezetés után pihenőt kell tartania. Szeretne egy útitervet készíteni: előre eldönteni azt, hogy melyik benzinkúton kell majd pihennie. A szabály egyszerű: minden olyan benzinkútnál megáll, amelynél ha nem tartana pihenőt, a következő kúthoz már csak úgy érne el, ha túllépné a másfél órás egyfolytában vezetést.

Írj programot, amely soronként beolvassa az egyes benzinkutak közötti távolságot km-ben! Előbb megkapja a távolságok számát, magukat a távolságokat (valós számok, soronként egy darab). Végül pedig írja ki az útitervet. Például ha bemenetként a 45.3, 30.7, 64, 35, 72 számsort kapja (km-ek), akkor a kimenet az alábbi kell legyen:

45.3 km, 30.7 km, 64 km, szünet.
35 km, 72 km, vége.

(Az első három táv összesen 140 km, amihez 1,4 óra kell. Ha megtette volna a következő 35 km-t, ahhoz már 1,75 óra kellett volna, ezért jött a szünet.)

Megoldás
def main():
    sebesseg = 100  # km/h
    szunet = 1.5    # h

    n = int(input("n = "))
    tavok = []
    for _ in range(n):
        tavok.append(float(input("Táv (km): ")))

    megtett = 0     # km
    for tav in tavok:
        if (megtett + tav)/sebesseg > szunet:
            print('szünet.')
            megtett = 0
        print('{} km, '.format(tav), end='')
        megtett += tav

    print('vége.')

main()

A hiányos sorozat

Kapunk egy számsort, amiről tudjuk, hogy egy számtani sorozat elemei. Pontosan egy elem hiányzik belőle, de előre nem tudjuk, melyik. Adjuk meg a hiánytalan sorozatot, megjelölve a hiányzó elemet! Például:

Bemenet: 1 3 5 7 11
Kimenet: 1 3 5 7 *9* 11

Megjegyzés: nem az első elem hiányzik, és nem is az utolsó (mert akkor olyan lenne, mintha nem hiányozna egyik sem). És azt is lehet tudni, hogy legalább három elem van.

Megoldás

Érdemes előbb a sorozat differenciáját (növekményét) meghatározni. Arra jöhetünk rá, hogy ehhez elég a számsor első három elemét megvizsgálni. Ugyanis ha ilyesmit látunk:

1 3 5

Akkor az első három elem rendben van, mert közöttük d = 2 a különbség mindkét helyen; nem hiányzik elem sem az 1 és a 3 közül, sem a 3 és az 5 közül. Ha ezt látnánk:

1 3 7

Akkor tudnánk, hogy a 3 és a 7 közül tűnt el a szám, mivel ott nagyobb a különbség (d = 4), mint az első két elem között (d = 2). A sorozat differenciája pedig 2 kell legyen. Ha pedig ezt kapjuk:

1 5 7

Akkor az első pár között van a hiány, mert ott d = 4, a második párnál viszont csak d = 2. Összefoglalva: a sorozat differenciája az első két elempár között látott különbségek közül a kisebbik.

Ha megvan a differencia, akkor csak ki kell írni a sorozat elemeit, és közben figyelni, mennyi kellene legyen a kiírt elem. Ha nem annyi, akkor megvan a hiány. Mindig annyi kellene legyen, mint az előző elem plusz a differencia. A kiírásnál megtehetjük azt is, hogy kiírjuk a sorozat elején lévő elemet külön (azt még nincs mihez hasonlítani). De tekinthetjük úgy is, mintha a sorozat első eleme előtt sorozat[0] - d lett volna.

sor = []
while True:
    try:
        sor.append(int(input()))
    except:
        break

diff = min(sor[1]-sor[0], sor[2]-sor[1])

elozo = sor[0] - diff
for x in sor:
    if elozo + diff != x:
        print("*{}*".format(elozo + diff), end=" ")
    print(x, end=" ")
    elozo = x

Érdemes elgondolkozni azon, hogy megoldható-e ez a feladat lista nélkül. Emlékezzünk vissza: ha sorban kell feldolgozni az elemeket, és nem kell sem előre, sem hátra látni a sorozatban, akkor nincs szükség az adatok tárolására. (Spoiler alert: megoldható lista nélkül.) Kegyelemdöfésként pedig jegyezzük meg, hogy valójában a hiányos sorozat differenciája még ennél egyszerűbben is meghatározható: (sor[-1] - sor[0]) / len(sor), vagyis az utolsó és az első elem különbsége, osztva a sorozat hosszával.