Tökéletes szám tesztelő (Újratervezés Program, kompetenciateszt gyakorlás)
Tegnap feladtam egy feladatot a (Újratervezés Program Tanuló Szoba) Facebook-csoportban:
Adott egy szám (pl. textfield-ben), mondjuk meg róla, hogy tökéletes szám-e. (pl. írjuk ki a konzolra, hogy az-e vagy sem).
Tökéletes szám egy nemnegatív egész szám, ha a önmagánál kisebb osztóinak összege önmaga. (Pl. 6 = 1 + 2 + 3).
(Kevés ilyen szám van, ezért az egyik megoldás az lehetne, hogy ha szám == az első_tökéletes_szám_a_wikipédián VAGY szám == a második_tökéletes_szám_a_wikipédián… akkor igen… keress rá más megoldást!)
Mi a megoldás?
Induljunk ki a tökéletes szám definíciójából, és vizsgáljuk meg ezt a tulajdonságot. Ahhoz, hogy el tudjuk dönteni, hogy egyenlő-e a számmal a magánál kisebb osztók összege, előbb meg kell határozni a magánál kisebb osztók összegét. Az összeghez pedig az osztókat.
Egy szám magánál kisebb osztóinak meghatározása
Végigmegyünk az osztók számára lehetséges tartományon egy for-ciklussal, és megnézzük, hogy a a ciklusváltozó osztja-e az eredeti számot.
Mi számít lehetséges tartománynak? Ha nagyon egyszerűen akarod elintézni, akkor [1..n-1], de ezt még lehet szűkíteni, hiszen a szám felénél nagyobb (számnál kisebb) osztó nincs, tehát lehet ez a felső határ: [1…n/2]. (Ha még ügyesebb vagy, akkor megoldod úgy, hogy a szám négyzetgyökéig vizsgálódjunk, mégis benne legyen az összes lehetséges osztó, de maradjunk egyelőre a feléig történő vizsgálatnál).
let szam = ...; for(let oszto = 1; oszto <= szam / 2; oszto++) { if (szam % oszto == 0) { console.log(oszto); } }
Ez eddig az alapalgoritmusok közül a kiválogatás algoritmusa. Kiválogatjuk azokat az értékeket, amelyek osztják a számot.
De ezzel még nem végeztünk.
Egy szám magánál kisebb osztói összegének meghatározása
Adjuk őket össze!
Alkalmazzuk az összegzés algoritmusát. Mit összegzünk? Azokat az "oszto" értékeket, amelyekre igaz az, hogy osztják a számot.
let szam = ...; let osszeg = 0; for(let oszto = 1; oszto <= szam / 2; oszto++) { if (szam % oszto == 0) { osszeg = osszeg + oszto; //console.log(oszto); } } console.log(osszeg);
Az új részeknek köszönhetően most már megvan az összege a magánál kisebb osztóknak.
Feltétel vizsgálata
Hasonlítsuk össze a megkapott összeget az eredeti számmal:
let szam = ...; let osszeg = 0; for(let oszto = 1; oszto <= szam / 2; oszto++) { if (szam % oszto == 0) { osszeg = osszeg + oszto; //console.log(oszto); } } if (osszeg == szam) { console.log("A " + szam + " tökéletes."); } else { console.log("A " + szam + " nem tökéletes."); }
(Ha tovább akarsz menni, akkor persze lehetséges háromoperandusú operátorral (?: ) is kezelni ezt a kiírást).
Tömbbel?
Lehet, hogy eszedbe jutott az, hogy tömbbel oldd meg a feladatot: a kiválogatást egy tömbbe végzed, majd annak a tömbnek az elemeit összegzed. Véleményem szerint takarítsuk meg a memóriát, és inkább "röptében" összegezzük a számokat, azaz akkor, amikor előálltak. A tömbös megoldást nem javaslom.
Más megoldás?
Persze, simán elképzelhető más, matematikai alapú megoldás is, amivel a kompetenciádat még jobban bizonyítod, de azt gondolom, ha ezt most érted, esetleg te is így csináltad, az már egy jó pont.
Felépítés
Amit érdemes a konkrét megoldáson túl ebből a gondolkodásmódból elsajátítani, az a program lebontásának (analízis) és részekből való összeépítésének képessége.
Továbblépés
Ha szeretnél hasonló feladatokat megoldani, automatikus feladatértékelővel, és esetleg mentori segítséget is kapni hozzá, akkor
- töltsd ki a tesztünket és kaphatsz az első 5 fejezethez két hét ingyen hozzáférést, vagy
- ha ezen már túl vagy, fizess elő augusztus 31-ig 20% kedvezménnyel a folytatásért (az első 11-13. fejezet ismerete várhatóan elegendő lesz a kompetenciateszten is).
Sikeres felkészülést kívánok!
Pasztuhov Dániel