Tag Archives: Python

Informatika emelt érettségi 2008. május – Programozás (SMS)

SMS

Feladat: https://www.oktatas.hu/pub_bin/dload/kozoktatas/erettsegi/feladatok2008tavasz/e_info_08maj_fl.pdf

Esemes Ernő szenvedélyes SMS-küldő, ezért a MaMobil nevű cég tesztelésre kérte fel. Ehhez egy új, kézreálló telefont adnak, melynek tesztüzemben egyetlen hátránya, hogy legfeljebb az először érkező 10 darab, egyenként legfeljebb 100 karakteres üzenetet tud eltárolni. Ha ettől több üzenet van, akkor azokat korlátlan számban a szolgáltató őrzi meg a hangpostá- hoz hasonlóan, tehát azokhoz csak bizonyos díj fejében juthat hozzá. Az üzenetek nem tartalmazhatnak ékezetes karaktereket. Az sms.txt állomány első sorában az a k szám olvasható, amely megadja, hogy hány üzenet érkezett a készülékre a mai napon. Az érkező üzenetek száma legalább egy, de nem haladja meg a 100 darabot. Minden üzenethez 2 sor tartozik. Az első sor szerkezete a következő: először az érkezés órája (szám), érkezés perce (szám), telefonszám (pontosan 9 jegyű szám), a másodikban pedig az üzenet (legfeljebb 100 karakternyi szöveg) található. Az állományban az üzenetek számát követően k×2 sor szerepel. Az üzenetek érkezési idő szerint növekvően rendezettek.

Például:

Készítsen programot sms néven, amely az alábbi kérdésekre válaszol! Ügyeljen arra, hogy a program forráskódját a megadott helyre mentse!
A képernyőre írást igénylő részfeladatok eredményének megjelenítése előtt írja a képernyőre a feladat sorszámát! (Például 3. feladat: )

1. feladat

Olvassa be az sms.txt állományban talált adatokat, s annak felhasználásával oldja meg a következő feladatokat! Ha az állományt nem tudja beolvasni, akkor a benne található adatok közül az első tíz üzenet adatait jegyezze be a programba, s úgy oldja meg a feladatokat.

Ez egy az eddigiektől eltérő fájl beolvasást kíván, mert egy ciklusban két sort is illene beolvasni. Természetesen másként is meg lehet oldani, de így legalább a readline() függvényt is be tudom mutatni.

print("1. feladat")
smsList = []
egySms = []
with open('sms.txt', 'r') as smsek:
    smsSzam=int(smsek.readline().strip())
    for i in range(0, smsSzam):
        egySms.append(smsek.readline().strip().split(" "))
        egySms.append(smsek.readline().strip())
        smsList.append(egySms)
        egySms = []
Magyarázat:

Az állományokat, csak szekvenciálisan tudjuk olvasni. Ehhez minden programozási nyel egy rekord léptetőt alkalmaz, amely ha egy sort beolvasunk automatikusan a következő sorra lép. Így minden olvasás után a következő sor olvasása következik.

smsSzam = int(smses.readline().strip()) az első sort vagyis a 30-at olvassa be az sms.txt-ből. Az ezt követő for ciklus első readline() utasítása, már az állomány következő sorát adja eredményül. Ezt a split(‘ ‘) függvénnyel szétszedem egy listába (óra, perc, telefonszám). Ezek után a listához hozzáadom még az sms.txt következő sorát, ami az üzenet.

Az így kapott listát teszem az smsList listába. Így ennek minden egyes sora egy listát (óra, perc, telefonszám)  és az üzenetet fogja tartalmazni, az összes számomra fontos adatot.

A ciklusmag utolsó sora egy nem túl elegáns megoldás, mert az egySms lista objektumot kiürítem, de ez így nem módosítja az smsList listában lévő objektumokat

2. feladat

A fájlban tárolt utolsó üzenet érkezésekor melyik üzenet a legfrissebb a telefon memóriájában? Írja az üzenet szövegét a képernyőre!

print("2. feladat")
utolsoSMS = len(smsList)
print(smsList[utolsoSMS-1][1])

Mivel az smsList egy sora egy listát és egy üzenetet tartalmaz ezért a 2. elem (index = 1) az üzenet az utolsó sorban. Az utolsoSMS a lista hossza, de a lista utolsó indexű tagja eggyel kevesebb.

3. feladat

Adja meg a leghosszabb és a legrövidebb üzenetek adatait! Ha több azonos hosszúságú üzenet van, akkor elegendő csak egyet-egyet megadnia! A képernyőn óra, perc, telefonszám, üzenet formában jelenítse meg az adatokat!

Ez egy kiváló példa a maximum kiválasztás tételére, amely pontosan ugyan olyan mint a minimum kiválasztás tétele csak egy relációs jel a pici különbség.

Tegyük fel, hogy a lista legelső eleme a legnagyobb adat. Meg kell vizsgálni az összes többi elemet a listában, össze kell hasonlítani az elsővel. Amennyiben találunk nála nagyobbat, az lesz az újabb feltételezett maximumértékünk. Az összehasonlítást a lista utolsó eleméig el kell végezni.

MAXIMUMKIVÁLASZTÁS tétele
Adott egy N elemű A sorozat. Adjuk meg a sorozat legnagyobb elemét.
Eljárás:
	INDEX:=0
	Ciklus I=1-től N-ig
		Ha A(INDEX) < A(I) akkor INDEX:=I
	Ciklus vége
        Ki(INDEX)
Eljárás vége.

A megoldás fele:

print("3. feladat")
index = 0
for i in range(1,len(smsList)):
    if len(smsList[index][1]) < len(smsList[i][1]):
        index = i
print("A leghosszabb üzenet adatai:")
ora = smsList[index][0][0]
perc = smsList[index][0][1]
tel = smsList[index][0][2]
uzenet = smsList[index][1]
print("%s:%s tel: %s üzenet: %s"%(ora,perc,tel,uzenet))

Szerintem menni fog a legrövidebb egyedül is! 🙂

Folytatása következik….

Informatika emelt érettségi 2016. május (magyar) – Programozás (Zár)

Zár

http://dload.oktatas.educatio.hu/erettsegi/feladatok_2016tavasz_emelt/e_infma_16maj_fl.pdf

Egy ajtót elektronikus zárral láttak el. A zárat egy ismétlődő pontokat nem tartalmazó, megfelelő irányban rajzolt, törött vonalból álló mintával lehet nyitni. A minta megadását egy szabályos tízszög segíti, amelynek csúcsait 0-tól 9-ig sorszámozták, így a leghosszabb használható minta 10 számjegyet tartalmazhat. Az ajtót nyitó kódszám megadásánál csupán az alakzat és annak iránya érdekes, ezért a 135 mintával nyitható zárat a 802 is nyitja (vagy akár a 024 kódszám is), de a 208 nem. Tehát ebben a mintában a zár csak az óramutató járásával megegyező irányban nyílik. A nyitás az egyes számok egymást követő megérintésével történik.

Az ajto.txt fájl soronként egy-egy nyitási próbálkozás adatait tartalmazza. A fájlban legfeljebb 500 sor, soronként legalább 3, legfeljebb 10 karakter lehet.

Készítsen programot, amely az ajto.txt állomány adatait felhasználva az alábbi kérdésekre válaszol! A program forráskódját mentse zar néven! (A program megírásakor a felhasználó által megadott adatok helyességét, érvényességét nem kell ellenőriznie, feltételezheti, hogy a rendelkezésre álló adatok a leírtaknak megfelelnek.) A képernyőre írást igénylő részfeladatok eredményének megjelenítése előtt írja a képernyőre a feladat sorszámát (például: 3. feladat:)! Ha a felhasználótól kér be adatot, jelenítse meg a képernyőn, hogy milyen értéket vár! Az ékezetmentes kiírás is elfogadott.

Megoldások: 1. 2. 3. 4. 5. 6. 7.

1. feladat

Olvassa be és tárolja el az ajto.txt fájl tartalmát!

print('1. feladat')
probalkozasok=[]
with open('ajto.txt', 'r', encoding='utf-8') as ajto:
    for egyProba in ajto:
        probalkozasok.append(egyProba.strip())
1. feladat megoldása

A megnyitott ajto.txt-t soronként végigjárva (for in), a végéről a sortörést (\n) eltávolítva a strip() metódusssal, hozzáfűztem az előkészített probalkozasok listához.

2. feladat

Kérjen be a felhasználótól egy számjegysorozatot, amely a zár kódszáma lesz! (Feltételezheti, hogy a felhasználó ismétlődés nélküli jelsorozatot ad meg.) A teszteléshez használhatja a 239451 sorozatot is.

print('2. feladat')
ujProba = input('Adja meg, mi nyitja a zárat! ')
#ujProba = '239451'
2. feladat megoldása

Hát izé, szerintem meg lesz ennek még a böjtje …. 🙂

3. feladat

Jelenítse meg a képernyőn, hogy mely kísérleteknél használták a nyitáshoz pontosan az előző feladatban beolvasott kódszámot! A sorok számát egymástól pontosan egy szóközzel válassza el! (A sorok számozását 1-től kezdje!)

Az ötletem a következő:
Vonjuk ki az ujProba minden egyes karakterének megfelelő egész számból a régi próbálkozások megfelelő karaktereinek szám értékét és ha a különbségük végig állandó, akkor a két kód azonos. Persze ez csak akkor működik, ha a kivonandó végig vagy nagyobb vagy kisebb (esetleg egyenlő) a kisebbítendőnél.

Pl: 135 és 802 estén 1-8=-7, 3-10=-7, 5-12=-7. Mint a példából látható, ha kisebb a kivonandó, mint a kisebbítendő, akkor a kivonandóhoz egyszerűen hozzáadok 10-t.

Mivel ez a feltételes kivonás igen megbonyolítaná a kódot ezért a különbség kiszámítását egy függvényre bízom.

def substract(uP, rP):
    if uP <= rP:
        return uP - rP
    else:
        return uP-(rP+10)
két szám távolsága

Az uP az új kód egy karakterének számértéke, az rP a régi kód számértéke.

Ezután már megírható az az eldöntés tétel, amely az oly gyakori kivétel kiemeléssel kezdődik.

Eldöntés tétele

Általános feladat: Adott egy N elemű sorozat és egy, a sorozat elemein értelmezett T tulajdonság. Az algoritmus eredménye: annak eldöntése, hogy van-e a sorozatban legalább egy T tulajdonsággal rendelkező elem.

Algoritmus:

Eljárás
  i := 0
  Ciklus amíg i<N és A(i) nem T tulajdonságú
    i:=i+1
  Ciklus vége
  VAN := i<N
Eljárás vége

Forrás: programozás | Érettségi

Nézzük a konkrét megoldást:

nyitok = []
sorszam = 0
for egyProba in probalkozasok:
    sorszam += 1
    if len(egyProba) == len(ujProba):
        s = substract(int(ujProba[0]), int(egyProba[0]))
        i = 1
        while i < len(ujProba)-1 and s == substract(int(ujProba[i]), int(egyProba[i])):
            i += 1
        if i == len(ujProba)-1:
            nyitok.append(sorszam)
print("A nyitó kódszámok sorai: ", end='')
#print(" ".join('{: >1}'.format(str(e)) for e in nyitok))
print(" ".join(str(e) for e in nyitok))
3. feladat megoldása

A nyitok listába fogom gyűjteni az azonos kombinációkat. A sorszam az éppen vizsgált régi próbálkozás sorszáma. Végig járom az összes régi próbálkozást (for in). Csak akkor kezdek vizsgálódni, az új próbálkozás (ujProba) hossza egyenlő a régi próbálkozás (egyProba) hosszával.

Az első karaktereinek különbségét kiszámolom és tárolom (s), és beállítom i értékét 1-re, mert ez a karakter mutatója és a második indexe 1.

Kezdődik az eldöntés tétele, amelynek két feltétele és (and) kapcsolatban van egymással. Az első arra figyel, hogy mikor ér a ciklus az új próba (i < len(ujProba)-1) végére, a másik feltétel azt figyeli, hogy a különbség azonos-e az első két számjegy különbségével. Ha bármelyik hamissá válik a ciklus véget ér.

Ha az első szakítja meg (i < len(ujProba)-1),  vagyis válik hamissá az azt jelenti, hogy végig egyenlő volt különbség, tehát a két kód azonos. Ha másik szakítja meg, akkor a két kód különböző.

Hogy melyik szakította meg a ciklus futását a ciklust követő elágazás  (if) hivatott eldönteni. Vagyis ha elértem a kód végét a sorszámát hozzáadom a nyitok listához.

Ezek után már csak a lista elemeinek kiírás van hátra. Persze egy elágazás itt sem ártana, hiszen, ha a nyitok hossza nulla, akkor azt kellene kiírnom, hogy nincs egyező sorozat. 🙂

A kiírásnál direkt hagytam benne megjegyzésként a formázási lehetőséget is tartalmazó print() utasítást. Bővebb leírást róla a Lottó feladatnál találsz.

4. feladat

Adja meg, hogy melyik az első olyan próbálkozás, amely ismétlődő karaktert tartalmaz! Ha nem volt ilyen, írja ki a „nem volt ismétlődő számjegy” üzenetet! (A sorok számozását 1-től kezdje!)

A megoldás itt is egy eldöntés tétel alkalmazása, de az érthető és átlátható kód kedvéért a döntéselhalasztás elvét alkalmazom:

i=0
while i<len(probalkozasok) and nincsIsmetles(probalkozasok[i]):
    i+=1
if i<len(probalkozasok):
    print("Az első ismétlődést tartalmazó próbálkozás sorszám: %d"%(i+1))            
else:
    print("nem volt ismétlődő számjegy")
4. feladat (döntés elhalasztás elvének alkalmazása)

Végig a próbálkozásokon, addig amíg nincs ismétlődés. Ha Egyikben sem volt akkor i nagyobb lesz (egyenlő), mint a lista hossza (i<len()). Ha azonban van a próbálkozásban legalább két egyenlő szám, akkor nem élek a lista végére és az i a listában elfoglalt indexe az ismétlődést tartalmazó próbálkozásnak, ezért a keresett próbálkozás sorszáma i+1,

Kár, hogy nincs ilyen függvény beépítve a pythonba, hogy nincsIsmetles(). 🙂 Ez volt a döntéselhalasztás elvének alkalmazása. (Vagyis majd később megírom a kódot, amely a kérdést eldönti. )

Tehát nekem kellett megírnom:

def nincsIsmetles(kod):
    darab = {}
    for szam in kod:
        if szam not in darab.keys():
            darab[szam] = 1
        else:
            darab[szam] += 1
    darabList = list(darab.values())
    i = 0
    while i < len(darabList) and darabList[i] <= 1:
        i += 1
    if i < len(darabList):
        return False
    else:
        return True
nincsIsmetles() függvény

Ez pedig egy megszámlálás tétel és egy eldöntés tétel együttes alkalmazása. A darab lista egy dictionary (asszociatív lista), amely kulcsa a próbálkozás egy számjegye. Ha még nincs benne a soron következő számjegy a lista kulcsai között (szam not in darab.kys()), akkor új kulcs és az értéke 1 (darab[szam] = 1), különben (ha szerepel már a számjegy a lista kulcsai között) hozzáadok 1-t az adott kulcs értékéhez.

Az elkészült darab dictionary értékeiből listát készítek (darabList = list(darab.values())) és eldöntöm, hogy van-e az elemei között 1-nél nagyobb szám. Ha igen megszakad a ciklus (while) futása és hamis értékkel  tér vissza a függvény (return False).

5. feladat

Állítson elő egy, a második feladatban beolvasottal egyező hosszúságú, véletlenszerű, ismétlődés nélküli jelsorozatot, majd a mintának megfelelően jelenítse meg a hosszát és az előállított kódszámot!

Mivel véletlen számot kell elő állítani, ezért szükségem van a random modulra, amit a program legelején (1. sor) kell beimportálnom.

import random

print("1. feladat")

....
print("5. feladat")
kodHossz = len(ujProba)
veletlenProba = ''
while len(veletlenProba) < kodHossz:
    ujSzam = str(random.randint(0,10))
    while ujSzam in veletlenProba:
        ujSzam = str(random.randint(0,10))
    veletlenProba += ujSzam
print("Egy %d hosszú véletlen kódszám: %s"%(kodHossz,veletlenProba))
5. feladat

A kodHossz az előállítandó kód hossza. Mindig megkérdezhetném a len() függvénnyel, de  így a program hatékonyabb. A veletlenProba lesz a véletlenszerűen előállított kód. Elindítok egy ciklust, amely addig fut amíg a szükséges kódhossz kész nincs. Ez lehetne nyugodtan egy számlálós ciklus is (for), de én jobban szeretem a feltételes ciklus (while) alkalmazni ilyenkor.

Sajnos, amikor előállítok egy új számot a kódba (ujSzam = str(random.randint(0,10)), akkor nem lehet biztos benne, hogy ez a szám nem szerepel az eddig véletlenül előállítottak között a kódban, ezért megvizsgálom és addig (while ujSzam in veletlenProba) állítok elő újabb és újabb számot, amíg az olyan lesz, ami nem szerepel az eddig már előállítottak között.

Megjegyzés:
A python nem ismeri az elől tesztelő feltételes ciklus-t, így a kód egy sorral hosszabb. Vedd észre kétszer szerepel az ujSzam = str(random.randint(0,10) sor. Ha ciklus végén tesztelhetnénk elég lenne egyszer.

6. feladat

Készítsen függvényt nyit néven az alábbi algoritmus alapján, amely a neki átadott két kódszámról megállapítja, hogy ugyanazt a zárat nyitják-e! (A 239451 és a 017239 ugyanazt a zárat nyitja.) A függvény két, legfeljebb 10 számjegyből álló karaktersorozathoz egy
logikai értéket rendel. A függvény elkészítésekor az algoritmusban megadott változóneveket használja! Az elkészített függvényt a következő feladat megoldásánál felhasználhatja.

Függvény nyit(jo, proba:karaktersorozat): logikai érték
  egyezik:=(hossz(jo)=hossz(proba))
  Ha egyezik akkor
    elteres=ascii(jo[1])-ascii(proba[1])
    Ciklus i:=2-től hossz(jo)
      Ha ( elteres - (ascii(jo[i])-ascii(proba[i])) ) mod 10 <> 0
      akkor egyezik:=hamis
    Ciklus vége
  Elágazás vége
  nyit:=egyezik
Függvény vége

Ez a 3. feladattal teljesen megegyező megoldás. Ha eddig nem tudtad volna a 3. feladatot megoldani, akkor már tudod. Az én megoldásommal azonos elveken alapszik vagyis a számok közötti távolság egyenlőségén alapszik. Az ord() függvény az ascii kódtábla szerinti kódját adja meg a karakternek( ord(“1”) = 49 vagy ord(“3” =51).  A megoldás menete megegyezik a 3. feladatban leírtakkal, csak én az eldöntés tételét alkalmazva, azonnal abbahagytam a kód vizsgálatát, ha találtam eltérést. Ez az algoritmus a végig vizsgálja az egész kódot akkor is, ha már a második két karakter eltért egymástól.

Íme a pythonra fordított kód:

print("6. feladat")
def nyit(jo, proba):
    egyezik = (len(jo) == len(proba))
    if egyezik:
        elteres = ord(jo[0]) - ord(proba[0])
        for i in range(1,len(jo)):
            if (elteres -(ord(jo[i]) - ord(proba[i]))) % 10 != 0:
                egyezik = False
    return egyezik
6. feladat mgoldása

7. feladat

Állítsa elő a siker.txt fáljt, amelynek soraiban a nyitási próbálkozás kódszáma után – attól egy szóközzel elválasztva – annak értékelése olvasható.

  • „hibás hossz”, ha a felhasználótól a 2. feladatban bekért kódszám és a sorbeli kódszám hossza eltér;
  • „hibás kódszám”, ha a felhasználótól a 2. feladatban bekért kódszám és a sorbeli kódszám hossza egyezik, de nem összetartozók;
  • „sikeres”, ha a két kódszám egyenértékű.
Részlet a siker.txt fájlból:
239451 sikeres
154932 hibás kódszám
340562 sikeres

Anélkül, hogy a nyit() függvényt módosítanánk, annak felhasználásával oldom meg a feladatot.

print("7. feladat")
with open("siker.txt", "w", encoding="utf-8") as siker:
    for egyProba in probalkozasok:
        if len(egyProba) != len(ujProba):
            siker.write("%s hibás hossz\n"%egyProba)
        else:
            if nyit(egyProba, ujProba):
                siker.write("%s sikeres\n"%egyProba)
            else:
                siker.write("%s hibás kódszám\n"%egyProba)
7. feladat megoldása

Azt hiszem ez nem kíván magyarázatot.

 

Ötszáz programozás feladat – 2016. május

Feladat leírása


Egy apróságokat árusító boltban minden árucikk darabja 500 Ft. Ha egy vásárlás során valaki egy adott árucikkből több darabot is vesz, a második ára már csak 450 Ft, a harmadik pedig 400 Ft, de a negyedik és további darabok is ennyibe kerülnek, tehát az ár a harmadik ugyanazon cikk vásárlása után már nem csökken tovább.
A pénztárhoz menők kosarában legalább 1 és legfeljebb 20 darab árucikk lehet. A kosarak tartalmát a penztar.txt fájl írja le, amelyben soronként egy-egy árucikk neve vagy az F karakter szerepel. A fájlban legfeljebb 1000 sor lehet. Az F karakter azt jelzi, hogy az adott vásárlónak nincs már újabb árucikk a kosarában, fizetés következik. Az árucikkek neve ékezet nélküli, több szóból is állhat, hossza legfeljebb 30 karakter.

A példa alapján az első vásárló összesen 1 tollat vásárolt, ezért összesen 500 Ft-ot kell fizetnie. A második vásárlás során hatféle árucikket vásároltak – a HB ceruzából és a colostokból többet is –, összesen 3900 Ft értékben.

Készítsen programot, amely a penztar.txt állomány adatait felhasználva az alábbi kérdésekre válaszol! A program forráskódját mentse otszaz néven! (A program megírásakor a felhasználó által megadott adatok helyességét, érvényességét nem kell ellenőriznie, és feltételezheti, hogy a rendelkezésre álló adatok a leírtaknak megfelelnek.)

A képernyőre írást igénylő részfeladatok eredményének megjelenítése előtt írja a képernyőre a feladat sorszámát (például: 3. feladat:)! Ha a felhasználótól kér be adatot, jelenítse meg a képernyőn, hogy milyen értéket vár! Az ékezetmentes kiírás is elfogadott.

1. feladat

Olvassa be és tárolja el a penztar.txt fájl tartalmát!

A megoldás alapötlete, hogy egy darab egydimenziós lista (vektor) , minden egyes elem egy újabb lista.

Megnyitottam olvasásra a penztar.txt.
  Egy for ciklussal bejárom a fájlt.
    Minden sorárának végéről levágom ('/n') karaktert.
    Ha az elem éppen nem egy 'F' karakter, akkor
      egy listába gyűjtöm az árucikkeket (egyVasarlas)
    különben
      Hozzáfűzöm a vásárlások listához az összegyűlt árúcikkeket
      törlöm az egyVasarlas lista tartalmát

2. feladat

Határozza meg, hogy hányszor fizettek a pénztárnál!

A len() függvény megadja a lista hosszát. Ez a vásárlások száma.

3. feladat

Írja a képernyőre, hogy az első vásárlónak hány darab árucikk volt a kosarában!

A vasarlasok lista első elemének (0. sorszámú) hossza a válasz.

4. feladat

Kérje be a felhasználótól egy vásárlás sorszámát, egy árucikk nevét és egy darabszámot! A következő három feladat megoldásánál ezeket használja fel!

input() a felhasználótól kérem be az adatokat. Az input() függvény string típust add vissza, amit az int() függvénnyel alakítok egész számmá.

Feltételezheti, hogy a program futtasásakor csak a bemeneti állományban rögzített adatoknak megfelelő vásárlási sorszámot és árucikknevet ad meg a felhasználó.

5. feladat

Határozza meg, hogy a bekért árucikkből
a. melyik vásárláskor vettek először, és melyiknél utoljára!
b. összesen hány alkalommal vásároltak!

A megszámlálás tétel átalakított formáját használtam.
Végigjártam az összes vásárlást és minden vásárlás alkalmával megnéztem, hogy van-e a kosár a megfelelő árucikk. Ha van akkor annak a vásárlásnak a sorszámát elteszem egy listába.

A lista első eleme az első vásárlás sorszáma, az utolsó eleme az utolsó vásárlás sorszáma. A lista hossza a vásárlások száma.

6. feladat

Határozza meg, hogy a bekért darabszámot vásárolva egy termékből mennyi a fizetendő összeg! A feladat megoldásához készítsen függvényt ertek néven, amely a darabszámhoz a fizetendő összeget rendeli!

Az ertek(darab) függvény meghívásakor átadom a bekért darabszámot. Mivel minden árucikk 400 Ft ezért az ár a darab 400-szorosa, ha egy darabot vásároltak, akkor +100 Ft, ha 2 vagy annál több akkor viszont +100 Ft az első és +50 a második árucikk felára.

7. feladat

Határozza meg, hogy a bekért sorszámú vásárláskor mely árucikkekből és milyen mennyiségben vásároltak! Az árucikkek nevét tetszőleges sorrendben megjelenítheti.

A kosar most egy dictionary. Ezt más programozási nyelven asszociatív tömbnek hívják. Minden bejegyzéshez tartozik egy kulcs (key) és egy érték (value) együtt item.

Bejárjuk az adott sorszámú vásárlást (for). Azért van 1 kivonva a sorszámból, mert a lista első sorszáma 0.  Az egyVasarlas tartalma minden ciklusban egy árucikk.

Ha (if) az árucikk nincs benne (not in) a kosárban (kosar.keys()), akkor létrehozzuk az árucikk nevű kulcsot (kosar[egyVasarlas]) és az értéket 1-re állítom.

Különben (else), ha már volt ilyen árucikk ebben vásárlásban, vagyis van ilyen kulcs, akkor az értékét megnövelem 1-el.

A második ciklus (for) végigjárja a kosar dictionary-t és kiírja a kulcsot (cikk) és az értéket (db) a kosárból (kosar.items())

Ez egy megszámlálás programozási tétel python alkalmazása volt.

7. feladat (másképp)

Ha hamarabb elolvastam volna a 8. feladatot, akkor így készítem el a 7. feladatot:

A kosár tartalmából készített dictionary létrehozását általánosítottam (absztraháltam) úgy hogy az egyKosar függvénynek csak a vásárlás sorszámát adom át és a függvény visszatérési értéke a kosár tartalma megszámolva a benne lévő tárgyakat.

8. feladat

Készítse el az osszeg.txt fájlt, amelybe soronként az egy-egy vásárlás alkalmával fizetendő összeg kerüljön a kimeneti mintának megfelelően!

A feladat megoldása az előzőek birtokában, már gyerekjáték. Egy fájlba írást kell kombinálni egy összegzés programozási tétellel, amelyben felhasználom az ertek() és az egyKosar() függvényeket.

A print() megjegyzésként azért maradt benne, hogy lásd, mielőtt a fájlba írtam volna azelőtt kiírtam a képernyőre.

A magyarázat a következő:
Megnyitottam írásra az osszeg.txt állományt, a logikai neve v. Az i változó a vásárlás sorszáma ezt 0 értékkel inicializálom. A for ciklus bejárja az összes vásárlás és minden vásárlás értékét az osszeg változóba gyűjtöm. A belső for ciklus bejárja az átalakított vásárlást (egyKosar(i).values()). A darab a vásárláskor az az adott árúból megvásárolt darabszám. Az osszeg változóba az ertek() függvény által visszaadott vásárolt darabszám szerinti értéket összegzem.

A v.write() úgy működik, mint a print() csak fájlba ír, a \n a sortörés. A végén csak megnövelem az i-t vagyis a vásárlás sorszámát.

SMS feladat – 2007. május

Feladatleírás


Napjainkban a kommunikáció egy elterjedt formája az SMS-küldés. Az SMS-küldésre alkalmas telefonok prediktív szövegbevitellel segítik az üzenetek megírását. Ennek használatakor a szavakat úgy tudjuk beírni, hogy a telefon számbillentyűjén található betűknek megfelelő számokat kell beírnunk. A számok és betűk megfeleltetését az alábbi táblázat mutatja:
sms01

Ha meg szeretnénk jeleníteni az „ablak” szót, akkor a 22525 kódot kell beírnunk. A telefon a tárolt szótára alapján a kódhoz kikeresi a megfelelő szót. Ha több szóhoz is azonos kód tartozik, akkor a kódhoz tartozó összes szót felkínálja választásra. Egy ilyen szógyűjteményt talál a szavak.txt fájl-ban. A fájlról a következőket tudjuk:

  • Legfeljebb 600 szó található benne.
  • Minden szó külön sorban található.
  • A szavak hossza maximum 15 karakter.
  • A szavak mindegyike csak az angol ábécé kisbetűit tartalmazza.
  • Minden szó legfeljebb egyszer szerepel.

Írjon sms néven programot, ami a szógyűjtemény felhasználásával megoldja az alábbi feladatokat!

1. feladat

1. Kérjen be a felhasználótól egy betűt, és adja meg, hogy milyen kód (szám) tartozik hozzá! Az eredményt írassa a képernyőre!

Először egy kis elmélet:

Eldöntés és Kiválasztás tétele

A programozási tételek megkönnyítik a feladatok megoldását. Amennyiben egy probléma megoldása visszavezethető egy programozási tételre, akkor nincs más dolgod, mint alkalmazd. Ebben az esetben a kiválasztás tételének alkalmazása kézenfekvő, hiszen tudjuk, hogy egy halmazban ott van a keresett elem, csak azt nem tudjuk hányadik (melyik az). Tehát csak ki kell választani a megfelelőt a listából.

A legegyszerűbb eset, ha csak azt kell eldönteni, hogy van-e benne számunkra megfelelő elem, ez az ELDÖNTÉS tétele:

Általános megfogalmazás:

Eldöntés: Adott egy N elemű sorozat és az azon értelmezhető T tulajdonság. Döntsd el van-e a sorozatnak T tulajdonságú eleme!
Kiválasztás: Adott egy N elemű sorozat és az azon értelmezhető T tulajdonság. Valamint azt is tudjuk, hogy a sorozatnak van legalább egy T tulajdonságú eleme. Határozd meg a T tulajdonságú elemének az indexét.

Eldöntés: A T sorozat tartalmaz-e T tulajdonságú elemet?

bemenet: T[] tömb
i = 0;
N = tömb hossza
Ciklus amig  i < N és T[i] nem T tulajdonságú
   i++
Ciklusvége
VAN = (i<N)
Ha azonban biztosan tudjuk, hogy a keresett elem benne van a listában, akkor már nem kell a végét figyelni, mert legrosszabb esetben az utolsó elem az amelyiket keresed. Ez a Kiválasztás tétele.

Kiválasztás: A T sorozat tartalmaz T tulajdonságú elemet, mi a sorszáma?

bemenet: T[] tömb
i = 0;
N = tömb hossza
Ciklus amig  T[i] nem T tulajdonságú
   i++
Ciklusvége
kimenet: index = i

A feladat megoldása

Mindenek előtt a billentyűket tároljuk egy listában a következő módon. Az egyes billentyűkön látható betűket egy string-ben tárolom a billentyűket pedig egy listában.
bill=['abc', 'def', 'ghi', 'jkl', 'mno','pqrs','tuv', 'wxyz']

Most pedig válasszuk ki a billentyűk közül azt, amelyik a megadott betűt tartalmazza.

print('1. feladat')
beBill = input('Kérek egy betűt: ')
i=0
while bill[i].count(beBill) != 1:
    i += 1
print(i+2)
Természetesen, ha bolondbiztossá akarod tenni (ezt nem kéri az érettségi feladat), akkor a kiválasztás tétele helyett alkalmazd a keresés tételét, amely az eldöntés tétele egybegyúrva a kiválasztás tételével.

2. feladat

Kérjen be a felhasználótól egy szót, és határozza meg, hogy milyen számsorral lehet ezt a telefonba bevinni! Az eredményt írassa a képernyőre!
Itt már világosan látszik, hogy az előző feladat megoldását itt is felhasználhatom, tehát hatékony lenne, ha készítenék egy függvényt, amelyik egy megadott betű alapján visszatér a billentyű sorszámával.
def BetuSzama(betu):
    i=0
    while bill[i].count(beBill) != 1:
        i += 1
    return i+2
Az előző feladatot már nem kell módosítani, bár elegáns lenne. Viszont figyeld meg, hogy így milyen áttekinthető és egyszerű a 2. feladat megoldása.
print('2. feladat')
beSzo = input(('Kérek egy szót: ')
for betu in beSzo:
    print(betuSzama(betu),end=''))
print("\n")

A print() utasítás alapból sortöréssel záródik (‘/n’), ha azt szeretnénk, hogy a következő kiírt adat ne új sorba kezdődjön, akkor küldjük el az end=” paramétert is.

Ebből világosan következik, hogy ha az end=”;/n” karakter sorozatot küldöd paraméterként, akkor minden kiírás végén pontosvessző lesz és sortörés.

3. feladat

Olvassa be a szavak.txt fájlból a szavakat, és a továbbiakban azokkal dolgozzon! Ha nem tudja az állományból beolvasni az adatokat, akkor az állományban található „b” kezdőbetűs szavakat gépelje be a programba, és azokkal oldja meg a feladatokat!
Most már igen nagy rutinunk van állományból beolvasásban. Ez megint egy egyszerű lista feltöltése. Nézzük:
print("3. feladat")
szavak = []
with open('szavak.txt','r',encoding='utf-8') as szavakFile:
    for egySor in szavakFile:
        szavak.append(egySor.strip())

Mivel a szavak.txt minden szava külön sorban van ezért a sorzáró karaktert kell eltávolítani a beolvasáskor (strip()) és minden sort hozzáfűzni (append()) a szavak listához.

4. feladat

Határozza meg és írassa a képernyőre, hogy melyik a leghosszabb tárolt szó! Amennyiben több azonos hosszúságú van, elegendő csak az egyiket megjeleníteni. Adja meg ennek a szónak a hosszát is!
Ez egy maximum kiválasztás tétel. A lényeg, hogy amikor a probléma megoldásához kezdesz a lista első eleme a leghosszabb, Majd minden következő elemet összehasonlítasz az aktuális leghosszabbal, ha nagyobbat találsz, akkor az lesz a leghosszabb.

Általános megfogalmazás:

Adott egy N elemű sorozat és a sorozat elemein értelmezhető T tulajdonság. Melyik a legnagyobb eleme a sorozatnak?

A T sorozatnak melyik a legnagyobb eleme?

bemenet: T[0..N-1] tömb (lista, sorozat)

maxIndex = 0 #Ez a sorozat első elemének indexe, jelenleg a legnagyobb elem a T[0]
i = 1; #Ez a sorozat második elemének indexe
N = lista hossza
Ciklus amíg  i < N 
   Ha T[i] > T[maxIndex] akkor maxIndex = i 
   #Ha az aktuális sorszámú elem nagyobb, mint az aktuális legnagyobb, akkor ez az új legnagyobb.
   i++
Ciklusvége
MAXIMUM = T[maxIndex]

Tisztán a tételt alkalmazva így néz ki:

print('4. feladat')
maxIndex = 0
i = 1
while i < len(szavak):
    if len(szavak[i]) > szavak[maxIndex]:
        maxIndex = i
    i += 1
print(szavak[maxIndex])

Ez egy másik megoldás:

print('4. feladat')
maxIndex = 0
for i in range(1, len(szavak)):
    if len(szavak[i]) > szavak[maxIndex]:
        maxIndex = i
print(szavak[maxIndex])

A for i in  range(1, len(szavak) egy számlálós ciklus, amelyben az i ciklusváltozó értéke a range(1, len(szavak)) függvény által meghatározott tartomány értékeit veszi fel. Ebben az esetben a kezdőérték 1, az utolsó érték a szavak lista hossza – 1.

A harmadik megoldás pedig ez:

print('4. feladat')
max = szavak[0]
for egySzo in szavak:
    if len(egySzo) > len(max):
        max = egySzo
print(max)

Egy kis érdekesség, ez a Python nyelv lehetőségeit kihasználó megoldás:

print('4. feladat')
szoHosszak = list(map(len, szavak))
print(szavak[szoHosszak.index(max(szoHosszak)))

Magyarázat: A map() függvény első paramétere a len függvény, a második a szavak lista. A map() függvény a szavak lista minden elemén végrehajtja a len() függvényt és egy listába pakolja a list() függvény segítségével. Létrejött tehát egy a szavak hosszát tároló lista. (szoHosszak). A max() függvény megadja a legnagyobb értéket a szoHosszak litából. A szoHosszak.index() metódusa visszadja a legnagyobb érték indexét, amely pont a szavak lista leghosszabb szavának az indexe is egyben.

5. feladat

Határozza meg és írassa a képernyőre, hogy hány rövid szó található a fájlban! Rövid szónak tekintjük a legfeljebb 5 karakterből álló szavakat.
Ez egy megszámlálás tétel, amelyik arra hivatott, hogy egy adott sorozat megfelelő tulajdonságú elemeit megszámolja.

Általános megfogalmazás:

Adott egy N elemű sorozat és sorozat elemein értelmezhető T tulajdonság. Számold meg, hogy a sorozatnak hány T tulajdonságú eleme van.

A T sorozatnak hány T tulajdonságú eleme van?

bemenet: T[0..N-1] tömb (lista, sorozat)

darab = 0 
i = 0; #Ez a ciklus változó, a sorozat 1. elemétöl kezdünk, aminek indexe 0
N = lista hossza
Ciklus amíg  i < N 
   Ha T[i] T tulajdonságú akkor
      darab ++ # Növeljük eggyel a darbszámot
   i++
Ciklusvége
Kimenet: darab

A sorozat vagy lista a szavak a T tulajdonság a szavak hossza (len(szavak[i])). A feladat, hogy azokat számoljuk meg, amelyek legfeljebb 5 betűből állnak len(szavak[i] >= 5).

Ez megszámlálás tétel szó szerinti alkalmazása:

print('5. feladat')
darab = 0
i = 0
while i < len(szavak):
    if len(szavak[i]) <= 5:
        darab += 1
    i += 1
print(darab)

Ez a Pythonos változat:

print('5. feladat')
darab = 0
for egySzo in szavak:
    if len(egySzo) <= 5:
        darab += 1
print(darab)

6. feladat

Írassa a kodok.txt állományba a szavak.txt fájlban található szavaknak megfelelő számkódokat! Minden szónak feleljen meg egy számkód, és minden számkód külön sorba kerüljön!
Mivel a szavak.txt tartalma már a szavak listában van, ezért a már elkészített betuSzama() függvényt felhasználva, minden szót kóddá alakíthatunk és kiírhatjuk a kodok.txt-be. (Ha már most előre olvasod a 7. feladatot láthatod, hogy érdemes lenne egyből egy listát is készíteni a kiírt kódokból, de most úgy viselkedünk, mint az átlagos diák. Nem olvas csak, ha muszáj.)
print("6. feladat")
with open('kodok.txt','w',encoding='utf-8') as kodokFile:
    for egySzo in szavak:
        kod = ""
        for betu in egySzo:
            kod += str(betuSzama(betu))
        kodokFile.write(kod+"\n")

Magyarázat: A ‘w’ paraméter létrehozza és írásra megnyitja a kodok.txt állományt. Az első (külső) ciklus bejárja a szavakat. A kod változót minden szó előtt üres sting-re cserélünk. A belső ciklus a szavak betűit járja be. Minden betűhöz tartozó kódot string-gé konvertálunk és hozzáfűzünk a kod változóhoz. Majd a kész kódsort egy sortörés karakter kíséretében kiírjuk a kodok.txt állományba.

7. feladat

Kérjen be a felhasználótól egy számsort, és határozza meg, hogy melyik szó tartozhat hozzá! Amennyiben több szó is megfelelő, akkor mindegyiket írassa ki! (Teszteléshez használhatja például a 225 számsort, mivel ehhez egynél több szó tartozik a szógyűjteményben.

Jé, ez meg egy kiválogatás tétel.

Általános megfogalmazás:

Adott egy N elemű sorozat és sorozat elemein értelmezhető T tulaj-donság. Válogassuk ki egy új B sorozatba az összes T tulajdonságú elemét a sorozatnak.

A T sorozatból válogassuk ki a T tulajdonságú elemeket!

bemenet: T[] tömb
i = 0;
j = 0;
N = tömb hossza;
Ciklus amig i < N
   Ha T[i] T tulajdonságú akkor
        B[j] = T[i]
        j++
   i++
Ciklusvége

Először egészítsük ki a 6. feladat kódját. Mint már említettem, ha lenne egy listánk a kódokról, akkor azt ebben a feladatban felhasz-nálhatnánk.

print("6. feladat")
with open('kodok.txt','w',encoding='utf-8') as kodokFile:
     kodok = []
     for egySzo in szavak:
        kod = ""
        for betu in egySzo:
            kod += str(betuSzama(betu))
        kodok.append(kod)
        kodokFile.write(kod+"\n")

Így már van egy kódokat tartalmazó listánk, amelyikben kereshetjük a felhasználó által megadott kódot.

print("7. feladat")
szamSor = input("Kérek egy számsort: ")
joKodok = []
i = 0
for kod in kodok:
    if kod == szamSor:
         joKodok.append(i)
    i += 1
if len(joKodok) > 0:
     for kod in joKodok:
         print(szavak[kod])
else:
     print("Nincs a számsornak megfelelő szó!")
Magyarázat: Bekérünk egy számsort, utána létrehozunk egy üres listát (joKodok). A ciklus végig halad az össes kódon, ha valamelyik egyezik a beírt számsorral azt hozzáfűzzük a joKodok listához. Ha végére érünk a listának, akkor megvizsgáljuk, hogy van-e elem a joKodok listában. Ha a lista elemeinek száma nagyobb, mint nulla, akkor van tehát kiírjuk a képernyőre, különben szólunk, hogy nincs a kódnak megfelelő szó.

8. feladat

Határozza meg, hogy a szógyűjteményben mely kódokhoz tartozik több szó is! Írassa ki a képernyőre ezeket a szavakat a kódjukkal együtt egymás mellé az alábbi mintának megfelelően (a szavak sorrendje ettől eltérhet):

sms02

1. megoldási javaslat:

Végig nézem az összes kódot és megszámolom melyikből hány darab van. Majd kiírom azokat, amelyekből egynél több van.

2. megoldási javaslat:

Végig járom az összes kódot, mindegyikből megnézem van-e még több, ha igen kiírom.

Szerintem a második elgondolás az egyszerűbb. Azonban, ha a ). feladatot is elolvasom, akkor rájövök, hogy érdemes egy listába kigyűjteni, hogy melyik szóból mennyi van, mert a 9. feladatban szükség lesz arra a kódra, amelyik a legtöbbször szerepel.

Tehát mégis az első gondolat a jó gondolat. mosoly

No akkor járjuk végig a kodok listát. Minden kódról derítsük ki, hogy hányszor szerepel, majd írjuk ki a szavak és kodok listából azokat, amelyek indexe megegyezik az összesített listában azon elemek indexével, ahol az érték nagyobb, mint 1.
print("8. feladat")
kodOsszesites = []
for kod in kodok:
    kodOsszesites.append(kodok.count(kod))
i = 0
for o in kodOsszesites:
    if o > 1:
        print(szavak[i] + " : " kodok[i] + "; ", end = '')
    i += 1
Persze, ha a kodOsszesites.append(kodok.(kod)) sor helyett egy megszámlálás tételt szeretnéd alkalmazni. Vagyis egy darab = 0 után, egy új ciklussal végigjárod a kodok listát és ha éppen az aktuális kóddal találkozol, akkor növeld a darabszámot eggyel. Majd fűzd a kódOsszesites listához a kapot darabszámot. Nekem jó így is.

9. feladat

Határozza meg, hogy melyik kódnak megfelelő szóból van a legtöbb! Írassa ki a képernyőre a kódot, és a kódhoz tartozó összes tárolt szót! Ha több kódhoz is azonos számú szó tartozik, akkor elegendő ezen kódok közül csak az egyikkel foglalkozni.

Elméleti megoldás

Azért érdemes végig gondolni, mert a python által kínált lehetőségek, már nem rajzolnak ilyen szép tételes megoldást, viszont hatékonyak és az egyszerűségükben a szépség.
Azért gyűjtöttük ki az előbb, hogy melyik kódból mennyi van, mert így egy maximumkiválasztással megtaláljuk a legnagyobbat, majd egy kiválogatással megszerezzük az összes indexét és ezáltal a szavakat is.
# Először megkeressük a legnagyobb számot a kodOsszesites listában, mert ez lesz az a kód, amely legtöbbször előfordult 
max = kodOsszesitett[0]
i = 1
Ciklus amíg i < len(kodOsszesitett)
     if kodOsszesitett > max akkor max = kodOsszesitett[i]
     i ++
Ciklus vége
# Kiválogatjuk azokat az indexeket, amelyek a max értékét hordozza
azonosak = [] #ebben fogjuk tárolni az azonosak indexét
i = 0
Ciklus amíg i < len(kodOsszesitet)
     if kodOsszesitett[i] == max akkor azonosak.append(i)
Ciklus vége
# Már csak ki kell írni az összesített eredményt, legalábbis az elsőt
Kiír: 
Legtöbbször előforduló kód: kodok[azonosak[0]]
i = 0
# Az azonosak listában több is összegyűlhet, ami azonos hosszú, de nekünk csak az elsőre van szükségünk.
Ciklus i < max
      kiír: szavak[azonosak[i]] 
Ciklus vége
Természetesen az előbb vázolt elméleti megoldás, mondatszerű leírással  könnyedén átültethető python nyelvre. A megoldás azonban, ha kihasználjuk a nyelv adta lehetőségeket rövidebb, mert a maximumkiválasztás helyett a max() függvényt használjuk.
print('8. feladat')
legtobbszor = max(kodok)
azonosak = []
i = 0
for egyMax in kodOsszesites:
    if egyMax == legtobbszor:
        azonosak.append(i)
    i += 1
print('A legtöbb szóhoz tartozó azonos számsor pl:: %s'%kodok[azonosak[0]])
for i in range(0, legtobbszor):
    print(szavak[azonosak[i])

Törtek feladat – 2012. május

Feladat leírás


A matematikában sokszor van szükségünk műveletvégzésre a közönséges törtekkel. A legtöbb számológép és számítógépes program csak a tizedes törteket ismeri. Készítsen programot, amely az alábbi – közönséges törtekkel kapcsolatos – feladatokat megoldja! A program forráskódját tort néven mentse! A feladatban csak pozitív számokkal kell dolgoznia, és ennek a tulajdonságnak a feldolgozandó fájlban található számadatok is megfelelnek. A felhasználótól bekérendő és a feldolgozandó fájlban található számokról feltételezheti, hogy legfeljebb kétjegyűek.

Feladatok megoldásai:
1. feladat
2. feladat
3. feladat
4. feladat
5. feladat
6. feladat
7. feladat

1. feladat

Kérjen be a felhasználótól két számot, amely egy közönséges tört számlálója és nevezője!
Döntse el, hogy az így bevitt tört felírható-e egész számként! Ha igen, írja ki értékét egész számként, ha nem, írja ki „Nem egész”!

print("1. feladat")
a = int(input("Kérem a tört számlálóját: "))
b = int(input("Kérem a tört nevezőjét: "))
if a % b == 0:
    print(int(a/b))
else:
    print("Nem egész")

A % operandus két szám maradékát adja eredményül – például: 4 % 2 = 0 vagy 11 % 3 = 2, mert 11 / 3 = 3 és a maradék 2.

Az a/b eredménye valós szám típusú szám. Az int(a/b) egész szám típusúvá alakítja a hányadost.

2. feladat

A közönséges törteket úgy tudjuk a legegyszerűbb alakra hozni, ha a számlálóját és nevezőjét elosztjuk a két szám legnagyobb közös osztójával, és az így kapott érték lesz az új számláló, illetve nevező. Az egyszerűsítéshez készítsen egy rekurzív függvényt az alább leírt euklideszi algoritmusnak megfelelően!

Természetesen a Python tudja önállóan az LNKO előállítását is, de ezt most nem használhatjuk.

A legszebb megoldás, de sajnos a feladat nem ezt kéri a következő:

def lnko(m, n):
    if n:
        return lnko(n, m%n)
    return m

Ez az Euklideszi algoritmus python leírása. Röviden ez történik:

Az euklideszi algoritmus két egész szám legnagyobb közös osztójának (lnko) meghatározására szolgál, maradékos osztások egymásutánjával. Először maradékosan elosztjuk az egyik számot a másikkal, majd az osztót a maradékkal, majd a második osztás osztóját a második osztás maradékával, és így tovább egészen addig, amíg a maradék 0 nem lesz.
A maradékos osztás maradékát visszaadó kifejezés jele a Python-ban a % jel, úgyhogy a példában szereplő számokkal az osztások láncolata: 21 % 33 = 21, 33 % 21 = 12, 21 % 12 = 9, 12 % 9 = 3, 9 % 3 = 0. (A hányadosokra jelen esetben nincs szükségünk.)
Az utolsó nem nulla maradék lesz az lnko. Ő ugyanis osztója a láncolatban szereplő összes számnak, tehát a kiinduló két számnak is. És fordítva, a kiinduló két szám minden közös osztója osztója lesz a láncolatban szereplő összes számnak, tehát az utolsó nem nulla maradéknak is. És az algoritmus valamikor biztosan véget ér, mivel a maradékok sorozata szigorúan monoton csökkenő.

Itt találtam: Python haiku

Megoldás a feladat szerint

A feladat azt kéri, hogy ezt az algoritmus használjuk:

tortAlgRekurzio

Ez egy rekurzív függvény, mert önmagát hívja meg egészen addig, amíg az a egyenlő nem lesz b-vel. Ez a kilépési pont!

Nézzük, hogyan működik:

Ez egy rekurzív függvény, mert önmagát hívja meg egészen addig, amíg az a egyenlő nem lesz b-vel. Ez a kilépési pont!

Nézzük, hogyan működik:

Algoritmus teszt
a b a = b a < b a > b
21 33 hamis igaz hamis
21 33-21 = 12 hamis hamis igaz
21-12 = 9 12 hamis igaz hamis
9 12 – 9 = 3 hamis hamis igaz
9 – 3 = 6 3 hamis igaz hamis
3 3 igaz hamis hamis

És tényleg a 21 és 33 legnagyobb közös osztója a 3.

Megoldás python nyelven

print("2. feladat")
def lnko(a, b)
    if a == b:
        return a
    if a < b:
        return lnko(a, b - a)
    if a > b:
        return lnko(b, a - b)

Az lnko egy saját gyátású függvény, használata a következő:

print(lnko(21, 33))
vagy
x = lnko(21,33)

3. feladat

Az első feladatban bekért törtet hozza a legegyszerűbb alakra a létrehozott függvény segítségével! Amennyiben nem sikerül az előírt függvényt elkészítenie, alkalmazhat más megoldást, hogy a további feladatokat meg tudja oldani. Az eredményt írja ki a következő formában:
24/32 = 3/4

vagy

24/6 = 4

A megoldás

print("3. feladat")
oszto = lnko(a,b)
if int(b / oszto) != 1:
    print("%d/%d = %d/%d"%(a,b,int(a/oszto), int(b/oszto)))
else:
    print("%d/%d = %d"%(a,b,int(a/oszto)))

4. feladat

Két törtet úgy tudunk összeszorozni, hogy a két tört számlálóját összeszorozva kapjuk az eredmény számlálóját, és a két tört nevezőjét összeszorozva kapjuk az eredmény nevezőjét. Kérjen be a felhasználótól egy újabb közönséges törtet a számlálójával és a nevezőjével! Szorozza meg ezzel a törttel az első feladatban bekért törtet! Az eredményt hozza a legegyszerűbb alakra, és ezt írja ki a következő formában:
24/32 * 12/15 = 288/480 =3/5

vagy

24/32 * 8/3 = 192/96 = 2

A megoldás

print("4. feladat")
c = int(input("Kérem a szorzó tört számlálóját: "))
d = int(input("Kérem a szorzó tört nevezőjét: "))
oszto = lnko(a*c,b*d)
if int(b*d / oszto) != 1:
    print("%d/%d * %d/%d = %d/%d = %d/%d"%(a,b,c,d,a*c,b*d,int(a*c/oszto), int(b*d/oszto)))
else:
    print("%d/%d * %d/%d = %d/%d = %d"%(a,b,c,d,a*c,b*d,int(a*c/oszto)))

5. feladat

Két közönséges tört összeadásához a következő lépésekre van szükség:

  • Mindkét számot bővíteni kell, azaz mind a számlálóját, mind a nevezőjét ugyanazzal a számmal kell megszorozni. Ezt a bővítést úgy célszerű elvégezni, hogy a közös nevező a két eredeti nevező legkisebb közös többszöröse legyen. Ez lesz az összeg nevezője.
  • A két bővített alakú tört számlálóját összeadjuk, ez lesz az eredmény számlálója. Ehhez készítsen függvényt az alábbiakban leírtak szerint – a korábban elkészített lnko függvény felhasználásával – a legkisebb közös többszörös meghatározására!
Függvény lkkt(a, b: egész számok) : egész szám
   lkkt := a * b / lnko(a, b)
Függvény vége

Egyszerű matematika:

12 = 2 * 2 * 3 és 18 = 2 * 3 * 3, tehát a legnagyobb közös osztó  2 * 3 = 6. A függvény szerint a legkisebb közös többszörös 12 * 18 / 6 = 36. A matek órán tanultak szerint az összes prímtényező a legmagasabb hatványon a legkisebb közös többszörös. Vagyis 2 * 2 * 3 * 3 = 36. És tényleg.

 

A megoldás

print("5. feladat")
def lkkt(a, b):
    return int(a * b / lnko(a,b))

6. feladat

A függvény segítségével határozza meg a két bekért tört összegét, és ezt adja meg a következő formában! (Amennyiben nem sikerül az előírt függvényt elkészítenie, alkalmazhat más megoldást, hogy a további feladatokat meg tudja oldani.)

24/32 + 8/3 = 72/96 + 256/96 = 328/96 = 41/12

Amennyiben az eredmény felírható egész számként, akkor ebben az alakban jelenjen meg:

22/4 + 27/6 = 66/12 + 54/12 = 120/12 = 10

A megoldás

print("6. feladat")
_lkkt = lkkt(b,d) #a legkisebb közös többszörös kiszámítása
_a = a * _lkkt / b #az első tag bővített számlálója
_c = c * _lkkt / d #az második tag bővített számlálója
_sz = _a + _c #eredmény számlálója
if int(_lkkt / lnko(_sz, _lkkt)) != 1:
    print("%d/%d + %d/%d = %d/%d + %d/%d = %d/%d = %d/%d"%(a,b,c,d,_a, _lkkt, _c, _lkkt, _sz, _lkkt, int(_sz/lnko(_sz,_lkkt)),int(_lkkt/lnko(_sz,_lkkt))))
else:
    print("%d/%d + %d/%d = %d/%d + %d/%d = %d/%d = %d"%(a,b,c,d,_a, _lkkt, _c, _lkkt, _sz, _lkkt, int(_sz/lnko(_sz,_lkkt))))

7. feladat

Az adat.txt (becsomagolva(zip)) állományban található műveleteket végezze el, és az eredményeket a korábbi, képernyőre kiírt formátumnak megfelelően írja az eredmeny.txt állományba! Az adat.txt fájlnak legfeljebb 100 sora lehet; soronként 4 számot és egy műveleti jelet tartalmaz, melyeket mindenhol egy szóköz választ el egymástól. Műveleti jelként csak összeadás és szorzás szerepel.

Például:

tortAdatTxt

A megoldás

Ez  a beolvasás:

print("7. feladat")
feladatok = []
with open('adat.txt','r') as adat:
    for egySor in adat:      
        feladatok.append(list(egySor.strip().split(' ')))

Ez pedig a kiírás:

with open('eredmeny.txt','w') as eredmeny: 
    for egyFeladat in feladatok:
        a = int(egyFeladat[0])
        b = int(egyFeladat[1])
        c = int(egyFeladat[2])
        d = int(egyFeladat[3])
        muvelet = egyFeladat[4]
        if muvelet == '+':
            _lkkt = lkkt(b,d)
            _a = a * _lkkt / b
            _c = c * _lkkt / d
            _sz = _a + _c
            if int(_lkkt / lnko(_sz, _lkkt)) != 1:
                eredmeny.write("%d/%d + %d/%d = %d/%d + %d/%d = %d/%d = %d/%d"%(a,b,c,d,_a, _lkkt, _c, _lkkt, _sz, _lkkt, int(_sz/lnko(_sz,_lkkt)),int(_lkkt/lnko(_sz,_lkkt))))
            else:
                eredmeny.write("%d/%d + %d/%d = %d/%d + %d/%d = %d/%d = %d"%(a,b,c,d,_a, _lkkt, _c, _lkkt, _sz, _lkkt, int(_sz/lnko(_sz,_lkkt))))
        if muvelet == "*":
            oszto = lnko(a*c,b*d)
            if int((b*d) / oszto) != 1:
                eredmeny.write("%d/%d * %d/%d = %d/%d = %d/%d"%(a,b,c,d,a*c,b*d,int(a*c/oszto),int(b*d/oszto)))
            else:
                eredmeny.write("%d/%d * %d/%d = %d/%d = %d"%(a,b,c,d,a*c,b*d,int(a*c/oszto)))
        eredmeny.write("\n")            
Ez a megoldás olyan, mint amikor a diák, nem olvassa el előre a feladatot, nem tervez előre, csak csinálja, csinálja és csinálja. Gyakorlatilag lemásoltam újra az előző feladatok megoldását, a print() utasítást pedig átírtam eredmeny.write() utasításra. Ez gyors, de nem szép programozói megoldás.

A tört feladat megoldás hivatkozás alatt a teljes programot találod a szebbik megoldással.

 

Lottó programozás feladat – 2005. május

Feladat leírás


Magyarországon 1957 óta lehet ötös lottót játszani. A játék lényege a következő: a lottószelvényeken 90 szám közül 5 számot kell a fogadónak megjelölnie. Ha ezek közül 2 vagy annál több megegyezik a kisorsolt számokkal, akkor nyer. Az évek során egyre többen hódoltak ennek a szerencsejátéknak és a nyeremények is egyre nőttek. Adottak a lottosz.dat szöveges állományban a 2003. év 51 hetének ötös lottó számai. Az első sorában az első héten húzott számok vannak, szóközzel elválasztva, a második sorban a második hét lottószámai vannak stb.

Például:
 37 42 44 61 62
 18 42 54 83 89
 ...
 9 20 21 59 68

A lottószámok minden sorban emelkedő számsorrendben szerepelnek.

Megoldások:

  1. feladat
  2. feladat
  3. feladat
  4. feladat
  5. feladat
  6. feladat
  7. feladat
  8. feladat
  9. feladat
  10. Az összes megoldás: Lottó feladat állományai

1. feladat

Kérje be a felhasználótól az 52. hét megadott lottószámait!

Az állományból kimaradtak az 52. hét lottószámai. Ezek a következők voltak: 89 24 34 11 64.

Elméleti megoldás

A feladat 5 db egész szám beolvasását kéri a billentyűzetről, amelyet egy tömbben (Listában) a legegyszerűbb tárolni.

számok = []   #Üres lista létrehozása
Ciklus i=1-től 5-ig   #Számlálós ciklus, a ciklus változó i értékei rendre 1,2,3,4,5
   szamok[i] = adatBekérés() #A lista i. elemét beolvasom a billentyűzetről
Ciklus vége

Megoldás python nyelven

print("1. feladat")
print("Kérem az 52. heti LOTTÓ számokat!")
szamok =[]
for i in range(0,5):
    szamok.append(int(input("%d. kihúzott szám: "%(i+1))))

2. feladat

A program rendezze a bekért lottószámokat emelkedő sorrendbe! A rendezett számokat írja ki a képernyőre!

print("2. feladat - Rendezett lista")
szamok.sort() 
print(", ".join([str(i) for i in szamok]))

3. feladat

Kérjen be a felhasználótól egy egész számot 1-51 között! A bekért adatot nem kell ellenőrizni!

print("3. feladat")
het = int(input("Hányadik hét számaira kíváncsi (1-51)? "))

4. feladat

Írja ki a képernyőre a bekért számnak megfelelő sorszámú hét lottószámait, a lottosz állományban lévő adatok alapján! (csomagold ki a lotto.zip állományt)

Adatforrás megnyitása

with open('lottosz.dat','r',encoding='utf-8') as lottoFile:

A felhasznált utasítások:
with -> Ez egy olyan utasítás, amely abban segít, hogy ne a programozónak keljen a fájl lezárásával törődni-e.
open(‘útvonal\állomány.név’,’adatáramlás iránya’, [encoding=”])
‘útvonal\állomány.név’ –> az állomány, amelyte meg kívánunk nyitni
‘adatáramlás iránya’ –> ‘r’ – olvasásra, ‘w’ – írásra (mindíg új állomány jön létre), ‘a’ – hozzáfűzés (létező állomány végére)

Adatok beolvasása listába

print("4. feladat")
osszesHet=[]
with open('lottosz.dat','r',encoding='utf-8') as lottoFile:
    for egySor in lottoFile:
        osszesHet.append(list(map(int, egySor.strip().split(' '))))

A felhasznált utasítások:
Az osszesHet egy üres lista, ebben fogjuk tárolni a beolvasott lottószámokat.
A lottoFile egy logikai leképezése a lottosz.dat fizikai állománynak. Az with open() as parancssor hozza létre ez az adatfolyamnak is nevezett objektumot.
A for in vezérlőszerkezet bejárja a lottoFile  adatfolyamot (szekvenciális) az elejétől a végéig. A kiolvasott sort elhelyezi az egySor szövegváltozóba (string)
strip() –> levágja a sortörés (‘/n’) karaktert a szövegváltozó (string) végéről
split(‘ ‘) –> a szóközök mentén szétvágja a szöveg változót (string) és elhelyezi egy listában
map(int, egysor.strip().split(‘ ‘)) –> a feldarabolt, most már listaként létező lottószámokat, amelyek még stringek, átalakítjuk (konvertáljuk) egészszámmá (int).
list(map(..))–>a map típusú objektumot listává alakítja.
osszesHet.append() –> elhelyezi a feldarabolt lottószámok listáját (egy hét számai) az osszesHet listában

A bekért hét nyerőszámainak kiírása

het = int(input('Melyik hét számaira kíváncsi? '))-1
print(", ".join('{: >2}'.format(str(e)) for e in osszesHet[het]))

A felhasznált utasítások:
Az utolsó sor, miután bekértünk egy egész számot a felhasználótól (a kért hét sorszámát) a kiírja a számokat vesszővel elválasztva, pontosan két karakter hosszan.
for in bejárja az adott hét listáját.
az egyes számok az e változóba kerülnek.
az str(e) átalakítja szövegváltozóvá, a számot.
format() a megadott megjelenésűvé alakítja ‘{: >2}’. A kettős pont után egy szóköz van. Ha a kiírt szám csak egyjegyű, akkor 2 karakterre egészíti ki szóközzel.
join() pedig a számokat hozzáfűzi a a “, ”  stringhez.

Ez lesz a kiírás eredménye:
18,  2, 54, 83, 89

5. feladat

A lottosz.dat állományból beolvasott adatok alapján döntse el, hogy volt-e olyan szám, amit egyszer sem húztak ki az 51 hét alatt! A döntés eredményét (Van/Nincs) írja ki a képernyőre!

Gondolatok a megoldáshoz

1. gondolat

Az gondoltam, hogy az egyik megoldás az lehetne, ha összegyűjteném az összes előforduló számot az osszesHet listában, és ha az összegyűjtött számok száma 90 darab, akkor mindegyiket kihúzták, ha kevesebb, akkor van olyan, amelyiket nem húztak ki.

Előnye, hogy a megoldás viszonylag egyszerű, mert megyek végig az összes kihúzott számon és egy listába pakolom azokat a számokat, amelyek még nem szerepelnek benne. A végén a lista hosszát vizsgálom.

Hátránya végig kell mennem az összes kihúzott számon ráadásul a végén nem tudom meg, hogy melyiket nem húzták ki, csak azt hogy van olyan.

Vizsgálatok száma: 5 * 52 = 160 és állandó.

2. gondolat

A másik megoldás, ami szóba jöhet, hogy a végig megyek a kihúzható számokon és megnézem, hogy kihúzták-e.

Ez a bonyolultabb megoldás, hiszen itt 3 ciklust kell kezelnem. Megy végig a lehetséges számokon (1..90) és megnézem, hogy kihúzták-e. Ha nem, akkor megtalálta, ha igen fogom a következő számot és azt vizsgálom.

Előnye, lehet, hogy már nagyon hamar meg lesz az, amit nem húztak ki és tudom is, hogy melyik szám az.

Hátrány a megoldás komplexebb és lehet, hogy hosszabb is a végrehajtási ideje, hiszen, ha mindet kihúzták, akkor 90-szer vizsgálom meg a listát, ha nem is megyek végig rajta.

Vizsgálatok száma: minimum: <52, maximum: 90*52*5 = 23 400

Ezek szerint az 1. gondolat a jó gondolat. Valósítsuk meg azt.

Az 1. gondolat megoldása

print('5. feladat')
vanLista = []                   # üres lista  
for egySor in osszesHet:        # Bejárom a heteket
   for szam in egySor:          # Bejárom a hét számait
      if szam not in vanLista:  # ha a szám nincs benne a listában beleteszem
          vanLista.append(szam)
if len(vanLista) == 90:         # Ha a listában 90 érték van, akkor mindet kihúzták 
    print("Nincs")
else:
    print("Van")

A 2. gondolat megoldása

2. elgondolás

6. feladat

A lottosz.dat állományban lévő adatok alapján állapítsa meg, hogy hányszor volt páratlan szám a kihúzott lottószámok között! Az eredményt a képernyőre írja ki!

Az elgondolás

Végig nézem az összes hetet és a heteken belül a számokat, ha kihúzott szám 2-es maradéka (modulus) egyenlő 1-el akkor növelek egyet egy változó értékén.

páratlanok = 0
Ciklus 1 héttől osszesHet hosszáig
   Ciklus 1 számtól a hét utolsó számáig
      Ha szám osztási maradéka = 1 akkor
            páratlanok = páratlanok + 1

A megoldás

Ez egy megszámlálás tétel alkalmazása!

print('6. feladat')
paratlan = 0
for het in osszesHet:
    for szam in het:
        if szam % 2 == 1:
            paratlan += 1
print("A páratlankihúzott számok száma: %d"%paratlan)

7. feladat

Fűzze hozzá a lottosz.dat állományból beolvasott lottószámok után a felhasználótól bekért, és rendezett 52. hét lottószámait, majd írja ki az összes lottószámot a lotto52.ki szöveges fájlba! A fájlban egy sorba egy hét lottószámai kerüljenek, szóközzel elválasztva egymástól!

Az első elgondolás

Az egyszerű bár nem ezt várják az érettségi feladatok kigondolói, de el kell fogadniuk megoldás a következő:

import shutil #az shutil objektum osztály kezeli az állományokat ezért beimportálom
majd
shutil.copy(“lottosz.dat”, “lotto52.ki”) #Lemásolom az egész lottosz.dat állományt a lotto52.ki állományba
majd
open(‘lotto52.ki’,’a’, encoding=’utf-8′ as lottoFile) #megnyitom hozzáfűzésre az új állományt
majd
lottoFile.write(” “.join([str(e) for e in szamok])) #a régen (2. feladat) bekért szamok listát kiírom

Együtt pythonban

import shutil

...

print('7. feladat')
shutil.copy("lottosz.dat", "lotto52.ki")
with open('lotto52.ki','a',encoding='utf-8') as lottoFile:
    lottoFile.write('\n')
    lottoFile.write(" ".join([str(e) for e in szamok]))

Második elgondolás

2. Ha megnyitom írásra az új “lotto52.ki” állományt beleírom az osszesHet list tartalmát és még a szamok listát is!

3. Sőt, hivatalosan az osszesHet listához hozzáfűzhetném a számokat és akkor csak az osszesHet listát kellene kiírnom az új állományba.
Ám ez azért veszélyes, mert akkor a következő feladatot esetleg egy “általam” (értsd: felhasználó) bővített listával kellene megoldanom, ami veszélyes, mert sehol nem ellenőriztem a bekért adatokat.

Egyébként ez lesz a legjobb megoldás, mert a nyolcadik feladat mind az 52 hét adataival akar majd dolgoztatni.

Tehát a 2. verziót fogom megoldani

print('7. feladat')
with open('lotto52.ki','w',encoding='utf-8') as lottoFile:
    for het in osszesHet:
        lottoFile.write(" ".join([str(e) for e in het]))
        lottoFile.write('\n')
    lottoFile.write(" ".join([str(e) for e in szamok]))

Vagy a 3. verzió megoldása

print('7. feladat')
osszesHet.append(szamok)
with open('lotto52.ki','w',encoding='utf-8') as lottoFile:
    for het in osszesHet:
        lottoFile.write(" ".join([str(e) for e in het]))
        lottoFile.write('\n')

8. feladat

Határozza meg a lotto52.ki állomány adatai alapján, hogy az egyes számokat hányszor húzták ki 2003-ban. Az eredményt írja ki a képernyőre a következő formában: az első sor első eleme az a szám legyen ahányszor az egyest kihúzták! Az első sor második eleme az az érték legyen, ahányszor a kettes számot kihúzták stb.! (Annyit biztosan tudunk az értékekről, hogy mindegyikük egyjegyű.)

Példa egy lehetséges eredmény elrendezésére (6 sorban, soronként 15 érték).

szamsor

Az elgondolás

Végig megyek az összes kihúzott számon és fogok egy listát és azon indexű elemeinek értékét növelem, amelyik egyenlő egy kihúzott számmal.

újlista feltöltve 0-kal
Ciklus 1 héttől összeshétig
  Ciklus  1 számtól a hétszámáig
       újlista[szám] = újlista[szám] + 1

Már csak a kiírással kell megbirkózni

Ciklus i=0-tól 5-ig
  Ciklus j=i*15 -től i*15+15-ig
       kiírni újLista[j]
  kiírni sortörés

A megoldás

print('8. feladat')
ujLista = [0 for i in range(0,90)]
for het in osszesHet:
    for szam in het:
        ujLista[szam-1] += 1

A kiírása

for i in range(0,6):
    print(" ".join([str(e) for e in ujLista[i*15:i*15+15]]))

9. feladat

Adja meg, hogy az 1-90 közötti prímszámokból melyiket nem húzták ki egyszer sem az elmúlt évben. A feladat megoldása során az itt megadott prímszámokat felhasználhatja vagy előállíthatja! (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89.)

Az előző feladatban minden egyes számról megtudtam hányszor fordult elő, csak végig kell mennem a lista azon  indexű elemein, amelyek prímszámok és megvizsgálni nulla-e a bennük tárolt érték.

primek = 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89
Ciklus egyprim a primek listában
   ha újLista[egyprim] = 0 akkor kiir "ezt nem húzták ki"

A megoldás

print('9. feladat')
primek = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89]
joPrim = []
for egyPrim in primek:
    if ujLista[egyPrim-1] == 0:
        joPrim.append(egyPrim)
print('A prímek, amelyeket nem húztak ki: ')
print(', '.join(str(e) for e in joPrim))