Euler állatos feladata – geometriai megközelítés

EulerAllat

EulerAllatValaki sertést, kecskét és juhot vásá­rolt, összesen 100 állatot, pontosan 100 aranyért. A sertés darabja 3 és fél arany, a kecskéé 1 és egyharmad, a juhoké fél arany. Hány darabot vehetett az egyes állatokból?

Tudjuk, hogy a feladatnak három megoldása van:

  • 5 db sertés és 42 db kecske és 53 db juh
  • 10 db sertés és 24 db kecske és 66 db juh
  • 15 db sertés és 6 db kecske és 79 db juh

Klasszikus informatikai megközelítést – egymásba ágyazott ciklusokat – bemutattam már: Euler állatos feladata. A brute force alapgondolat fokozatos finomítását követően néhány ötleteket is adtam a továbbfejlesztéshez. Ez igazi örökzöld feladat. Látogatottsága alapján rendületlenül népszerű ez a blog bejegyzés az it-tanfolyam.hu szakmai blogban. Többek között ez inspirált a feladattal való további foglalkozásra.

Mit jelent a geometriai megközelítés?

Egy térbeli pont három koordinátával leírható. Az (s, k, j) ponthármas jelenti a sertések, kecskék és juhok számát. Az RGB színkockához hasonlóan (amibe belefér az összes ábrázolható színhez tartozó koordinátapont), most is elférünk egy kockában. Legyen a kocka egyik csúcsa az origó és az élei legyenek 100 egység hosszúak. A feladat megfogalmazása alapján két egyenlet (e1 és e2) írható fel 3-3 együtthatóval. Mindkét egyenlet meghatároz egy síkot (s1 és s2) a térben, amelynek ábrázoljuk a kockába eső síkmetszeteit. A két sík metszésvonala egyenes (e3), amire esnek a megoldások pontjai (m1, m2, m3). Lépésenként haladunk a geometriai ábrázolás során.

A grafikus felületen történő ábrázoláshoz, rajzoláshoz két korábbi projektünkből indulunk ki. A Kígyókocka grafikus felületen feladat ismertet egy grafikus keretrendszert JavaFX-ben megvalósítva. A három részből álló Naprendszer szimuláció esettanulmányunk pedig ismerteti az ábrázoláshoz szükséges elméleti hátteret, homogén transzformációkat, vetületi leképezést, Java forráskódot is bemutat a transzformációs mátrix alkalmazására.  Az eddig említett három blog bejegyzést mind összeépítve készültek a továbbiak.

A geometriai megoldást lépésenként, saját fejlesztésű, grafikus felhasználói felülettel rendelkező, JavaFX alapú programról készült képernyőképek mutatják be – markáns Java forráskód-részletekkel.

Hogy jelenik meg a megoldásokat tartalmazó kocka?

Elegendő ábrázolni a kockának azt a három élét, amik egybeesnek a koordinátatengelyekkel. Az RGB színkockához hasonlóan piros, zöld, kék színekkel jelennek meg a három tengelyen lévő néhány pont. Az ábrázoláshoz érdemes kísérletezni egy kicsit: mekkora méretben (skála), honnan (nézőpont), milyen messziről (vetület, ideális pont, perspektíva, távolság) látszik a modelltérbeli objektum (igen, ez a kocka).

Az alábbi Java forráskód-részlet helyezi el a fenti pontokat. Mindhárom tengelyen 5-től 95-ig, 10-esével haladunk. Így elkerülhető, hogy az origóba kerüljön pont, hiszen az nem tudna egyszerre három színnel megjelenni. Mivel az állatok száma pozitív, így a koordinátapontok is nemnegatívak.

Hol vannak az első egyenlet síkjának pontjai?

A korábbi megoldásnál feltételként megfogalmazott első 3.5*s+4.0/3*k+0.5*j==100 egyenlet egyszerű átalakításokkal megadja a piros és zöld síkbeli ponthoz tartozó kék térbeli pontot: j=(600-21*s-8*k)/3. Ezek az s1 síkra esnek. A citromsárga pontokat páros koordinátapárokra vizsgált feltétel jelöli ki. A narancssárga vonal behatárolja ezt a síkmetszetet. Ez a négyszög (trapéz) esik bele a kockába.

A citromsárga pontokat az első egymásba ágyazott ciklusok adják hozzá az ábrázolt modelltérhez: érzékeltetve a síkbeli pontokat. A narancssárga pontokkal a második egymásba ágyazott ciklusok bővítik a modellteret: behatárolva a kockabeli négyszög síkrészletet. (A trapéz oldalait szakaszként is lehetne ábrázolni, de ez a kellően sűrű ponthalmaz is elegendő).

Hol vannak a második egyenlet síkjának pontjai?

Hasonlóan az eddigiekhez. A korábbi  s+k+j==100 feltételből adódik a szintén feltételként megfogalmazott  j==100-s-k egyenlet. Ezek az s2 síkra esnek. Világosszürke pontok érzékeltetik a síkot és sötétszürke pontok adják a síkrészlet határait. A síkból ez a háromszög esik bele a kockába.

A Java forráskód nagyon hasonló az előzőhöz.

Hogyan helyezkedik el a két sík a kockában?

Egyben kirajzoltatva a fentieket, könnyen adódik ez az ábra:

Hol van a két sík metszésvonala?

Mivel a két sík nem esik egybe, így van metszésvonaluk. Ez egy egyenes, amiből csak az az e3 szakasz rész szükséges, ami a kockába esik. Bíbor (magenta) szín jelöli az alábbi ábrán:

Ahol a két egyenlethez tartozó konkrét pontok egybeesnek, ott van a metszésvonal. A behelyettesítést behatároló ciklusok szervezéséből (a ciklusváltozók alsó és felső és határaiból) adódik, hogy csak a kockabeli szakaszt rajzolja ki az alábbi Java forráskód-részlet:

Hol jelenik meg a feladat három megoldása?

A két egyenlethez tartozó síkok kockába eső metszésvonalán helyezkednek el az egész koordinátákkal ábrázolható, koordináta-hármasként megjelenő pontok. Nagyobb fehér pontok jelölik ezeket az alábbi ábrán:

Az eddigiek alapján könnyen adódik a három pont/megoldást ábrázoló Java forráskód-részlet:

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ez a feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 5-8. óra: Vezérlési szerkezetek, illetve 9-12. óra: Metódusok, rekurzió alkalmához, a 29-36. óra Grafikus felhasználói felület alkalmaihoz, valamint minden tanfolyamunk orientáló moduljának 1-4. óra: Programozási tételek alkalmához kapcsolódik.

Tanfolyamainkon JavaFX grafikus felülettel hangsúlyosan nem foglalkozunk, de egy-egy kész forráskódot közösen megbeszélünk, és össze is hasonlítjuk a swing-es változattal. Fejlesztünk játékprogramot, de inkább konzolosan, vagy swing-es ablakban, vagy webes alkalmazásként.

A grafikus felületek felépítésének megismerése fontos lépcső az objektumorientált programozás elmélyítéséhez, gyakorlásához. A grafikus felületekhez egy másik lényeges szemléletváltás is kapcsolódik, hiszen a korábbi algoritmusvezérelt megközelítést felváltja az eseményvezérelt (eseménykezelés). A GUI-s feladatainkat tudatosan hangsúlyozott MVC-s projektekben készítjük el.

Skandináv lottó előállítása változókkal és rekurzióval

Újra skandináv lottó (heteslottó) szelvényt generálunk Java programmal. Két különböző elven megvalósuló megoldást hasonlítunk össze. A megoldást lépésenként bemutató, grafikus felhasználói felületű, saját fejlesztésű programunkról blogoltunk már: Skandináv lottó demóprogram. Most másképpen gondolkodunk – reméljük közösen.

Építünk az alábbi tipp() függvényre:

Ennek a függvénynek lokális felelőssége van, azaz előállít egyetlen olyan véletlenszámot, ami megfelelő a skandináv lottószelvényre. Másképpen 1 és 35 közötti (zárt intervallum) egész szám.

A globális felelősség a megoldások során azt biztosítja, hogy minden szám egyedi/különböző legyen és 7 db véletlenszám legyen.

1. megoldás

Az első megoldás során csupán egyszerű változók jelentik az emlékezetet. Külön adatszerkezet (tömb, lista, halmaz) nincs. A lotto1() metódus valósítja meg az alábbiak szerint:

Az a egész ( int) típusú változó ellenőrzés nélkül előállítható, mert az első szám biztosan egyedi. A b változót csak az a-val kell összehasonlítani. Célszerű a do while hátultesztelő ciklus alkalmazása. A b-t addig tippeltetjük újra és újra, amíg szükséges. Másképpen: amíg a megegyezik b-vel ( a==b), addig nem jó a b és ezért újra kell generálni. A c változó esetében már a korábban előállított a-val és b-vel is össze kell hasonlítani, hiszen c-nek mindkettőtől különböznie kell. Másképpen (1): amíg a==c vagy b==c, addig nem jó a c és ezért újra kell generálni. Másképpen (2): amíg nem igaz, hogy a különbözik c-től és b is különbözik c-től, addig meg kell ismételni a c előállítását. Kiválóan megérhető a gondolatmenet alapján a megoldás során használt De Morgan azonosság. És így tovább a többi változóval is: d, e, f, g. Nehézkes a sok változó külön-külön való kezelése és figyelmesen kell megírni Java nyelven a hosszú forráskódot. Az eredmény a konzolon jelenik meg, például így:

Kompromisszum, hogy a lottószelvényre kerülő véletlenszámok sorrendje is véletlen. Másképpen: a véletlenszámok nem „emelkedő számsorrendben” jelennek meg.

2. megoldás

Most nem használunk ciklus utasítást. Persze a lottószelvényre kerülő véletlenszámok előállítása megköveteli az ismétlést a vezérlés megvalósítása során. Az ismétlést rekurzív vezérlés oldja meg. Az emlékezetet most TreeSet jelenti. Ez egy generikus, Integer típusú adatszerkezet, amely a java.util csomagbeli kollekció keretrendszer része. Rendezett halmazként működik. Cím szerinti paraméterátadással kapja meg a metódus és kezdetben üres. Addig kell beletenni újonnan előállított véletlenszámot, amíg „egyszer csak” eléri az elemszáma a 7-et. Ha olyan elem kerül a halmazba, ami már benne van, akkor az add() halmazbővítő művelet hatástalan.

A rekurzió során a lotto2() függvény saját magát hívja meg. Működése során kihasználja, hogy az adatszerkezet „menet közben” megváltozik (bővül). A lottószelvényre kerülő véletlenszámok sorrendje egyfajta mellékhatásként valósul meg, mert a TreeSet típusú kollekció automatikus képessége. Az eredmény a konzolon jelenik meg, például így:

Ha érdekelnek bennünket a részletek, akkor a rekurzív vezérlés kiegészíthető a lotto3() metódusnál látható szint paraméterrel és néhány kiírással az alábbiak szerint:

Az önmagyarázóvá tett forráskód például az alábbi eredményt írhatja ki a konzolra:

Jól látható, hogy mennyi lépést igényel a lottószelvény előállítása, mikor fordult elő ismétlődés a véletlenszámok előállítása során.

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 9-12. óra: Metódusok, rekurzió alkalomhoz, illetve a 21-24. óra: Objektumorientált programozás, 2. rész alkalomhoz kötődik.

Top 5 fizetésű alkalmazottak listája

Top5 fizetés

Top5 fizetésAz a fela­da­tunk, hogy az Oracle HR sé­má­ból le­kér­dez­ve állít­suk elő a top 5 fizetésű alkalmazottak listáját, a fizetések csökkenő sorrendjében. Ez egytáblás lekérdezéssel megvalósítható. Az EMPLOYEES táb­lában megtalálható az összefűzött névhez szükséges FIRST_NAME és LAST_NAME mezők, valamint a fizetés a SALARY mezőben. Min­den alkalmazottnak van neve és fizetése. Előfordul legalább 5 különböző fizetés.

Oracle HR séma

Tanfolyamainkon többféleképpen modellezzük és tervezzük meg a feladat megoldását.

Megoldás (Java SE szoftverfejlesztő tanfolyam)

A Java SE szoftverfejlesztő tanfolyam 45-52. óra: Adatbázis-kezelés JDBC alapon alkalmain a következők szerint modellezünk és tervezünk.

Kiindulunk az alábbi egyszerű lekérdező parancsból (V1):

Top5SalaryV1Select

Eredményül ezt kapjuk (részlet, V1):

Top5SalaryV1 Eredmény

A kapott 107 rekordból álló eredménytáblát a Java kliensprogram fejlesztése során leképezzük egy generikus POJO listába, a rekordonként összetartozó két adatból előállítva az objektumok tulajdonságait. Kiderül, hogy a 17000 többször is előfordul. Mivel bármely fizetés előfordulhatna többször is, így előre nem tudjuk, hogy az eredménytáblából mennyi rekordot kell áttölteni a listába. A fizetésekből generikus halmazt építhetve, addig tudjuk folytatni a beolvasást, amíg a halmaz elemszáma kisebb ötnél. Eredményül hat rekordot kapunk. A Java kliensprogram forráskódját most nem részletezzük, de tanfolyamaink hallgatói számára ILIAS e-learning tananyagban tesszük elérhetővé a teljes forráskódot. Ennél a megoldásnál egyszerűbb a lekérdező parancs, de több feladat hárul a Java kliensprogramra.

Lássunk néhány tévutat és az általános megoldás helyett konkrét megoldásokat! Ha szeretnénk adatbázis oldalon megoldani a feladatot, akkor használhatnánk a ROWNUM pszeudooszlopot. Ez 1-től sorszámozza az eredménytáblát, így használható lehetne arra, ha limitálni szeretnénk a visszaadandó rekordok számát.

1. elvi hibás lekérdező parancs:

Top5SalaryV2 Select

1. elvi hibás eredmény:

Top5SalaryV2 Eredmény

A hiba elvi, a lekérdező parancs szintaktikailag helyes. A harmadik oszlopban látjuk, hogy a rekordok sorszámozása megtörténik, de a kapott nevek és fizetések eltérnek a V1 esetben kapott helyes eredménytől. Az okokat természetesen megbeszéljük. Támpont: próbáljuk meg a lekérdező parancs feltételében kicserélni az 5-öt például 10-re és próbáljuk megmagyarázni, miért kapjuk azt, amit kapunk. Továbbá a konkrét esetben tudjuk, hogy hat rekordot kellene kapunk. Felmerülhet a gyanú, hogy a rendezés túl későn történik meg. Megpróbáljuk zárójelezéssel és lekérdezések egymásba ágyazásával befolyásolni a WHERE és ORDER BY alparancsok végrehajtási sorrendjét.

2. elvi hibás lekérdező parancs:

Top5SalaryV3 Select

2. elvi hibás eredmény:

Top5SalaryV3 Eredmény

A hiba most is elvi, a lekérdező parancs szintaktikailag helyes. A zárójelezés valóban hatással van a két alparancs végrehajtási sorrendjére és megfigyelhető, hogy a harmadik oszlopban a rekordok táblabeli fizikai sorrendje jelenik meg és a feltétel ( ROWNUM <= 5) nem a mező értékére, hanem a rekordok darabszámára értendő. Nyilván az 5-öt 6-ra módosítva visszakaphatnánk a V1 első hat rekordját, de ez nem lenne általános megoldás. Más úton is eljuthatunk a konkrét megoldáshoz.

3. elvi hibás lekérdező parancs:

Top5SalaryV4 Select

3. konkrét megközelítéssel kapott helyesnek látszó eredmény:

Top5SalaryV4 Eredmény

A hiba most is elvi, a lekérdező parancs szintaktikailag helyes. Általános megoldás helyett konkrét megoldásként megkapjuk a V1 első hat rekordját, de ehhez be kellett építeni a lekérdező parancsba a 13000-et. Ez a Top 5-ben legkisebb fizetés. Megbeszéljük, hogy miért hasznos a DISTINCT módosító/kulcsszó beépítése a lekérdező parancsba.

Megoldás (Java adatbázis-kezelő tanfolyam)

A Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalmával a következők szerint modellezünk és tervezünk.

Most arra helyezzük a hangsúlyt, hogy back-end, azaz adatbázis oldalon állítsuk elő az eredményt és ezáltal a front-end, azaz a Java kliensprogram egyszerűbb lehet. A lekérdező parancsot belülről kifelé haladva gondoljuk végig. Először kell egy halmaz a különböző fizetésekről csökkenő sorrendben. Utána ebből kell az első öt darab, amelyek halmazt alkotnak. Végül erre építve kell azoknak az alkalmazottaknak a neve és fizetése, akiknek a fizetése benne van a halmazban.

1. majdnem helyes megoldás:

Top5SalaryV5 Select

1. általános megközelítéssel kapott helyesnek látszó eredmény:

Top5SalaryV4 Eredmény

A probléma az, hogy az adatok helyes sorrendje a véletlennek köszönhető. Ha a lekérdező parancs feltételében az 5 helyett nagyobb számokat helyettesítünk be, akkor ez jól megfigyelhető. A következő megoldás már ezt a problémát is kezeli.

Finomítva a 3. elvi hibás lekérdező parancsot, a konkrét 13000 helyettesíthető belső lekérdező paranccsal. Építsük ezt be az 1. helyes megoldásba úgy, hogy az IN predikátum helyett használjuk a nagyobb vagy egyenlő hasonlító operátort. A középső lekérdező parancs a halmaz helyett már csak egyetlen értéket adjon vissza, amelyhez könnyű hasonlítani az aktuális alkalmazott fizetését. Ezzel kiváltható a nagyobb memóriaigényű halmazban való tartalmazottságot eldöntő művelet, a jóval hatékonyabb egy értékkel való összehasonlítással. Memóriaigény szempontjából nem maga a konkrét művelet/operátor az érdekes, hanem a használatukhoz szükséges adatok előállítása, mennyisége, tárolása, feldolgozása.

2. helyes megoldás:

Top5SalaryV6 Select

2. általános megközelítéssel kapott helyes eredmény:

Top5SalaryV4 Eredmény

Közben az is kiderült, hogy miért szükséges két helyen az ORDER BY alparancs.

Végül, ha ismerjük az Oracle DENSE_RANK() analitikai függvényét, amely egy rendezett lista különböző elemeihez rendel sorrendben számokat (másképpen rangsort állít fel 1-től kezdve), akkor elkészíthetjük az alábbi megoldást.

3. helyes megoldás:

Top5SalaryV7 Select

3. általános megközelítéssel kapott helyes eredmény:

Top5SalaryV7 Eredmény

Érdemes átgondolni és összehasonlítani a többféle különböző megközelítés lehetőségeit, korlátait. Ha egyensúlyozni kell a kliensprogram és az adatbázis-szerver terhelése között, valamint az MVC modell összetettsége, karbantarthatósága, könnyen dokumentálhatósága a/is szempont, akkor többféle alternatív módszer is bevethető, valamint építhetünk a különböző Oracle verziók (dialektusok) képességeire is.

Az SQL forráskódok formázásához a Free Online SQL Formatter-t használtam.

Dátumok csoportosítása

dátumintervallumok logó

dátumintervallumok logóEbben a Java projektben dátumok csoportosítását oldjuk meg, többféleképpen is. Mikor van erre szükség? Jelentés, kimutatás, riport, lista készítése során.

Példaként tekintsünk egy blogot. A blogban rendszeresen jelenik meg új tartalom (bejegyzés, poszt). Azért, hogy a blog hosszabb távon, sok bejegyzéssel is könnyen kereshető, átlátható, böngészhető legyen/maradjon a felhasználók, látogatók számára, célszerű:

  • taxonómia kialakítása. Ez kategóriákat és címkéket jelent. Ebből címkefelhő vagy szófelhő is készíthető, ahogyan erről blogoltunk már: Címkefelhő generálása.
  • marketing analitika használata. Ezek általában toplisták valamilyen könnyen hozzáférhető adat alapján. Például: látogatottság, népszerűség, eltöltött idő, hozzászólások száma, megosztások száma, egérmutató mozgása alapján hőtérkép. Ezek általában toplisták, amelyek eleje listázódik csökkenő sorrendben.
  • dátum szerint is csoportosítani a blog bejegyzéseit. Érdemes megjeleníteni a legújabbtól a régebbi felé haladó (retrospektív) listát, hierarchikus fa struktúrát, lenyíló panelt. Mindez kombinálható toplistával. A csoportosítás elvégezhető igény szerint tetszőlegesen, például évente, negyedévente, havonta.

Lássuk, hogyan lehet megvalósítani a dátumok csoportosítását Java programozás nyelven!

Milyen adatokra van szükség?

Egy megadott zárt dátumtartományban véletlenszerűen előállítunk néhány dátumot. Nem számít, hogy különböznek-e. A dátumokat tároló listát érdemes csökkenő sorrendben tárolni. Minden dátum múltbeli, így ez a sorrend a jelenhez legközelebbitől halad a legtávolabbi felé. Például a Java program ezekkel a dátumokkal dolgozik (lapozható):

Milyen eredményeket kaphatunk?

Az évenkénti csoportosítás így jelenik meg:

A havonkénti csoportosítás így jelenik meg (lapozható):

Természetesen blog esetén gyűjtőoldalra mutató hivatkozást kell tenni a megjelenő elemekre. Azok az évek és hónapok nem jelennek meg, ahol nincs dátum (blog bejegyzés).

Hogyan kapjuk meg az eredményeket?

Természetesen Java nyelven programozva készítünk megoldást, sőt többféle megoldást. Ezek szépen összevethetők és mindenki kiválaszthatja azt, amit szívesen használna. A dátumobjektumok tárolása generikus listában történik, aminek típusa LocalDate. A dátumok formátuma: DateTimeFormatter.ofPattern("yyyy.MM.dd.").

1. megoldás

Ez a hagyományosnak tekinthető megoldás. Végigjárja a dátumobjektumokat tartalmazó dateList dátumlista adatszerkezetet. Két egymásba ágyazott ciklussal csoportváltást valósít meg. Feltételezi – nem ellenőrzi -, hogy az adatok sorrendje megegyezik az eredmény kiírásának megfelelő sorrenddel. Amíg két egymást követő dátum GROUP_BY_FORMAT formátuma azonos, addig ugyanabba a csoportba tartoznak. A csoportváltáskor az eredmény TYPE_FORMAT formátumú. Közben a beépített megszámolás programozási tétel is működik.

A groupByDate1() függvény képes az évente és havonta csoportosítás megvalósítására. Mindez a paraméterezésén múlik. Évente csoportosít, ha így hívja meg a vezérlés:

Évenkénti csoportosítás során például a 2024.02.26. és a 2024.01.30. (dátumként, nem szövegként értelmezve) azért tartozik egy csoportba, mert a dátumobjektumoktól elkért év "2024" szövegként mindkettő esetében megegyezik.

A groupByDate1() függvény havonta csoportosít, ha így hívja meg a vezérlés:

Havonkénti csoportosítás során például a  2023.06.14. és a 2023.06.08. (szintén dátumként értelmezve) azért tartozik egy csoportba, mert mindkettő illeszkedik a "202306" szövegmintára.

2. megoldás

Ez a Stream API-t és funkcionális programozást használó, újabb megoldás. Ciklus helyett beépített műveletek vannak. A groupByDate2() függvény a dátumok évenkénti csoportosítását képes megoldani:

A groupByDate3() függvény a dátumok havonkénti csoportosítására készült. A YearMonth osztály beépített ( java.time csomag). A DateCount saját POJO. Konstruktora 4 paramétert kap: YearMonth key, Long value, DateTimeFormatter format és String groupText, valamint van két hasznos metódusa. Az egyik az örökölt és felüldefiniált toString() a formázott kiíráshoz, a másik pedig a Comparable interfésztől implementált compareTo() a sorrend kialakításához szükséges összehasonlításhoz.

A funkcionális programozáshoz kötődő lambda műveletekről többször is blogoltunk már, így azokat most nem részletezem. Helyette ajánlom a szakmai blog lambda kifejezés címkéjét.

Továbbfejlesztés

Érdemes átgondolni az 1. és 2. megoldás markáns különbözőségeit, illetve egymást kiegészítő gondolatmenetét. Zárjuk két ötlettel a továbbfejlesztésre vonatkozóan:

  • A 2. megoldás két függvénye megoldható egyetlen függvénnyel, amely hasonlóan paraméterezhető, mint az 1. megoldás függvénye. Ezáltal univerzális(abb)nak tekinthető megoldás is készülhetne. Aki kellően motivált és végiggyakorolja a fentieket, biztosan meg tudja oldani. Várjuk hozzászólásban, vagy az ILIAS-ban a megoldást!
  • A csoportosítás egyben hierarchiát jelent, amiből fa szerkezet építhető. A fa vizuális komponensen is megjeleníthető, ahogyan blogoltunk is róla: Fát építünk.

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, a Java EE szoftverfejlesztő tanfolyam és a Java adatbázis-kezelő tanfolyam szakmai moduljának több alkalmához és az orientáló moduljának 1-4. óra: Programozási tételek alkalmához is kötődik. A Stream API-val és a lambda kifejezésekkel sokszor foglalkozunk.

Egy matematika érettségi feladat megoldása programozással 2024

érettségi logó

érettségi logóA 2024-es középszintű matematika érettségi feladatsorból az 12. feladata inspirált arra, hogy elkészítsem a grafikus ábrázolását Java nyelven. A korábbi Kígyókocka grafikus felületen esettanulmány kiváló alapot, „keretrendszert” adott a továbbfejlesztésre. Érdekes belegondolni, hogy mennyire más lehetne a problémamegoldás, ha programozhatnánk a matematika érettségi vizsgán. A teljes feladatsor letölthető az oktatas.hu-ról.

12. feladat

Egy piros, egy fekete és egy fehér szabályos dobókockával egyszerre dobunk. Határozza meg annak a valószínűségét, hogy a dobás eredménye három különböző szám lesz! Megoldását részletezze!

1. megoldás

A kedvező /összes eset száma ad választ a kérdésre. Az egymásba ágyazott ciklusok – i-j-k számhármasokként – előállítják az összes esetet. Ezek száma 216, rendre: 1-1-1, 1-1-2, …, 1-1-6, 1-2-1, …, 6-6-5, 6-6-6-ig. A összes eset között megtalálhatók a kedvező esetek. Ezek száma 120, rendre: 1-2-3, 1-2-4, 1-2-5, 1-2-6, 1-3-2, 1-3-4, 1-3-5, 1-3-6, 1-4-2, 1-4-3, 1-4-5, 1-4-6, 1-5-2, 1-5-3, 1-5-4, 1-5-6, 1-6-2, 1-6-3, 1-6-4, 1-6-5, 2-1-3, 2-1-4, 2-1-5, 2-1-6, 2-3-1, 2-3-4, 2-3-5, 2-3-6, 2-4-1, 2-4-3, 2-4-5, 2-4-6, 2-5-1, 2-5-3, 2-5-4, 2-5-6, 2-6-1, 2-6-3, 2-6-4, 2-6-5, 3-1-2, 3-1-4, 3-1-5, 3-1-6, 3-2-1, 3-2-4, 3-2-5, 3-2-6, 3-4-1, 3-4-2, 3-4-5, 3-4-6, 3-5-1, 3-5-2, 3-5-4, 3-5-6, 3-6-1, 3-6-2, 3-6-4, 3-6-5, 4-1-2, 4-1-3, 4-1-5, 4-1-6, 4-2-1, 4-2-3, 4-2-5, 4-2-6, 4-3-1, 4-3-2, 4-3-5, 4-3-6, 4-5-1, 4-5-2, 4-5-3, 4-5-6, 4-6-1, 4-6-2, 4-6-3, 4-6-5, 5-1-2, 5-1-3, 5-1-4, 5-1-6, 5-2-1, 5-2-3, 5-2-4, 5-2-6, 5-3-1, 5-3-2, 5-3-4, 5-3-6, 5-4-1, 5-4-2, 5-4-3, 5-4-6, 5-6-1, 5-6-2, 5-6-3, 5-6-4, 6-1-2, 6-1-3, 6-1-4, 6-1-5, 6-2-1, 6-2-3, 6-2-4, 6-2-5, 6-3-1, 6-3-2, 6-3-4, 6-3-5, 6-4-1, 6-4-2, 6-4-3, 6-4-5, 6-5-1, 6-5-2, 6-5-3, 6-5-4.

A megszámolás programozási tétel előállítja a szükséges változókat, amik hányadosa megadja a szükséges p valószínűséget és ezt a program ki is írja a konzolra: A keresett valószínűség: 0.5555555555555556. Az esetek/lehetőségek felsorolása egyben a megoldás részletezése. A megszámoláshoz használt sokféle feltétel természetesen átfogalmazható lenne. Az egyszerűsítés többféleképpen is elvégezhető, többek között a De Morgan-azonosságok alkalmazásával.

2. megoldás

A korábbi JavaFX alapon megvalósított program módosításával könnyen állítható a megoldás grafikus/vizuális reprezentációja. Íme egy képernyőkép az elkészült program felhasználói felületéről:

A 3 db dobókockával kapott számhármasok 3D-ben, térbeli pontként jelennek meg egy kockában. A nagy piros gömbök jelölik azt a 6 db esetet, amikor mindhárom kockadobás megegyezik. Ezek a kocka egyik testálójában találhatók. A közepes narancssárga gömbök jelölik azt a 90 db lehetőséget, amikor bármely (pontosan) két kockadobás megegyezik. Végül a kis szürke gömbök jelölik a megoldást. Ez a 120 db kimaradó eset, másképpen: amikor mindhárom kockadobás különbözik. Másféle lehetőség nincs és megvan a 216 esethez tartozó összes gömb.

A megoldás implementálása a korábbi programban szinte csak egy metódus frissítését, kiegészítését igényelte. Ez a korábbi tudatos, objektumorientált, MVC szerkezetnek köszönhető és egyben a forráskód újrafelhasználása is. A createCube() metódus az alábbiak valósítja meg a feladatot:

A belépési pont, a grafikus felület építése, a nyomógombok eseménykezelése, a geometriai transzformációk, és persze a 3D -> 2D leképezés a megjelenítés során megmaradt. A virtuális térben elhelyezett objektumok változtak (pozíció, nézőpont, anyagtulajdonság). További részletes magyarázat érhető el a Kígyókocka grafikus felületen esettanulmányban.

3. megoldás

Itt most csak ötletet szeretnék mutatni. A 2022-es 6. feladat 3-7. kombinatorikai megoldásai könnyen továbbfejleszthetők és sokféle hasznos apróság gyakorolható.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ajánljuk matematika érettségi feladat címkénket, mert a témában évről-évre blogolunk.

A feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 5-8. óra: Vezérlési szerkezetek, 9-12. óra: Metódusok, rekurzió, valamint 17-28. óra: Objektumorientált programozás alkalmaihoz kötődik.