Barátságos számok

Barátságos számok

Barátságos számokAzokat a számpárokat, amelyekre igaz, hogy az egyik szám önmagánál kisebb osztóinak összege megegyezik a másik számmal és fordítva, külön-külön barátságos számoknak, együtt barátságos számpárnak hívjuk.

Másképpen: legyen d(n) az n természetes szám önmagánál kisebb osztóinak összege. Ha d(a)=b és d(b)=a, ahol ab, akkor a és b barátságos számpár.

Például: (220; 284), hiszen a 220 önmagánál kisebb osztói: 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 és ezek összege 284, illetve 284 önmagánál kisebb osztói: 1, 2, 4, 71, 142 és ezek összege 220.

Írjunk Java programot, amely kiírja az 1-10000 zárt intervallumban található barátságos számpárokat!

1. megoldás

A baratsagosSzamparok1() eljárás ciklusai a brute force módszer szerint behelyesítik az összes lehetséges számot. Minimális lépésszám csökkentésre adódik lehetőség, hiszen a belső ciklus j változója i+1-ről indítható (így a megtalált számpárok nem íródnak ki fordítva is, mert teljesül, hogy i<j).

Az osztokOsszege1(n) függvény is minden lehetséges osztót figyelembe vesz 1-től n-1-ig.

2. megoldás

Kisebb módosításokkal a lépésszám csökkenthető. A baratsagosSzamparok2() eljárás külső ciklusánál figyelembe vettem, hogy a legkisebb barátságos számpár kisebb tagja nagyobb 200-nál. Mivel a barátságos számpárok tagjainak paritása mindig megegyezik (azaz mindkettő páros vagy mindkettő páratlan), így a belső ciklus j változója indítható i+2-ről és léptethető kettesével ( j+=2), és továbbra is teljesül, hogy i<j.

Az osztokOsszege2(n) függvényt is módosítottam. Mivel az 1 minden számnak osztója, illetve a 2 minden páros számnak osztója, így s lehet 3 vagy 1 és a ciklus indítható 3-ról. A páros számok esetén a számnál kisebb legnagyobb osztó maximum n/2 lehet, illetve ugyanez páratlan számok esetén n/3 lehet. Ezekre figyelve a max változó adja a ciklus léptetésének felső határát. Az i változó léptetésénél figyelembe vettem, hogy páratlan számnak csak páratlan osztói lehetnek ( i=3-mal szinkronban).

3. megoldás

Az eddigi két egymásba ágyazott ciklus helyett átszervezhető a baratsagosSzamparok3() eljárás. A j>i && osztokOsszege2(j)==i feltétel kiértékelése így sokkal hatékonyabb.

Vajon milyen nagyságrendű különbségek adódnak, ha összehasonlítjuk a három megoldás futási idejét?

Az 1. megoldás futási ideje 1104156 ms, a 2. megoldásé 257055 ms, a 3. megoldásé 121 ms. A konkrét értékek helyett a nagyságrendet megfigyelve a különbség nagyon látványos.

Mindhárom megoldás helyes és megkapjuk az intervallumban található öt barátságos számpárt: (220; 284), (1184; 1210), (2620; 2924), (5020; 5564), (6232; 6368).

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

Források:

A feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 9-12. óra: Metódusok, rekurzió alkalomhoz kötődik.

Denevérek a barlangban

Évekkel ezelőtt hálózatos Java EE esettanulmányt akartunk készíteni Lengyel Borisz kollégával. Ötleteltünk: milyen technológiával és hogyan kommunikáljon egymással a szerver és a kliens(ek). A távoli metódushívás (Remote Method Invocation) mellett döntöttünk és elkészült a denevérek a barlangban projekt, amely evolúciós projektként azóta több változatot is megélt. A felhasználói felület (barlang) betölt néhány képet (denevér kliensek), amelyek a szerver segítségével mozognak.

Ismertetjük a tervezés folyamatát, a kliens és szerver funkcióit részletesen, végül ötleteket adunk a továbbfejlesztésre.

A főbb feladatokat így határoztuk meg:

  • az RMI kommunikációs módszer megismertetése,
  • az RMI szolgáltatás reprezentálása látványos grafikus/swinges klienssel,
  • alternatíva nyújtása a TCP protokoll közvetlenül csatlakozó socket-jére.

Elkészítettük az alábbi osztálydiagramot (persze ez nem az első változat):

Denevérek a barlangban - Osztálydiagram

A szerver és kliens funkcióit megvalósító osztályok/interfészek feladatait így határoztuk meg:

BarlangDenevérInterfész interfész:

  • véletlen 5 és 10 közötti a denevérek száma,
  • méretek a GUI-hoz.

Denevér osztály:

  • megvalósítja az RMI kliens funkciót,
  • JLabel leszármazott, külső képfájlt tölt be ( bat.jpg),
  • egyedi azonosítója van,
  • eldönti mozgásának irányát (4) és léptékét (3), mintha ultrahangot adna,
  • a szerver megadja neki, hogy az új helyre elmozdulhat-e,
  • saját magát képes mozgatni.

Pozíció interfész:

  • öröklődik a java.rmi.Remote interfészből,
  • két távolról hívható metódus fejét tartalmazza.

BarlangSzerver osztály:

  • megvalósítja az RMI szerver funkciót,
  • implementálja a Pozíció interfészt,
  • JFrame leszármazott,
  • figyel arra, hogy a denevérek ne mozogjanak ki a barlangból.

BarlangFelület osztály:

  • JFrame leszármazott,
  • GUI az RMI kliensek megjelenítéséhez.

BarlangSzerverTérkép osztály:

  • JPanel leszármazott,
  • GUI a szerveren a kliensek mozgásának követésére.

Ha futtatjuk az elkészült szerver és kliens programot, akkor ezt láthatjuk:

Denevérek a barlangban - animáció

A fejlesztés és tesztelés közben sok-sok továbbfejlesztési ötletet/javaslatot fogalmaztunk meg:

  • háttérkép a barlangról,
  • a háttérkép megvalósíthat labirintust, koordináta-rendszert,
  • átlátszó illetve egyedi képfájlok a denevéreknek,
  • a denevérek mozgásának tetszőleges iránya (360°),
  • a denevérek mozgásának egyedi léptéke,
  • a denevérek figyeljenek egymásra (ne ütközzenek össze),
  • a denevérek figyeljenek a környezetükre (ne ütközzenek bele sziklákba, cseppkövekbe),
  • a szerver követheti a denevérek útvonalát,
  • a szerver archiválhat, szerializálhat, készíthet statisztikát.

A bejegyzéshez tartozó – több lépésben továbbfejlesztett – forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java EE szoftverfejlesztő tanfolyam 21-24. óra: RMI alapú kommunikáció alkalmához kapcsolódik.