9. Megoldások¶
A korábbi fejezetekben található néhány kérdésre és feladatra vonatkozóan itt megtalálhatod a válaszokat és a megoldásokat. Az itt található megoldások az azonosító kóddal megjelölt feladatokhoz tartoznak. Kérlek, először önállóan próbálkozz a megoldással és ezt a fejezetet csak ellenőrzésre használd!
9.1. A problémamegoldás és a számítógép¶
[S102]:
Fájl megnyitás és mentés
Képformátumok kezelése
Vágólap kezelés
Színkeverés
Rajzeszközök (ceruza, ecset, radír, kitöltés, stb.) használata
Alakzat beszúrás
Képtranszformációk (átméretezés, forgatás, tükrözés, stb.)
Beállítások
9.2. Az algoritmusokról általában¶
[S202]:
Nem félreérthetetlen: Mit jelent a „közelítőleg megegyezik”?
Nem véges: Ha
A>B, akkor a különbség folyton nőni fog. Ha az elején nem áll meg az algoritmus, akkor a később sem. Tegyük fel, a „közelítőleg megegyezik” kifejezés matematikai egyenlőséget jelent ésB>A. Ekkor haB-Apáros, akkor az algoritmus jól működik, különben viszont nem áll meg ismét.
9.3. A folyamatábra¶
[S301]:
Ha egy rombusz (feltétel) két oldaláról kiinduló ágak találkoznak és a csatlakozási pontból csak egy nyíl megy tovább, akkor a feltétel egy elágazáshoz tartozik. Amennyiben a rombuszból kiinduló egyik végrehajtási ág visszavezet közvetlenül a rombuszhoz (míg a másik ág nem), akkor a feltétel egy ciklus feltétele.
[S302]:
x
y
60
?
60
2
30
2
15
2
15
3
5
3
5
4
5
5
1
5
A kimenet:
2 2 3 5.
[S309]:
9.4. A pszeudokód¶
[S403]:
A kimeneten a
15lesz, mivel azoutpututasítás a bemenetként megadott két egész szám legnagyobb közös osztóját írja ki. Ezt az algoritmust Euklideszi algoritmusnak hívják.
[S404]:
Az algoritmus a bementként (tízes számrendszerben) megadott természetes számot kettes számrendszerbeli alakra hozza.
1 2 3 4 5 6 7 8 9 input N P = 1 R = 0 while N>0 do R = R+(N%2)*P N = (N-N%2)/2 P = P*10 enddo output R
[S405]:
Az algoritmus a bementként megadott természetes számot prím tényezőkre bontja. Ezek a prímszámok lesznek a kimeneten.
1 2 3 4 5 6 7 8 9 10 input x y = 2 while y<=x do if x%y==0 then output y x = x/y else y = y+1 endif enddo
[S408]:
1 2 3 4 5 6 input a, b, c if a*a+b*b==c*c OR b*b+c*c==a*a OR c*c+a*a==b*b then output "Derékszögű háromszög." else output "Nem derékszögű háromszög." endifEgy hosszabb alternatív megoldás így nézhet ki egymásba ágyazott elágazásokkal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 input a, b, c if a*a+b*b!=c*c then if b*b+c*c!=a*a then if c*c+a*a!=b*b then output "Nem derékszögű háromszög." else output "Derékszögű háromszög." endif else output "Derékszögű háromszög." endif else output "Derékszögű háromszög." endif
[S410]:
1 2 3 4 5 6 7 8 9 10input N S = 2 while S*S<=N AND N%S!=0 do S = S+1 enddo if N%S==0 then output ”Nem prím.” else output ”Ez egy prím.” endif
[S412]:
Az alábbi megoldásban nem tároljuk folyamatosan az összes elemet, mivel úgyis mindig csak a két legutóbbira kell emlékeznünk. Az újonnan kiszámolt értéket mindig csak a következő két lépésben kell ismernünk.
1 2 3 4 5 6 7 8 9 10 11 F1 = 0 F2 = 1 output F1, F2 N = 2 while N<20 do F3 = F1+F2 output F3 N = N+1 F1 = F2 F2 = F3 enddo
9.5. Tömbök¶
[S504]:
Mivel 11 lehetséges elemünk van ezért egy 11 elemű tömbben (
Times) megszámoljuk, melyik értékből mennyi van. Ennek a tömbnek legnagyobb értékű elemének indexe határozza meg a leggyakoribb elemet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 i = 0 while i<11 do Times[i] = 0 i = i+1 enddo i = 0 while i<N do Times[A[i]-10] = Times[A[i]-10]+1 i = i+1 enddo max = 0 i = 1 while i<11 do if Times[i]>Times[max] then max = i endif i = i+1 enddo output "A leggyakoribb elem a ", max+10 output "Ez ", Times[max], " alkalommal fordult elő."
[S509]:
A tömböt logikailag két változó méretű részre osztjuk. A tömb elejét egy rendezett résztömbnek képzeljük el, kezdetben egy, majd egyre több elemmel. A tömb hátralévő része marad az eredeti rendezetlen formában. Minden lépésben a rendezetlen szakasz első elemét szúrjuk be a rendezett rész megfelelő helyére a nagyobb értékek eggyel hátrébb csúsztatása közben. Ezzel egy elemmel bővül a rendezett szakasz. Ezt a lépést kell megfelelő számban ismételni.
1 2 3 4 5 6 7 8 9 10 11 actual = 1 while actual<N do i = actual-1 while A[i]>A[i+1] AND i>=0 do tmp = A[i+1] A[i+1] = A[i] A[i] = tmp i = i-1 enddo actual = actual+1 enddo
[S511]:
Mind a két eredeti tömbnek és az új tömbnek is az elejéről indulunk. Amelyik aktuális elem kisebb az eredeti tömbökben, azt átmásoljuk az új tömb aktuális pozíciójába és ezen az elemen átlépünk mind a két tömbben. Ezt addig folytatjuk, amíg valamelyik eredeti tömb végét el nem érjük, majd a másik tömb maradék elemeit is átmásoljuk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 iA = 0 iB = 0 iC = 0 while iA<N AND iB<M do if A[iA]<B[iB] then C[iC] = A[iA] iA = iA+1 else C[iC] = B[iB] iB = iB+1 endif iC = iC+1 enddo if iA==N then while iB<M do C[iC] = B[iB] iB = iB+1 iC = iC+1 enddo else while iA<N do C[iC] = A[iA] iA = iA+1 iC = iC+1 enddo endif
9.6. Alprogramok¶
[S602]:
Az algoritmus
1-től a bementként megadott számig (Max) minden természetes számot kétszer kiír a kimenetre.A függvényhívások száma függ a bemenet értékétől. Ha
Maxértéke0, akkor egyszer sem hívódik meg, ha a bemenet egy pozitív egész szám, akkorMax*2-1alkalommal hívódik meg. Összességében tehát azt mondhatjuk, hogy egész értékű bemenet eseténmaximum{0 ; Max*2-1}függvényhívás történik.A függvényt most mindig
0vagy1aktuális paraméter értékkel hívtuk meg és ekkor rendre1és0értékeket ad vissza. Tehát a függvényt most arra használtuk, hogy két állapot között ide-oda váltogasson.
[S604]:
Dupla ciklust alkalmazva sorokba és oszlopokba rendezett értékeket íratunk ki. Új sort az
output NEWLINEutasítással tudunk létrehozni. Egy soron belül egy adott érték kiírása után átváltunk a másik értékre. Ha az oszlopok elemszáma (N) páros, akkor ugyanazt az értéket kell kiírni egy sor végére, mint a következő elejére. Páratlan oszlopszám páratlan, akkor soremelésnél is váltani kell a kiírandó értéket.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 procedure chessboard( N ) V = 0 i = 1 while i<=N do j = 0 while j<=N do output V V = 1-V j = j+1 enddo if N%2==0 then V = 1-V endif output NEWLINE i = i+1 enddo end procedure output "Add meg a méretet! " input S call chessboard( M )
[S608]:
A hatványozás megadható megfelelő számú szorzás alkalmazásával nullánál nagyobb, egész kitevő esetén. Ezt egy ciklussal megoldhatjuk. A negatív kitevő esetén a pozitív kitevőjű hatvány reciprokát kell megadnunk. Az alábbi megoldásban a függvényt négyszer is meghívjuk különböző paraméterekkel. A kimenetek:
32 0.001 1 0.04
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function power( B, E ) P = 1 if E<0 then E = -1*E N = 1 endif while E>0 do P = P*B E = E-1 enddo if N==1 then P = 1/P endif return P end function output power( 2, 5 ) output power( 0.1, 3 ) output power( 321, 0 ) output power( 5, -2 )
[S611]:
Egy teljes keresést valósítunk meg a függvényben őrszem használatával. Feltételezzük, hogy az
Anevű,Nelemű több már fel van töltve értékekkel. A visszatérési értéket nem íratjuk ki, de a példa kedvéért felhasználjuk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function keres( B, M, Y ) B[N] = Y i = 0 while B[i]!=Y do i = i+1 enddo if i==M then return -1 else return i endif end function output "Mit keresel?" input X i = keres( A, N, X ) if i==-1 then output "Nincs szerencséd." else if i<N/2 then output "Az elem a tömb első felében van." else output "Az elem a tömb második felében van." endif endif
[S614]:
Vegyük észre, hogy az eljárás meghívódhat a saját törzsén belül is, azaz rekurzióról beszélhetünk. A végrehajtás a 11. sorral kezdődik, ahol tehát
Nértéke900lesz. A 12. sorban először hívódik meg az eljárás, ha majd ez befejeződik, akkor a 13. sorral fogjuk folytatni. Az első hívás során a900és a2, mint aktuális paraméter értékek átmásolódnak azxésyformális paraméterekbe. (Az eljárás első példányában tehátx=900ésy=2.) Az első és a második elágazás feltétele is teljesül, tehát végrehajtjuk a 4. sort, azaz meghívjuk afooeljárást ismét, csak most a450és2aktuális paraméterekkel. Ez a két érték a második hívásxésyváltozójába kerül. (Ha majd kész leszünk ezzel a második hívással, akkor majd az 5. sorral folytatjuk.) A feltételek teljesülése miatt újra a 4. sorban vagyunk, azaz harmadjára is meghívjuk a eljárást (foo( 225, 2 )). Ebben a példányban a második elágazás feltétele hamisnak bizonyul, így azelseágra ugrunk, ahol megtörténik a negyedik hívás is (aktuális paraméterek:225és3). Ha majd egyszer visszatérünk ide, akkor utána a 8. sor fog következni. Ha folytatjuk ezt a gondolatmenetet, néhány további hívás után, az egyik eljárás példány 2. sorában az elágazás feltétele hamis lesz és mivel nincselseág így az eljárás be is fejeződik. Visszatérünk az előző példány 5. sorába, kiírva a kilencedik eljárás példányyváltozójának értékét vagyis, az5-öt. Ezután vége az elágazásoknak és így ennek a példánynak is. Visszatérünk a 8. példány 5. sorába. Itt egy újabb5-ös kiírása után ismét befejeződnek az elágazások és a 8. példányból visszatérünk a 7. példány 7. sorába. Előbb-utóbb a legelső eljárás is véget ér, visszatérünk a főprogram 13. sorába.A helyzet könnyebb átlátása érdekében tekintsük át az alábbi táblázatot, amely az egyes eljáráshívások adatait tartalmazza.
hívás
hívó
első paraméter
második paraméter
hívás helye
főprogram
900
2
sor
az 1. eljárás példány
450
2
sor
a 2. eljárás példány
225
2
sor
a 3. eljárás példány
225
3
sor
a 4. eljárás példány
75
3
sor
az 5. eljárás példány
25
3
sor
a 6. eljárás példány
25
4
sor
a 7. eljárás példány
25
5
sor
a 8. eljárás példány
5
5
sor
a 9. eljárás példány
1
5
sor
Tíz alkalommal történt tehát az eljárás meghívás a rekurziónak köszönhetően. Egyszer a 12. sorban, hatszor a 4. sorban és háromszor a 7. sorban. A végrehajtás során az alábbi kimenet keletkezik.
5 5 3 3 2 2Mint látható ez az eredeti paraméter prím tényezős felbontása, mivel
900 = 5*5*3*3*2*2.
9.7. Tesztelés¶
[S702]:
Az algoritmus
Nértéke kizárólag természetes szám lehet, aBváltozó pedig a{ 2, 3, 4, 5, 6, 7, 8, 9, 10 }halmaz elemeit veheti fel, más bemenetek esetén elvileg sem ad helyes kimenetet. Egy lehetséges tesztkészletet tartalmaz a következő táblázat.
N
B
Elvárt kimenet
0
2
0
1
2
0
11
2
1011
12
2
1100
32
2
10000
31
2
11111
1000000000
2
111011100110101100101000000000
11
3
102
12
3
110
7
4
13
8
4
20
24
5
44
25
5
100
15
6
23
342
7
666
0
8
0
7
8
7
8
8
10
9
8
11
1000000000
8
7346545000
39
9
43
0
10
0
5
10
5
25
10
25
125
10
125
9.8. Implementáció¶
[S802]:
Szintaktikai hibák:
A
whileszó helyettwihleszerepel.A ciklus feltétele után nincs
dokulcsszó.Az értékadás bal oldalán mindig csak egy változó szerepelhet.
E = E-1a helyes.Az
endoegy azonosító lehet (nem kulcsszó). A ciklustenddokulcszóval kell zárni. (Most nincs ciklusvég.)Szemantikai hibák:
Az
Ekezdőértéke ismeretlen. Bemenetként kellene megadni. Hiányzik a pszeudokód elejéről egyinput Eutasítás.Az
Rkezdőértékének nem jó választás a nulla, mivel azR = R*Butasításnak így nincs hatása. Mivel ebben az utasításban szorzás szerepel, a valós számok multiplikatív egységelemére van szükségünk az additív helyett. HelyesenR = 1.Ha a ciklus magja akkor is lefut, amikor az
Eértéke nulla, akkor eggyel nagyobb kitevőjű hatvány lesz az eredmény. A feladat leírása szerint az algoritmusnak negatív kitevőt (E<0) nem kell kezelnie. A feltételnekE>0logikai kifejezésnek kell lennie.
[S803]:
Az első kifejezés értéke
109, a másodiké-123. A kiértékelés menete a következő:+ 103 - / * 6 35 14 7 + 103 - / 210 14 7 + 103 - 13 7 + 103 6 109- - - 900 1000 3 20 - - -100 3 20 - -103 20 -123
[S806]:
A megoldás előbb teljesen zárójelezett formában, majd pedig a felesleges zárójelek elhagyása után így néz ki:
( 1 + ( ( ( 3 * 4 ) / ( 1 + 2 ) ) * ( 103 - 97 ) ) ) 1 + 3 * 4 / ( 1 - 2 ) * ( 103 - 97 )
[S809]:
A szemantikai hibák nem formalizálhatóak. A szemantikai hibát tartalmazó program is végez tevékenységeket, csak az eredmény nem az, amit a programozó szeretett volna. Ha a számítógép minden esetben felismerné, hogy mit akart a programozó, akkor nem lenne szükség programozóra. Az IDE-k nem ismerik fel a szemantikai hibákat.
[S816]:
[S819]:
A két bájt az 16 bitet jelent. Összesen
65536különböző kettes számrendszerbeli természetes szám van, amely nem hosszabb 16 helyiértéknél. Vagyis2^16darab eltérő értéket tudunk tárolni0-tól65535-ig. A Föld lakosainak száma jelenleg közel 8 milliárd, ami jelentősen magasabb érték, mint az előbb említett maximum, így nem tudjuk ezt a számot 2 bájton eltárolni. (Megjegyzés: még 4 bájton sem lehetséges.)
[S821]:
A
-1negatív szám, előjeles fixpontos számábrázolással tárolhatjuk, amihez a kettes komplemens képzés technikáját kell alkalmaznunk. Vegyük a szám abszolút értékét és írjuk fel kettes számrendszerben 32 biten! Ezt kapjuk:00000000000000000000000000000001. Ennek az egyes komplemense az11111111111111111111111111111110. Ha ehhez hozzáadunk egyet, megkapjuk a kettes komplemenst, tehát az eredmény:11111111111111111111111111111111, azaz 32 darab1-es bit. Mint látható a legelső (előjel) bit1-es, vagyis a szám tényleg negatív.
[S822]:
Az adott szám pozitív tehát a legelső bit biztosan
0lesz. Ha átváltjuk a3,5értéket kettes számrendszerbe, akkor11,1bináris értéket kapunk. Hozzuk normál alakra, azaz toljuk el a kettedes vesszőt az első1bit elé! Az eredmény1,11, amelyet tehát a kettedes vessző1helyiértékkel való balra tolásával kaptunk. Ehhez az1-hez adjunk hozzá127-et! Az eredmény 8 biten a10000000lesz, vagyis ez a következő 8 bitje a reprezentációnak. Ezt követi a mantissza (jelenleg1,11) kettedes vessző utáni része0bitekkel kiegészítve. Az eredmény tehát logikai illetve bájtonkénti tagolásban a következő:0 10000000 11000000000000000000000 01000000 01100000 00000000 00000000Ez a 32 bit jelenti a
+3,5értéket egyszeres pontosságú lebegőpontos számábrázolás esetén.
[S823]:
Típusos nyelvekben egy változó nem vehet fel tetszőleges értéket. A típus egyértelműen meghatározza a lehetséges értékek halmazát. Természetesen egy előjel nélküli egész típusú változó értéke nem lehet
-123, egy egész típusú változó nem tárolhatja a3,14értéket és egy valós típusú változó értéke nem lehet az „Euler-szám” karaktersorozat. Ezen túlmenően logikailag megfelelő típusú értékek sem biztos, hogy tárolhatóak a technikai korlátok miatt. A legtöbb nyelv egész típusú változója képtelen eltárolni a például a tízmilliárdot (mert túl nagy) vagy a valós típusú változóik a0,1értéket csak pontatlanul tudják eltárolni (mivel ez binárisan egy végtelen kettedes tört).

