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

Sikeres felkészülést kívánok!
Pasztuhov Dániel

Kompetenciateszt!

Töltsd ki tesztünket!
Ha sikerül legalább 55%-ra, akkor ajándékot is kapsz!