Informatika érettségi 2005. Május
Ez volt az első emelt szintű informatika érettségi. Akkoriban még a Pascal volt az elsődlegesen preferált és legjobban oktatott programozási nyelv.
A feladatkiírás
Magyarországon 1957 óta lehet ötöslottó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öslottó 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.
Az állományból kimaradtak az 52. hét lottószámai. Ezek a következők voltak: 89 24 34 11 64.
Készítsen programot a következő feladatok megoldására!
- Kérje be a felhasználótól az 52. hét megadott lottószámait!
- A program rendezze a bekért lottószámokat emelkedő sorrendbe! A rendezett számokat írja ki a képernyőre!
- 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!
- Írja ki a képernyőre a bekért számnak megfelelő sorszámú hét lottószámait, a lottosz.dat állományban lévő adatok alapján!
- 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!
- 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!
- 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!
- 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):
4 2 2 4 2 2 6 1 1 2 1 5 2 1 1
1 3 5 0 5 5 2 6 6 5 1 0 6 4 3
3 3 5 4 3 1 4 2 2 4 2 4 1 2 3
4 2 1 2 3 2 2 2 4 4 5 1 3 5 5
5 2 0 2 2 4 4 3 1 3 6 1 5 6 2
4 3 2 2 3 1 1 4 1 3 3 2 1 5 3
- 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.)
A megoldás
1. Kérje be a felhasználótól az 52. hét megadott lottószámait!
Az első feladat beugratós része, hogy sehol sincs a feladatkiírás szövegében kijelentve, hogy nem kell ellenőrizni a bevitt adatot. Vagyis a megoldáskor pontosan 5db olyan számot kell beolvasnunk, amik 1 és 90 közé esnek.
Ez könnyen kivitelezhető egy do-while ciklussal, ahol a ciklusmagban a számlálót csak akkor léptetjük tovább, ha valóban elfogadható számot kaptunk. Arra, hogy tényleg számot kaptunk-e, az int struktúra TryParse metódusát használjuk, ami egy logikai érték visszaadásával jelzi, hogy sikerült a szöveget átalakítania számmá, vagyis a bemenet tényleg szám. Ezután még meg kell nézni, hogy a szám nagyobb-e mint 0 és kisebb-e mint 91.
Az _utolsoHet változó egy List<int> típus a megoldást tartalmazó osztályban.
public void Feladat01()
{
//ellenőrzött bekérés, mivel a feladat nem mondja, hogy ne legyen ellenőrzött
Console.WriteLine("Kérem adja meg az 52. hét lottószámait. Egy szám/sor!");
int szam = 1;
do
{
Console.Write("{0}. szam: ", szam);
if (int.TryParse(Console.ReadLine(), out int beolvasott)
&& beolvasott > 0
&& beolvasott < 91)
{
_utolsoHet.Add(beolvasott);
++szam;
}
}
while (szam <= 5);
}
2. A program rendezze a bekért lottószámokat emelkedő sorrendbe! A rendezett számokat írja ki a képernyőre!
A második feladatnak nekiállhatunk favágó módon valami rendezési algoritmus leimplementálásával, vagy szofisztikáltan. Jelen esetben az utóbbit választottuk. A List<T> adatszerkezet előnye, hogy van egy Sort() metódusa, ami az elemeket sorba rendezi.
Ezután csak egy egyszerű foreach ciklussal végigmegyünk az elemeken és kiírjuk őket.
public void Feladat02()
{
Console.WriteLine("Az 52. hét lottószámai:");
_utolsoHet.Sort();
foreach (var szam in _utolsoHet)
{
Console.Write("{0} ", szam);
}
}
- 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!
Itt explicit jelezve van, hogy nem kell ellenőrizni. Ezért a feladatmegoldás ténylegesen csak egy sor olvasásból és egy számmá konvertálásból áll. A _bevittHet változó int típusú a megoldásokat tartalmazó osztályban, mivel még később szükség lesz rá.
public void Feladat03()
{
Console.WriteLine("Adjon meg egy hetet 1-51 között:");
_bevittHet = int.Parse(Console.ReadLine());
}
- Írja ki a képernyőre a bekért számnak megfelelő sorszámú hét lottószámait, a lottosz.dat állományban lévő adatok alapján!
A feladat beugratós egy kicsit. Itt kell először beolvasni a lottosz.dat szöveges fájlt, de ez ne tévesszen meg bennünket. Az érettségi feladatok közös jellemzője (főként a későbbieké), hogy a fájl tartalma több feladatban fog kelleni. Ezért a megoldást úgy érdemes elkészíteni, hogy a későbbi feladatokban is felhasználható legyen.
A feladatkiírást elolvasva a számokra egyenként lesz szükségünk heti bontásban. Itt lehetne használni egy kétdimenziós tömböt, vagy egy listát, ami tömbökből áll. A megoldás során két okból is az utóbbit választottuk: a lista dinamikusan bővülhet, ezért később módosítás nélkül több hét adataival is elboldogul. A tömbök listájának másik előnye, hogy gyorsabb a kezelésük, mint a többdimenziós tömböknek. Ennek oka a CLR memória kezelésében keresendő.
public void Feladat04()
{
//beolvasás
using (var file = File.OpenText("lottosz.dat"))
{
string? sor = null;
do
{
sor = file.ReadLine();
if (!string.IsNullOrEmpty(sor))
{
int[] be = sor
.Split(' ')
.Select(szam => int.Parse(szam))
.ToArray();
_lottoszamok.Add(be);
}
}
while (sor != null);
}
//kiíratás
int[] szamok = _lottoszamok[_bevittHet-1];
Console.WriteLine("A {0}. hét lottó számai: ", _bevittHet);
foreach (var szam in szamok)
{
Console.Write("{0} ", szam);
}
}
A beolvasás soronként történik. Mivel az adatok szóközzel vannak elválasztva, ezért a string osztály Split metódusával felvágjuk őket szóközönként. Az egyes elemeket LINQ segítségével számmá konvertáljuk, majd az eredményt tömbbé alakítjuk, amit hozzáfűzünk a listához.
Ezután már csak a megfelelő hétre kell pozicionálni a listában és kiírni az elemeket egy foreach ciklussal.
- 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!
A feladat lényegében egy számolás. Végig kell olvasni a számokat és számolni az előfordulásukat, majd ezek között meg kell nézni, hogy volt-e olyan, ami 0 alkalommal szerepel. Ez megoldható lenne egy tömbbel is, de mivel van halmaz adatszerkezetünk, ami biztosítja, hogy egy elem pontosan csak egyszer szerepelhet a halmazban, megoldhatjuk úgy is a problémát, hogy a számokat egy halmazhoz adjuk. Ha a szám már benne van a halmazban, akkor nem fog semmi történni.
Ezután meg kell nézni a halmaz elemeinek a számát. Ha ez 90, akkor minden számot kihúztak már.
public void Feladat05()
{
//Halmaz. 1 adott elem csak 1x szerepelhet
HashSet<int> kihuzott = new HashSet<int>();
//halmaz feltöltése a kihúzott számokkal
foreach (int[] het in _lottoszamok)
{
foreach (int szam in het)
{
kihuzott.Add(szam);
}
}
//ha a halmaz elemeinek száma nem 90,
//akkor volt olyan, mit nem húztak ki
if (kihuzott.Count == 90)
{
Console.WriteLine("Nincs");
}
else
{
Console.WriteLine("Van");
}
}
- 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!
Ez a feladat lényegében egy számolás némi feltétellel. Ez elég könnyű leimplementálni LINQ segítségével. Itt a query syntaxot alkalmaztuk a kiválasztás leírására a jobb olvashatóság érdekében.
public void Feladat06()
{
var paratlanok = from het in _lottoszamok
from szam in het
where szam % 2 == 1
select szam;
Console.WriteLine("Páratlan számok száma: {0}", paratlanok.Count());
}
- 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!
Elérkeztünk a fájl írás feladathoz. Itt ugyanolyan formátumban kell kiírnunk az adatokat bővítve, mint amilyen formátumban kaptuk.
public void Feladat07()
{
using (var kimmenet = File.CreateText("lotto52.ki"))
{
foreach (int[] het in _lottoszamok)
{
kimmenet.WriteLine(string.Join(' ', het));
}
kimmenet.WriteLine(string.Join(' ', _utolsoHet));
}
}
- 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):
Ebben a feladatban ténylegesen számolnunk kell az elemek előfordulását. Erre a legjobban egy Dictionary<TKey, Tvalue> típus alkalmas. A kulcs jelen esetben a szám lesz, a hozzá tartozó érték pedig az előfordulások száma. A számolási algoritmus végigmegy minden számon. Ha a _statisztika Dictionary tartalmazza az elemet, akkor növeljük a hozzátartozó értéket. Ellenkező esetben felvesszük egyes értékkel.
A _statisztika Dictionary a megoldást tartalmazó osztályban került elhelyezésre, mivel egy későbbi feladatban még szükség lesz rá.
A kiírás egy kicsit meg van csavarva. Egy sorba 15db számot kell írni. Ezért a kiíráskor számolni kell, melyik elemnél járunk és minden 15. után be kell iktatni egy sortörést.
public void Feladat08()
{
//9. feladatban kell majd még a statisztika
var osszesszam = new List<int[]>(_lottoszamok);
osszesszam.Add(_utolsoHet.ToArray());
//Összeszámolás
foreach (int[] het in osszesszam)
{
foreach (int szam in het)
{
if (_statisztika.ContainsKey(szam))
{
++_statisztika[szam];
}
else
{
_statisztika.Add(szam, 1);
}
}
}
//kiírás
int darab = 0;
foreach (KeyValuePair<int, int> stat in _statisztika)
{
Console.Write("{0} ", stat.Value);
darab++;
if (darab == 15)
{
//15 elem után sortörés
Console.WriteLine();
darab = 0;
}
}
}
- 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 elkészült statisztika felhasználásával megoldható a feladat. Végig kell menni a prím számok listáján és megnézni, hogy melyik nem szerepel a statisztikában. A feladat volt annyira kedves, hogy megadta a prím számok listáját, de ahogy mondja, le is implementálhatjuk a saját megoldásunkat. Mi le is implementáltuk 🙂
private HashSet<int> Primek90ig()
{
var primek = new HashSet<int> { 1, 2, 3, 5, 7};
bool prim = true;
for (int szam=11; szam<91; szam+=2)
{
prim = true;
for (int oszto=2; oszto < (szam / 2); oszto++)
{
if (szam % oszto == 0)
{
prim = false;
}
}
if (prim)
{
primek.Add(szam);
}
}
return primek;
}
A feladat tényleges megoldása:
public void Feladat09()
{
HashSet<int> primek = Primek90ig();
Console.WriteLine("Ki nem húzott prímek: ");
foreach (var prim in primek)
{
if (!_statisztika.ContainsKey(prim))
{
Console.Write("{0} ", prim);
}
}
}
A teljes forráskód itt található: https://github.com/CsharptutorialHungary/eretsegikodok