A 2018-as középszintű matematika érettségi feladatsor 10. feladata inspirált arra, hogy a programozás eszköztárával oldjuk meg ezt a feladatot. Szükséges hozzá néhány programozási tétel: sorozatszámítás, eldöntés, kiválasztás. Érdekes belegondolni, hogy mennyire más lehetne a problémamegoldás, ha programozhatnánk a matematika érettségi vizsgán. A teljes feladatsor a megoldásokkal együtt letölthető az oktatas.hu-ról.
10. feladat
Adja meg az alábbi adathalmaz móduszát, mediánját és terjedelmét!
2; 6; 6; 6; 6; 6; 3; 3; 4; 4; 4; 5; 5; 5; 5
Tervezés
A Java 8 által biztosított újdonságok közül használunk néhányat. Célszerű konstans tömbben tárolni a megadott számsorozatot, ami könnyen konvertálható generikus listába. Alkalmazkodni kell ahhoz, hogy a lista indexelése 0-tól lista.size()-1 -ig értelmezhető. Hasznos, ha a konkrét feladatok helyett általános megoldásokban gondolkodunk és a feladatot 3 metódusra bontjuk, amelyek ellenőrzéseket is végeznek. Például extrém esetek:
- ha a lista üres, akkor nincs módusz, medián, terjedelem,
- ha a lista egyetlen elemből áll, akkor a módusz és a medián megegyezik az elemmel, a terjedelem pedig nulla,
- ha leggyakrabban több különböző szám is előfordul, akkor a módusz ezek közül a (leg)kisebb számot adja vissza.
Elvárjuk, hogy probléma esetén a metódusok dobjanak kivételt. Lényeges, hogy a referencia szerinti paraméterátadás során megváltozna a listában az elemek sorrendje, mert a megoldás igényli az elemek rendezettségét, akkor készüljön másolat az adatszerkezetről, hogy egy-egy részfeladat megoldása nem járjon azzal a mellékhatással, hogy az eredeti adatszerkezetben megváltozik az elemek sorrendje. Felhasználjuk a primitív típusú változók és a csomagolóosztályok közötti konverziós lehetőségeket: autoboxing és unboxing.
Megoldás: módusz
A módusz a lista leggyakoribb értékét adja meg. Másképpen az az érték, amelyik az adatsorban a legtöbbször előfordul.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public static int modusz(List<Integer> szamLista) { if(szamLista.isEmpty()) throw new IllegalArgumentException("Hiba! Üres lista."); List<Integer> lista= szamLista.stream().collect(Collectors.toList()); Collections.sort(lista); int i=0, maxAktSzam=0, maxAktSzamDb=0; while(i<lista.size()) { int aktSzam=lista.get(i), aktSzamDb=0; while(i<lista.size() && lista.get(i)==aktSzam) { aktSzamDb++; i++; } if(aktSzamDb>maxAktSzamDb) { maxAktSzam=aktSzam; maxAktSzamDb=aktSzamDb; } } return maxAktSzam; } |
A modusz() metódus átveszi a szamLista-t és készít róla lista néven egy másolatot, majd utóbbit növekvő sorrendbe rendezi. A másolat a Stream API-val készül el. Ezután csoportváltás algoritmussal feldolgozza a listát. Egy csoportba az azonos számok kerülnek és léptetés közben a belső ciklus megszámolja, hogy hány azonos szám alkotja az aktuális csoportot. Végül összehasonlítás következik a szélsőérték-kiválasztás ( aktSzamDb>maxAktSzamDb) beépítésével.
Megoldás: medián
A medián a lista középső értéke, amelynél az ennél kisebb és nagyobb elemek száma azonos. Rendezett adatsornál páratlan elemszám esetén a középső elem, illetve páros elemszám esetén a két középső elem átlaga.
1 2 3 4 5 6 7 8 9 10 11 |
public static double median(List<Integer> szamLista) { if(szamLista.isEmpty()) throw new IllegalArgumentException("Hiba! Üres lista."); List<Integer> lista= szamLista.stream().collect(Collectors.toList()); Collections.sort(lista); int n=lista.size(); return n%2==0? (lista.get((n-1)/2)+lista.get((n-1)/2+1))/2.0 : lista.get((n-1)/2); } |
A median() metódus átveszi a szamLista-t és készít róla lista néven egy másolatot, majd utóbbit növekvő sorrendbe rendezi. Ezután páros elemszám esetén visszaadja a két középső elem átlagát, illetve páratlan elemszám esetén a középső elemet. A metódusnak valós értéket ( double) kell visszaadnia, mert a két középső elem átlaga nem feltétlenül egész szám.
Megoldás: terjedelem
A terjedelem azt mutatja meg, hogy mekkora értékközben ingadoznak a lista elemei. A terjedelem az adatok változékonyságának „legdurvább” jellemzője, ami a szélsőértékek (minimum és maximum) közötti különbséget jelenti.
1 2 3 4 5 6 |
public static int terjedelem(List<Integer> szamLista) { if(szamLista.isEmpty()) throw new IllegalArgumentException("Hiba! Üres lista."); int min=Collections.min(szamLista), max=Collections.max(szamLista); return max-min; } |
A terjedelem() metódus átveszi a szamLista-t paraméterként és visszaadja a két szélsőérték különbségét, amelyek a Collections osztály metódusaival könnyen előállítható. Persze egyetlen ciklussal is megkaphatnánk a két szélsőértéket.
Eredmény
A vezérlést az alábbi main() metódus végzi el:
1 2 3 4 5 6 7 8 9 10 |
public static void main(String[] args) { int[] szamTomb={2, 6, 6, 6, 6, 6, 3, 3, 4, 4, 4, 5, 5, 5, 5}; List<Integer> szamLista= Arrays.stream(szamTomb).boxed().collect(Collectors.toList()); System.out.println( "A sorozat elemei: "+szamLista+"\n"+ "Módusz: "+modusz(szamLista)+"\n"+ "Medián: "+median(szamLista)+"\n"+ "Terjedelem: "+terjedelem(szamLista)); } |
A konzolon az alábbi eredményt kapjuk:
1 2 3 4 |
A sorozat elemei: [2, 6, 6, 6, 6, 6, 3, 3, 4, 4, 4, 5, 5, 5, 5] Módusz: 6 Medián: 5.0 Terjedelem: 4 |
Ajánljuk matematika érettségi feladat címkénket, mert a témában évről-évre blogolunk.
A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.
A feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 17-28. óra: Objektumorientált programozás alkalmaihoz kötődik.
Gyakoroltam ezt a feladatot is. A Stream API sorted() metódusával kicseréltem ezt:
erre:
Mindig jó ez a megoldás?
Általánosan igen Anett. A
Collections.sort()
metódus helyettesíthető astream().sorted()
metódussal. A konkrét példában egész számok vannak a generikuslista
adatszerkezetben és azInteger
osztályban létezikcompareTo()
metódus, ami a háttérben meghívódik ilyenkor. Ha saját típussal dolgoznál, akkor implementálnod kell rájuk összehasonlító képességet, azaz aComparable
interfészt (belülről) vagy aComparator
interfészt (kívülről). A következő óránkon mutatok majd rá példát.