univerza v ljubljanipefprints.pef.uni-lj.si/6083/1/melita.pdf · 2019. 11. 8. · večina...
TRANSCRIPT
UNIVERZA V LJUBLJANI
PEDAGOŠKA FAKULTETA
Poučevanje, predmetno poučevanje
Melita Kompolšek
VZPODBUJANJE URJENJA PROGRAMIRANJA S POMOČJO
PROBLEMSKEGA UČENJA
Magistrsko delo
Ljubljana, 2019
UNIVERZA V LJUBLJANI
PEDAGOŠKA FAKULTETA
Poučevanje, predmetno poučevanje
Melita Kompolšek
VZPODBUJANJE URJENJA PROGRAMIRANJA S POMOČJO
PROBLEMSKEGA UČENJA
Magistrsko delo
Mentor: prof. dr. Janez Demšar
Ljubljana, 2019
ii
POVZETEK
V magistrskem delu bo predstavljena študija o motiviranju učencev za učenje programiranja.
Vztrajnost je pri učenju ključni dejavnik, zato morajo biti motivacijske strategije za učence del
vsakršnega pedagoškega pristopa. To je še posebej pomembno pri tistih, ki se šele začnejo učiti
programiranja, saj je takšen koncept učenja za večino učencev nov in težek. Da bi bili učenci
uspešni, morajo vaditi veliko in kontinuirano. Pri tem pa je zelo pomembno, da so motivirani,
saj sta za premagovanje težav, na katere bodo naleteli, pomembna trud in predanost. V študiji
bo analiziran vpliv problemskih in motivacijskih nalog na motivacijo učencev za reševanje
nalog. V ta namen bo izdelana spletna stran s 25 nalogami, ki bodo med seboj povezane v
zgodbo. Učenec bo prejel naključne podatke, za katere bo moral sestaviti program, ki bo
skladno z navodili naloge generiral rešitev. Rešitev bo vnesel na spletno stran, ki ga bo v
primeru pravilne rešitve preusmerila na naslednjo nalogo. Ker se bo moral uporabnik za
reševanje nalog prijaviti v sistem, bo mogoče preko spletne strani beležiti podatke posameznega
učenca o njegovem reševanju nalog. Poleg tega bo v tem delu raziskano tudi, s katerimi
težavami se spopadajo učitelji pri sestavljanju takih vrst nalog.
KLJUČNE BESEDE
Programiranje, učenje programiranja, problemsko učenje, poigritev, učenje s primeri, spletna
stran za učenje
iii
ABSTRACT
This master's degree thesis presents a study on the motivation of students to learn programming.
Persistence is a key factor in learning, therefore motivational strategies must be present in every
pedagogical approach. This is especially important for beginners in programming, since such a
concept of learning is new and difficult for most students. In order to be successful, students
need to practice a lot and continuously. In doing so, it is very important that they are motivated
since effort and commitment are important to overcome the difficulties that they will encounter.
The study analyses the impact of problem-based and motivational tasks on student motivation
to solve them. For this purpose, a web page with 25 tasks linked together in a story was created.
The student receives input random data for which he has to compile a program that will generate
a solution according to instructions. The solution is then entered in a web page and if it is
correct, the user is redirected to the next task. As the user has to log into the system to solve
tasks, this allows us to collect information on his task solving. In addition, this study also
investigates the difficulties teachers came across while preparing these types of tasks.
KEYWORDS
Programming, learning programming, problem learning, gamification, learning with examples,
e-learning
iv
KAZALO VSEBINE
1. UVOD ................................................................................................................................. 1
2. TEORETIČNA IZHODIŠČA ............................................................................................ 3
2.1 UČENJE IN POUČEVANJE PROGRAMIRANJA .................................................... 3
2.2 RAČUNALNIŠKO MIŠLJENJE ................................................................................ 5
2.3 PROBLEMSKO UČENJE ........................................................................................... 6
2.4 PROJEKTO UČENJE .................................................................................................. 7
2.5 PRIMERJAVA PROBLEMSKEGA IN PROJEKTNEGA UČENJA ........................ 8
2.6 POIGRITEV ................................................................................................................ 9
2.7 UČENJE S PRIMERI ................................................................................................ 10
3. SPLETNA STRAN HEKERSKI NAPAD ......................................................................... 11
3.1 SPLETNA STRAN .................................................................................................... 11
3.2 NAMEN IN UPORABA SPLETNE STRANI .......................................................... 12
3.3 NALOGE ................................................................................................................... 16
3.3.1 Varnostno geslo .................................................................................................. 18
3.3.2 Iskanje ključa šifriranih podatkov ...................................................................... 19
3.3.3 GPS ..................................................................................................................... 20
3.3.4 Poišči geslo ......................................................................................................... 22
3.3.5 Dešifriraj geslo ................................................................................................... 23
3.3.6 Pretvarjanje v binarni zapis ................................................................................ 25
3.3.7 Analiza besedil glede na iskano besedo ............................................................. 27
3.3.8 Analiza besedil glede na dolžino besed .............................................................. 29
3.3.9 Napad na ključe za podpisovanje certifikatov .................................................... 31
3.3.10 Napad na pomnilnik ........................................................................................... 32
3.3.11 Pošiljanje sporočila guvernerju .......................................................................... 34
3.3.12 Lokacije državnih skrivališč ............................................................................... 37
3.3.13 Kodiranje po metodi RLE................................................................................... 39
v
3.3.14 Napad na telefonske številke .............................................................................. 40
3.3.15 Izbris besed v zaupnih dokumentih .................................................................... 42
3.3.16 Dodane besede v zaupnih dokumentih ............................................................... 44
3.3.17 Leksikografsko urejanje besed ........................................................................... 45
3.3.18 Izbrisane črke ...................................................................................................... 47
3.3.19 Napad na števila.................................................................................................. 48
3.3.20 Napad na identifikacijske številke dokazov ....................................................... 51
3.3.21 Branje zakodiranega sporočila............................................................................ 52
3.3.22 Določitev novih identifikacijskih števil .............................................................. 54
3.3.23 Napad na računske operacije .............................................................................. 55
3.3.24 Mapa Fibonacci .................................................................................................. 57
3.3.25 Koordinate napadalcev ....................................................................................... 58
4. OPREDELITEV RAZISKOVALNEGA PROBLEMA, NAMENA IN CILJEV
RAZISKOVANJA .................................................................................................................... 62
4.1 RAZSKOVALNA VPRAŠANJA ............................................................................. 63
4.2 METODA IN RAZSIKOVALNI PRISTOP ............................................................. 63
4.3 VZOREC ................................................................................................................... 64
4.4 OKOLIŠČINE IZVEDBE RAZISKAVE .................................................................. 64
4.5 OPIS POSTOPKA ZBIRANJA PODATKOV .......................................................... 64
5. REZULTATI IN INTERPRETACIJA ............................................................................. 65
5.1 INTERVJU ................................................................................................................ 65
5.2 KAKO BODO MED SEBOJ POVEZANE PROBLEMSKE NALOGE VPLIVALE
NA VZTRAJNOST PRI REŠEVANJU? ............................................................................. 70
5.3 S KATERIMI IZZIVI SE SPODADA UČITELJ OB SESTAVLJANJU TAKŠNIH
NALOG? .............................................................................................................................. 71
5.4 ALI BODO UČENCI NALOGE REŠEVALI NA NAČIN, KI SI GA JE OB
SESTAVLJANJU NALOGE ZAMISLIL UČITELJ? ......................................................... 72
5.5 KATERI KONCEPTI V PROGRAMIRANJU SO ZA UČENCE NAJTEŽJI? ....... 77
vi
6. ZAKLJUČEK ................................................................................................................... 81
7. VIRI IN LITERATURA ................................................................................................... 83
KAZALO SLIK
Slika 1: Ključne tehnike računalniškega mišljenja ..................................................................... 5
Slika 2: Registracija .................................................................................................................. 13
Slika 3: Baza uporabnikov ........................................................................................................ 13
Slika 4: Baza ene naloge ........................................................................................................... 13
Slika 5: Začetna stran z uvodno zgodbo ................................................................................... 14
Slika 6: Primer naloge .............................................................................................................. 15
Slika 7: Obvestilo o napačni rešitvi .......................................................................................... 15
Slika 8: Končna stran ................................................................................................................ 16
1
1. UVOD
Računalnike uporabljamo za pomoč pri reševanju problemov. Toda preden lahko problem
rešimo, ga moramo razumeti in najti načine, na katere ga lahko rešimo. To nam omogoča
računalniško mišljenje. Programiranje je torej več kot le kodiranje, saj od programerja zahteva
računalniško mišljenje, ki vključuje reševanje problemov z uporabo računalniških konceptov,
kot so abstrakcija in delitev problemov na manjše probleme. Poleg tega je programiranje
veščina, ki jo pridobimo z veliko vaje. Da bi učenci razvili spretnosti programiranja, potrebujejo
predvsem veliko utrjevanja. To je eden od razlogov, zakaj njihovo zanimanje za učenje
programiranja lahko upade. Drugi razlog za to, da učenci opustijo programiranje, so lahko
ponavljajoče se napake v njihovih programih ter težave pri odkrivanju in odpravljanju le-teh
(Lam, Chan, Lee in Yu, 2008). Tudi to lahko učenci v veliki meri odpravijo le z utrjevanjem.
Pri načrtovanju poučevanja programiranja je torej zelo pomembno upoštevati dejavnike, ki
spodbujajo učno motivacijo učencev.
Eden od pristopov za spodbujanje učenja in utrjevanja programiranja je problemsko učenje. Gre
za celostni pristop, s katerim dosegamo učinkovito in smiselno učenje, v sklopu katerega
morajo učenci problem razumeti, razviti načrt za reševanje in ga preizkusiti. Problemsko učenje
velja v računalništvu za ključno kompetenco, saj na tem področju bolj kot le tehnično usmerjene
aktivnosti potrebujemo dobre sposobnosti reševanja problemov. Sposobnost reševanja
problemov pa je glavni primanjkljaj začetnikov.
Spodbujanje razvoja sposobnosti učencev za problemsko reševanje je torej ena glavnih tematik
izobraževanja na področju računalništva. Pri tem pa lahko pomagajo naloge, ki simulirajo
zanimive, realne probleme iz vsakdanjega življenja ali pa so sestavljene v obliki igre. Uporaba
izobraževanih iger kot učnega orodja predstavlja obetaven pristop, saj z njimi učenci poleg
znanja krepijo tudi sposobnost reševanja problemov. Igre pa imajo veliko motivacijsko moč.
Uporabljajo namreč številne mehanizme za spodbujanje ljudi, da se, po navadi brez kakršne
koli nagrade, z njimi igrajo le zaradi samega igranja in možnosti za zmago. Pristop poigritve
(angl. gamification) predlaga uporabo igrivega učenja in elementov oblikovanja za namene
povečanja motivacije pri učencih in pomeni uporabo elementov igre v kontekstih, ki z njo niso
povezani.
Programerji si pri reševanju problemov pogosto pomagajo tudi z izkušnjami iz reševanja
preteklih problemov. Tradicionalni pristop uporabe primerov pri poučevanju je, da učitelj za
vsako učno uro pripravi skrbno izbrane primere problemov, ki zahtevajo pisanje krajših
2
programov. Učitelj med učno uro te probleme analizira in učencem za potrebe nadaljnjega
raziskovanja in uporabe problema lahko priskrbi tudi kodo. Težava pri tem pa je, da takšen
pristop deluje le pri majhnih homogenih skupinah učencev. V velikih nehomogenih skupinah
učencev pa sta raven predznanja in sposobnosti dojemanja učencev zelo različna, kar vpliva na
učinkovitost pristopa.
Učenci potrebujejo torej poleg dobre literature in razlage učitelja predvsem veliko praktičnega
učenja in nalog za utrjevanje. Pri tem pa je bistveno, da so naloge pripravljene tako, da učence
motivirajo za vztrajanje pri učenju programiranja tako v šoli kot tudi doma. Cilj magistrskega
dela je raziskati, kako učence motivirati za utrjevanje znanja , ali jih torej lahko pritegnemo s
serijo v zgodbo povezanih nalog in kakšne lastnosti morajo imeti takšne naloge, da na učence
delujejo motivacijsko. Raziskava bo temeljila na manjšem vzorcu dijakov ene srednje šole,
zaradi česar njenih rezultatov seveda ne moremo posplošiti na celotno populacijo. V delu so
predstavljene tudi težave, s katerimi se spopada učitelj ob sestavljanju takšnih vrst nalog. Po
navadi učitelj z vsako nalogo preverja neko določeno znanje oz. koncept, ni pa nujno, da učenci
nalogo rešijo na način, ki ga je predvidel učitelj. Zato je v magistrskem delu predstavljeno tudi,
na kakšen način so učenci naloge reševali oz. kakšne pristope in koncepte so uporabljali in
kateri koncepti v programiranju so za učence najtežji.
3
2. TEORETIČNA IZHODIŠČA
V tem poglavju bomo najprej pregledali nekaj značilnosti učenja in poučevanja programiranja,
nato pa se posvetili pristopom k poučevanju, ki so relevantni za to delo: problemskemu in
projektnemu učenju, poigritvi in učenju s primeri.
2.1 UČENJE IN POUČEVANJE PROGRAMIRANJA
Programiranje je veščina, ki se je ne naučimo, temveč jo pridobimo z veliko vaje. Da bi učenci
razvili dobre spretnosti programiranja in pridobili izkušnje pri odpravljanju napak, potrebujejo
predvsem veliko vaje (Lam, Chan, Lee in Yu, 2008). Vendar pa učenci zlahka izgubijo
navdušenje in zanimanje za učenje programiranja, še posebej, če pri samostojnem utrjevanju
doživljajo ponavljajoče se napake. Večina učencev se ob učenju programiranja, zlasti v prvem
letu, sooča s težavami, ob tem pa se počasi zmanjšuje tudi njihova motivacija za učenje (Azmi,
Iahad in Ahmad, 2015). Razočaranje se pri učencih pojavi, ko začutijo primanjkljaj spretnosti
za razvoj pravilnega računalniškega programa in nepoznavanje konceptov programiranja
(Xinogalos, 2014). Pri načrtovanju poučevanja programiranja je tako nujno potrebno pozornost
nameniti dejavnikom, ki vplivajo na učno motivacijo učencev (Jenkins, 2001). Proces učenja je
dinamičen, zato na pridobivanje in širjenje znanja vplivajo različni dejavniki (Lau in Yuen,
2009). Poleg individualnih razlik, učne motivacije in sposobnosti učencev lahko na tako učenje
vplivajo tudi dejavniki, kot so infrastruktura, socialni pritisk in učni pristopi (Law Sandnes, Jian
in Huang, 2009).
Pedagoška teorija je osredotočena predvsem na poučevanje učencev in dijakov (Jakoš in Veber,
2016), zato je pomembno nasloviti vrste mentalnih modelov, ki jih imajo učenci in dijaki ter
proučiti, kako se ti modeli spreminjajo (Winslow, 1996). Robins, Rountree in Rountree (2002)
so v svoji študiji proučevali poučevanje učencev v okviru uvodnega tečaja programiranja in
ugotovili, da je najbolj zanesljiv napovedovalec njihovega uspeha ocena. Drugi pomembni
dejavniki so še motivacija, zaupanje v svoje zmožnosti, pozitivni čustveni odzivi in iskanje
učenčevih skupnih ciljev (Sedighian & Sedighian, 1996). Eden od načinov za doseganje takšnih
ciljev je uporaba atraktivnih učnih orodij, ki morajo biti privlačno oblikovana in zgrajena z
upoštevanjem pedagoških spoznanj.
4
Tradicionalno vzgojno načelo podpira koncept prikritega učenja, pri katerem se učence
spodbuja k zabavi, ob kateri pa se hkrati tudi nezavedno učijo (Sharp, 2012). Učitelji poskušajo
takšen način učenja uvesti v šole, in sicer tako, da dosegajo učne cilje s pomočjo
netradicionalnih orodij. Ta način učenja, v primerjavi s formalnim pristopom poučevanja in
ocenjevanja, pri katerem učenci in učitelji ustvarjajo skupne učne cilje, skrbi, da posamezni
učenec razvije svoje učne cilje.
Večina današnjih otrok igra digitalne igre ali pa uporablja socialna omrežja. Pogosto tudi
sodelujejo v aktivnostih, ki nagrajujejo njihovo predanost in trud. Zato so začeli učitelji, da bi
zagotovili dobre učne rezultate, iskati učne cilje v učenju, z uporabo okolij, ki so učencem blizu
in v igralnih tehnologijah (Felicia, 2009). Cilj takšnega učenja je, da se učenci med igranjem
poglobijo v sam problem v takšni meri, da pozabijo na samo učenje in se programskih
konceptov naučijo nezavedno in nenamerno (Lode, Franchi in Frederiksen, 2012). Ta pristop
temelji na predpostavki, da je najboljše učenje interaktivno, kjer je vsaka naslednja naloga
malenkost težja od učenčeve trenutne ravni znanja (Norving, 2016). Konstruktivistični pristop
se pogosto uporablja za zagotovitev doseganja učnih ciljev, saj daje prednost učenju iz izkušenj,
problemskem in projektnemu učenju (Lewis in Williams, 1994). Pri takšnih vrstah učenja lahko
učenci opazujejo delo sovrstnikov in z njimi sodelujejo, da bi tako izboljšali svoje sposobnosti.
Takšno učenje vključuje proces delanja napak, preizkušanja in sposobnost učencev, da z
uporabo svojih preteklih in sedanjih izkušenj svoje znanje nadgradijo (Felicia, 2009). Primerno
oblikovano učno okolje lahko poveča notranjo motivacijo, radovednost, domišljijo in učencem
predstavlja izziv (Maragos in Grigoriadou, 2007). Takšno okolje lahko učencem ponudi
praktične primere nalog iz vsakdanjega življenja, s pomočjo katerih lahko eksperimentirajo in
se učijo iz lastnih napak.
Pri poučevanju programiranja je eden glavnih izzivov učitelja, kako pritegniti učence k takemu
učenju in utrjevanju programiranja, ki jim bo omogočilo, da postanejo ustvarjalci in oblikovalci
tehnologije, ne le njeni uporabniki (UNESCO, 2013). Za to potrebujemo motivacijske pristope
in orodja, ki bi bila primerna za začetnike in bi zagotovila kar najučinkovitejše učne izkušnje
za vse učence.
5
2.2 RAČUNALNIŠKO MIŠLJENJE
Wing (2006) opredeli računalniško mišljenje kot razmišljanje, ki temelji na računalniških
metodah, ki jih lahko izvajamo z računalnikom ali brez njegove uporabe. Pri tem ne gre za to,
da razmišljamo kot računalnik, pač pa, da znamo pri reševanju problemov uporabljati tehnike
in metode iz računalništva. Računalniško mišljenje nam torej omogoča, da se lotimo reševanja
kompleksnega problema, ga razumemo in razvijemo možne rešitve zanj. Nato pa te rešitve
predstavimo na način, ki ga razumejo ljudje in računalnik. Obstajajo štiri ključne tehnike za
računalniško mišljenje (Slika 1):
• dekompozicija – razgradnja kompleksnega problema na manjše, bolj obvladljive dele
• prepoznavanje vzorcev – iskanje podobnosti med problemi in znotraj problemov
• abstrakcija – osredotočanje samo na pomembne informacije, neupoštevanje
nepomembnih podrobnosti
• algoritmi – razvoj postopnih rešitev problema ali pravil, ki jih je potrebno upoštevani
pri reševanju problema.
Slika 1: Ključne tehnike računalniškega mišljenja
Računalniško mišljenje je postalo eno od osnovnih spretnosti, ki bi jih moral pridobiti vsak
učenec, ne glede na poklic, ki ga bo opravljal v prihodnosti (Fletcher in Lu, 2009). Wing (2006)
tako zagovarja poučevanje računalniškega mišljenja kot formativno spretnost na ravni
osnovnega znanja, in sicer za vsakega posameznika, ne glede na njegovo nadaljnjo poklicno
6
pot. Tako kot predstavlja znanje pisanja in branja osnovo za učinkovito komuniciranje, tako
predstavlja računalniško mišljenje osnovo za sistematično in učinkovito procesiranje informacij
in nalog. Čeprav je cilj poučevanje vseh učencev računalniškega mišljenja zelo plemenit, pa so
učitelji postavljeni tudi pred razne pedagoške izzive. Pri tem je najpomembnejše vprašanje
vloga programiranja in vprašanje, ali ga lahko ločimo od poučevanja osnovnega računalništva
ter koliko programiranja, če sploh kaj, bi se bilo potrebno naučiti za učinkovito računalniško
mišljenje. Vsekakor je za obvladanje računalništva potrebno postaviti temelje računalniškega
mišljenja, preden se učenci začnejo učiti prvega programskega jezika. Programiranje pa je za
učinkovito obvladovanje računalniške znanosti pomembno tako, kot je pomembno dokazovanje
v matematiki in analiza literature v književnosti. Po analogiji mora biti torej programiranje
vstop v višje računalniško mišljenje in ne prvo srečanje učenca z računalniškim mišljenjem.
2.3 PROBLEMSKO UČENJE
Problemsko učenje je celostni pristop za doseganje učinkovitega in smiselnega učenja
(Jonassen, 2004). Učenci morajo za uspešno reševanje problemov problem razumeti, zanj
razviti načrt in ta načrt tudi preizkusiti. Sami morajo torej analizirati strategije, za katere mislijo,
da bodo rešile problem, posledično pa bodo pri tem razvili kreativne rešitve in dosegli
učinkovito učenje (Bransford in Stein, 1984). Iz tega razloga je problemsko učenje kot sredstvo
za spodbujanje učenja razširjeno na mnogih področjih, kot so znanost (Linn, Clark in Slotta,
2003), matematika (Jonassen, 2003), oblikovanje (Jermann in Dillenbourg, 2008) in
računalništvo. Problemsko učenje v računalništvu, ki vključuje sestavljanje računalniških
programov za rešitev problema, velja za ključno kompetenco izobraževanja na računalniškem
področju, saj v računalništvu bolj kot zgolj tehnično usmerjene aktivnosti potrebujemo
predvsem dobre sposobnosti reševanja problemov (Kay idr., 2000). Ravno dobre sposobnosti
reševanja problemov pa so glavna težava in primanjkljaj začetnikov. Začetniki so večinoma
osredotočeni zgolj na površinsko znanje, primanjkuje jim tudi modelov za reševanje in zato ne
razvijejo potrebnih spretnosti za rešitev problema (Robins, Rountree in Rountree, 2003).
Reševanje učnih problemov pri programiranju je za začetnike težko še posebej, ker morajo
razumeti in znati uporabljati koncepte za reševanje problemov, kot so zanke, pogoji, rekurzija
itd. Spodbujanje razvoja sposobnosti učencev za problemsko reševanje je torej ena glavnih
tematik izobraževanja na področju računalništva.
7
Problemsko učenje je bilo najprej in najširše uporabljeno na področju medicine. Natančneje je
ta pristop usmerjal učence k ugotavljanju smiselnosti zbranih podatkov (Rhem, 1998).
Problemski pristop kot eden izmed pedagoških pristopov pa se uporablja na več področjih, ne
le na področju medicine.
Učenje na podlagi problemov je koncept poučevanja, ki usmerja učenje na osnovi nekega
problema, ki ga po navadi definira učitelj, da bi z njegovo pomočjo učenci dosegli neke učne
cilje. Izhaja iz kognitivne in konstruktivistične teorije in zagovarja dejstvo, da učenci s
povezovanjem izobraževalnega gradiva in svojih življenjskih izkušenj pridobijo več (Duffy in
Jonnasen, 1992). Konstruktivizem poziva k učnim konceptom, ki so izkustveni, aktivni,
sodelovalni in ki razvijajo spretnosti reševanja problemov (Jonnasen, 2000). Cilj je, da učenec
ne samo pasivno absorbira in ponavlja informacije, temveč da aktivno uporablja gradivo, pri
tem pa sodeluje z vrstniki in uporablja svoje pretekle izkušnje in sposobnosti reševanja
problemov. Končni cilj je torej razvoj sposobnosti kritičnega mišljenja.
Učenec mora biti pri problemskem učenju aktivni udeleženec v učnem procesu (Bonwell in
Eison, 1991). Pri tem je pomembno, da lahko učenci razvijajo svoj tok misli in rešitev, ne da bi
morali pri tem strogo slediti predpisanemu postopku, ki si ga je zamislil učitelj. Učenci morajo
iskati rešitve in razvijati poti do cilja svobodno, na svoj način. Seveda pa tudi pri tem procesu
obstaja določena struktura (Kirschner, Sweller in Clark, 2006), le da je ta nekoliko ohlapnejša
in učencu vendarle omogoča, da lahko ob pomoči učitelja raziskuje različne smeri reševanja
problema. Obstaja več pedagoških pristopov, ki omogočajo ta način povezovanja, eden izmed
njih je problemsko učenje.
2.4 PROJEKTO UČENJE
Izraz projektno delo sta prvič uporabila John Dewey in William Kilpatrick leta 1918 (Edutopia,
2014). Projektno učenje je učni pristop, pri katerem se učenci učijo s preučevanjem
kompleksnega vprašanja, problema ali izziva. Spodbuja aktivno učenje, angažira učence in
omogoča razmišljanje na višji ravni (Savery, 2006). Učenci raziskujejo različne probleme in
najdejo odgovore oz. rešitve skozi projekt. Učenci imajo tudi določen nadzor nad projektom,
na katerem bodo delali, nadzor nad tem, kako bo projekt končan in kakšen bo končni izdelek.
Projektno učenje temelji na postavljanju vprašanj učencem, ki vzpodbudijo njihovo naravno
radovednost. Projekt se začne z raziskavo. Učenci razvijejo raziskovalno vprašanje, nato pa
8
njihovo nadaljnje delo vodi in raziskuje učitelj. Na podlagi odkritij učenci ustvarjajo projekt, ki
ga nato delijo z drugimi. Ključno pri tem pristopu je, da učenec izbire določen način izvedbe,
učitelj pa celoten postopek nadzira in odobri vsako izbrano odločitev, preden jo učenec zares
sprejme. Pri tem se lahko učenci z zanimanjem za podobne projekte odločijo pri projektnem
delu sodelovati, s čimer se spodbujata tudi sodelovanje in komunikacijske sposobnosti.
Projektno učenje ne sme biti le nadomestek za podporo učenja, pač pa osnova učnega načrta. V
večini primerov projektnega učenja so osnovna znanja, kot so pisanje, branje in računanje že
tako in tako vključena. V številnih primerih pa se je poleg tega potrebno seznaniti tudi z
določenimi spoznanji s področja znanosti in aktualnim socialnim problemom. Rezultat takšnega
učenja je boljše razumevanje tematike, trajnejše znanje in večja motivacija za učenje.
Problemsko učenje je tako ključna strategija za ustvarjanje neodvisnih in kritičnih mislecev, saj
učenci ob takšnem učenju rešujejo resnične probleme, tako da oblikujejo lastne poizvedbe,
načrtujejo svoje učenje, organizirajo svoje raziskave in uvajajo množico učnih strategij.
2.5 PRIMERJAVA PROBLEMSKEGA IN PROJEKTNEGA UČENJA
V procesu poučevanja programiranja pri pouku lahko pogosto zasledimo tehnike, v okviru
katerih mora učenec posamezne koncepte različnih poglavij predmeta med seboj povezati z
namenom, da reši nek problem, ki mu je bil dodeljen v okviru določenega projekta. Pri tem pa
je pomembno razlikovati med problemskim in projektnim učenjem.
Tako problemsko kot projektno delo sta aktivni obliki učenja, ki imata pomembno mesto v
današnji učilnici in spodbujata učenje 21. stoletja. Glavna razlika med njima je, da učenci ob
zaključku problemskega učenja pogosto delijo svoje rezultate in skupaj z učiteljem določijo
učne cilje. Po drugi strani pa je projektno učenje pristop, pri katerem je postavljen nek cilj in
pri katerem je struktura poučevanja precej določena.
Projektno učenje je pogosto multidisciplinarno in dolgotrajnejše, medtem ko se problemsko
učenje navadno nanaša na en predmet in poteka v krajšem časovnem obdobju. Na splošno
projektno učenje sledi splošnim korakom, medtem ko problemsko učenje zagotavlja posebne
korake. Pomembno je tudi, da projektno učenje pogosto vključuje avtentične naloge, ki rešujejo
resnične probleme, medtem ko problemsko učenje uporablja scenarije in primere, ki so z
resničnim življenjem morda manj povezani (Larmer, 2014).
9
2.6 POIGRITEV
Gioia in Brass (1985) v članku Teaching the TV Generation trdita, da sta učenje in poučevanje
boljša, če je stil poučevanja prilagojen stilu učencev. Avtorja sta opozarjala, da bo učence, ki
so odrasli v okolju, v katerem prevladujejo vizualne podobe (TV-generacija), težko spodbuditi
k učenju zgolj z verbalnimi metodami poučevanja. Proserpio in Gioia (2007) pa kasneje v
članku Teaching the Visual Generation trdila, da poučevanje ne sme biti niti verbalno niti
vizualno, pač pa se mora ponovno prilagoditi stilu učencev, torej mora biti virtualno. Avtorji
torej trdijo, da se optimalno poučevanje in učenje pojavi, ko je poučevanje usklajeno z učnimi
stili učencev. Danes je okolje učencev ponovno drugačno kot pred desetletji, zato potrebujejo
drugačne pristope k poučevanju. Tehnologija in igre so danes del učenčevega življenja, to pa
lahko izkoristimo tako, da v razrede vpeljemo zanimive, zabavne in spodbujajoče pristope, ki
temeljijo na aktivnostih, ki so učencem blizu.
Uporaba izobraževanih iger kot učnega orodja predstavlja obetaven pristop, saj z njimi učenci
poleg znanja krepijo tudi sposobnost reševanja problemov, igre pa imajo veliko motivacijsko
moč. Uporabljajo namreč številne mehanizme za spodbujanje ljudi, da se, po navadi brez
kakršne koli nagrade, z njimi igrajo le zaradi samega igranja in možnosti za zmago. Ustvarjanje
za učence privlačne izobraževalne igre je težko, dolgotrajno in velikokrat drago (Kapp, 2012).
Prav tako je za njihovo uporabo v razredu potrebna premišljena izbira tehnične infrastrukture
in ustrezno pedagoško povezovanje. Za razliko od zahtevnejših iger, ki zahtevajo veliko
oblikovanja in razvoja, pa pristop poigritve predlaga uporabo igrivega razmišljanja in
elementov oblikovanja za namene povečanja motivacije pri učencih. Pristop poigritve pomeni
uporabo elementov igre v kontekstih, ki z njo niso povezani (Deterding idr., 2011). Ključna pri
tem pristopu za spodbujanje uporabnikov je uporaba različnih elementov, kot so točke,
zvezdice, tekmovalne lestvice in zgodbe (Nah idr., 2014). Pri tem pristopu je koncept igranja
precej drugačen od koncepta igre ali izobraževane igre. Kljub temu da koncept poigritve ni nov,
pa se je sam izraz poigritev pojavil relativno pozno (Deterding idr., 2011). Prva dokumentirana
uporaba izraza izhaja iz leta 2008, širše pa se je izraz začel uporabljati šele v letu 2011.
Vsekakor pa se je v zadnjih letih zelo povečala njegova uporaba za poslovne namene, pri
trženju, upravljanju in drugje. Vse to pa predvsem zaradi njegovega potenciala, da usmeri
vedenje uporabnikov v želeno smer. Programi zvestobe, kot sta na primer Foursquare in Nike+,
so primeri uspešnih izdelkov s trga. Na računalniškem področju predstavlja takšen primer
spletna strani Stackoverflow.com. Stran deluje na način povečanja ugleda uporabnikov, in sicer
tako, da odgovarjajo na zastavljena vprašanja, od ostalih uporabnikov pa prejemajo glasove
10
podpore za svoje odgovore. Še en primer uporabe poigritve lahko najdemo na spletnem mestu
codeacademy.com, ki prav tako uporablja elemente igre za motiviranje uporabnikov.
Uporabnik namreč za opravljene naloge in ogledana predavanja prejme točke. Sistemi, kot je
eBay, uporabljajo elemente igre za pridobivanje in zvestobo kupcev ter za spodbujanje
konkurenčnosti.
Učenje s konceptom poigritve je težko, zahtevno in stresno, toda pomembno, saj lahko dobro
oblikovane igre pomagajo učencem pridobiti spretnosti, znanja in sposobnosti v okolju udobja,
z visoko stopnjo zadržanja in učinkovitim priklicem (Kapp, 2012). Poleg tega poigritev
pospešuje krivuljo učenja, omogoča dojemanje kompleksnih predmetov in zagotavlja sistemski
pogled na celoten proces (Kapp, 2012). Številne študije kažejo, da ne obstaja več stereotip
igranja, vsakdo se namreč lahko igra za različne namene, ne glede na starost; danes se ne igrajo
več samo otroci in najstniki (Kark, 2011 in Association, 2014).
2.7 UČENJE S PRIMERI
Ljudje si pri reševanju problemov pogosto pomagamo tudi z izkušnjami pri reševanju preteklih
problemov (Weber, 1996). Še posebej se to kaže na področju programiranja, kjer se tako
izkušeni programerji kot tudi začetniki pri reševanju novih programskih nalog pogosto
poslužujejo uporabe idej programov, ki so jih ustvarili oz. so se jih naučili v preteklosti (Linn
in Clancy, 1992 in Novick in Holyoak, 1991). Tradicionalni pristop uporabe primerov pri
poučevanju je, da učitelj za vsako učno uro pripravi skrbno izbrane primere reševanja
problemov v obliki krajših programov. Učitelj pri učni uri te probleme analizira in učencem za
namene nadaljnjega raziskovanja in uporabe problema priskrbi tudi kodo. Težava pri
tradicionalnem pristopu uporabe problemov pri programiranju v razredu je, da deluje le pri
malih in homogenih skupinah učencev (Brusilovsky, 2001). Takšni učenci imajo namreč
približno enako raven sposobnosti in znanja, zaradi česar lahko učitelj vnaprej določi število in
kompleksnost primerov za posamezno učno uro ter izbere pravo hitrost in poglobljenost
razlage. Pri delu z velikimi nehomogenimi skupinami učencev, kjer imajo učenci izrazito
različno raven predznanja in različne sposobnosti dojemanja, pa se učinkovitost tradicionalnega
pristopa uporabe primerov bistveno zmanjša. Različni učenci potrebujejo različno hitrost
obravnave primerov in različno raven razlage. Poleg tega potrebujejo običajno učno šibkejši
učenci za razumevanje nekega koncepta bistveno več primerov. Podobno opažanje sta povzela
tudi Brusilovsky in Yudelson (Brusilovsky in Yudelson, 2008).
11
3. SPLETNA STRAN HEKERSKI NAPAD
Izdelala sem spletno stran na temo hekerskega napada z nalogami, povezanimi v zgodbo.
Spletna stran je bila izdelana s pomočjo jezikov HTML, CSS, PHP in SQL. Za namen
shranjevanja podatkov o uporabnikih strani je bila s pomočjo phpMyAdmin ustvarjena baza.
Spletna stran Hekerski napad je dostopna na naslovu https://www.vegova.si/e-sola/hekerski-
napad/login.php.
V nadaljevanju poglavja bo podrobneje predstavljena spletna stran z nalogami. Predstavljen bo
namen spletne strani in njena uporaba, na koncu pa bodo podrobneje predstavljene tudi
posamezne naloge, znanja, ki jih neka naloga preverja in njene rešitve, skupaj z razlago.
3.1 SPLETNA STRAN
Zamisel za oblikovanje spletne strani Hekerski napadi se je rodila iz koncepta spletne strani
Advent of Code (https://adventofcode.com/). Gre za spletno stran, ki vsak december od leta
2015 dalje objavi petindvajset nalog. Vsak dan od 1. decembra do božiča se razkrije ena od
nalog, ki si vsebinsko sledijo in se navezujejo na temo božiča. Nagrada za vsako rešeno nalogo
je zvezdica, izdelana pa je tudi lestvica prvih 100 uporabnikov, ki so najhitreje rešili posamično
nalogo.
Spletna stran Hekerski napadi je bila izdelana s pomočjo jezika HTML (angl. Hyper Text
Markup Language) in oblikovana s pomočjo jezika CSS (angl. Cascading Style Sheets). Ker se
je za sodelovanje na spletni strani potrebno prijaviti in ker spletna stran preverja pravilnost
uporabnikovih odgovorov, je bil za to implementacijo uporabljen jezik PHP (angl. Hypertext
Preprocessor). S pomočjo phpMyAdmin je bila ustvarjena baza podatkov o uporabnikih. Za
dostop strani do podatkov uporabnika in za pošiljanje posameznih podatkov spletni strani pa so
bili uporabljeni stavki v jeziku SQL (angl. Structured Query Language).
S pomočjo spletne strani in njenih nalog želimo, da se učenci vživijo v vlogo programerja, ki
mora rešiti svet pred hekerskimi napadi. Pri tem pa mora pri vsakem napadu rešiti enega od
problemov. To stori tako, da lokalno na svojem računalniku sestavi program, ki mu vrne
pravilni rezultat glede na naključno generirane unikatne podatke, ki so mu bili dodeljeni pri
nalogi. Če uporabnik nalogo reši pravilno, se izvede nov hekerski napad, ki ga mora učenec
uspešno preprečiti. Pri reševanju nalog se učenec spoprijema z različnimi izzivi, ki od njega
12
zahtevajo poznavanje osnovnih struktur programiranja, kot so pogojni stavki, zanke, tabele,
funkcije in nizi.
Cilj igre je pravilno rešiti vseh 25 nalog oz. hekerskih napadov in s tem utrditi znanje s področja
programiranja. Posredni cilj je torej prepričati učence, da vztrajajo pri reševanju nalog za
utrjevanje, in sicer skozi koncept problemskega učenja in koncept poigritve. Ta dva koncepta
sta bila izbrana, ker je v literaturi mogoče zaslediti, da na učence vplivata bolj motivacijsko kot
pa klasičen način poučevanja programiranja. Poleg tega so bile naloge sestavljene tako, da se
učenec ob njihovem reševanju prelevi v neko drugo osebo, ki rešuje privlačne probleme
namesto klasičnih programerskih nalog, ki po navadi predstavljajo reševanje golih
matematičnih problemov in so za učence dostikrat nezanimivi.
3.2 NAMEN IN UPORABA SPLETNE STRANI
Spletna stran Hekerski napad je namenjena dijakom 2. letnika strokovne šole, smer tehnik
računalništva, in tudi vsem drugim začetnikom v programiranju, ki želijo utrditi svoje znanje.
Naloge s spletne strani lahko uporabimo za utrjevanje znanja posameznega sklopa pri pouku
programiranja ali za domače delo, lahko pa služijo tudi kot utrjevanje znanja ob koncu
poučevanja predmeta osnove programiranja oz. pred začetkom izvajanja predmeta
zahtevnejšega programiranja.
Z reševanjem nalog na tej spletni strani pa učenci poleg algoritmičnega mišljenja, urjenja pri
reševanju problemov in utrjevanja programskih struktur pridobijo tudi druge veščine,
pomembne za njihov razvoj. Zgradba strani in nalog jih namreč spodbujajo k ustvarjalnemu
načinu razmišljanja, k razmišljanju o tem, kako čim hitreje in čim lažje rešiti določeni problem.
Pri vsem tem sta v ospredju predvsem zgodba in dizajn spletne strani, medtem ko je pravi
namen strani in nalog uporabnikom prikrit.
Ob dostopu do spletne strani se mora uporabnik najprej registrirati (Slika 2). V ta namen mora
določiti še neuporabljeno uporabniško ime in geslo.
13
Slika 2: Registracija
Ob uspešni prijavi se uporabniku za vsako od 25 nalog generirajo naključni podatki (Slika 3 in
Slika 4), na podlagi teh podatkov in programov za rešitev posamezne naloge pa se mu določijo
še pravilne rešitve.
Slika 3: Baza uporabnikov
Slika 4: Baza ene naloge
Ko je registracija zaključena, spletna stran uporabnika preusmeri na začetno stran (Slika 5), kjer
je predstavljena uvodna zgodba.
14
Slika 5: Začetna stran z uvodno zgodbo
Zgodba pravi: »Dobrodošel! Urgentno si bil poklican v pisarno guvernerja za državno varnost.
Sporočijo ti, da so v sistem vdrli hekerji iz Severne Jekorije, ki grozijo, da bodo ob polnoči
povzročili električni mrk. Zaveš se, da gre zares. Novica se ne sme razvedeti, saj bi nastala
panika. Ti si edini, ki veš in nas lahko rešiš pred propadom. Pogledaš na uro, ki je pravkar
odbila enajst. Pohiteti bo treba. Če želiš preprečiti to katastrofo, moraš sistem rešiti pred 25
hekerskimi napadi. Ti napadi na sistem si sledijo eden za drugim in ogrožajo različne segmente
našega sistema. Tvoja naloga je, da vsak segment sistema uspešno ubraniš pred napadom. Ko
napad uspešno preprečiš, se pojavi nov. Za uspešno preprečitev električnega mrka moraš
preprečiti vseh 25 hekerskih napadov. Ugotoviš, da je usoda naše civilizacije odvisna od tebe.
Srečno!«
S klikom na gumb "začni" se odpre prvi hekerski napad (Slika 6), ki opiše problem, poda neke
naključne podatke in od uporabnika zahteva pravilen odgovor. Enaka zgradba se pojavlja tudi
v preostalih nalogah.
15
Slika 6: Primer naloge
Če uporabnik v polje za odgovor vnese napačno vrednost, se mu izpiše opozorilo (Slika 7),
sicer pa ga stran preusmeri na naslednjo nalogo.
Slika 7: Obvestilo o napačni rešitvi
Ko uspešno preprečimo vseh 25 hekerskih napadov, se pojavi končna stran (Slika 8) z
obvestilom: »Čestitke! Hekerski napad na sistem si uspešno preprečil in poskrbel, da so hekerji
iz Severne Jekorije razkriti in kaznovani!« S tem se uporabnikovi izzivi končajo.
16
Slika 8: Končna stran
3.3 NALOGE
Na spletni strani se nahaja 25 nalog za utrjevanje programiranja, ki simulirajo hekerske napade.
Naloge si logično sledijo in se navezujejo na začetno zgodbo, tako da se uporabnik zlahka vživi
v vlogo rešitelja sveta pred hekerskimi napadi. Vsak napad zahteva rešitev nove naloge.
Vsaka naloga ima svoje ime in določen koncept, ki ga obravnava.
Varnostno geslo Štetje (prištevanje in odštevanje), pogojni stavki, zanke
Iskanje ključa
šifriranih podatkov
Preštevanje različnih objektov, pogojni stavki, zanke, nizi, tabele
GPS Pretvarjanje med številskimi zapisi, deljenje, deljenje z
ostankom, pogojni stavki, zanke, tabele
Poišči geslo Štetje, iskanje nekega znaka v nizu, koncept stanja, pogojni
stavki, zanke, nizi
Dešifriraj geslo Računanje vsote, pogojni stavki, zanke, nizi
Pretvarjanje v binarni
zapis
Štetje, pretvarjanje med številskimi zapisi, deljenje, ostanek,
pogojni stavki, gnezdene zanke, tabele
Analiza besedil glede
na iskano besedo
Štetje, pogojni stavki, zanke, nizi
17
Analiza besedil glede
na dolžino besed
Koncept štetja z vmesno ponastavitvijo števca, pogojni stavki,
zanke, nizi
Napad na ključe za
podpisovanje
certifikatov
Iskanje največjega in najmanjšega elementa, gnezdene zanke,
dvodimenzionalne tabele
Napad na pomnilnik Odločitveni stavki, zanke, tabele
Pošiljanje sporočila
guvernerju
Funkcije
Lokacije državnih
skrivališč
Dvodimenzionalne tabele, iskanje elementa
Kodiranje po RLE-
metodi
Primerjanje dveh znakov v nizu, štetje enakih zaporednih znakov
niza
Napad na telefonske
številke
Tabele nizov, iskanje znakov v nizih, dvodimenzionalne tabele
Izbris besed v zaupnih
dokumentih
Iskanje podniza v nizu, štetje
Dodane besede v
zaupnih dokumentih
Tabele nizov, iskanje črk v nizih, štetje
Leksikografsko
urejanje besed
Urejanje elementov v tabeli
Izbrisane črke Funkcije, iskanje znakov v nizu
Napad na števila Razstavljanje števil na števke, odločitveni stavki, pogoji
Napad na
identifikacijske
številke dokazov
Razstavljanje števil na števke, funkcije
Branje zakodiranega
števila
Branje elementa z določenega mesta v tabeli, dvodimenzionalne
tabele
Določitev novih
identifikacijskih števil
Iskanje po tabeli, tabele
18
Napad na računske
operacije
Štetje različnih elementov v nizih
Mapa Fibonacci Iskanje člena zaporedja
Koordinate
napadalcev
Sestavljanje pogojev, uporaba koordinatnega sistema
3.3.1 Varnostno geslo
Zgodba
Pri prvi nalogi moramo ugotoviti pravo geslo za vstop v sistem: »S prvim napadom, ki ga moraš
preprečiti, so hekerji spremenili varnostno geslo za vstop v sistem. Edini podatek, ki ga imaš,
da odkriješ spremenjeno geslo, je niz, sestavljen iz znakov + in – ter drugih znakov. Začneš z
vrednostjo 0, nato pa slediš navodilom za vsak posamezni znak. Znak + pomeni povečanje za
ena, znak – pa zmanjšanje za 1, ostali znaki nimajo pomena, pojavljajo se le zato, da te
zmedejo. Kakšna je koda?«
Za lažje razumevanje problema je podanih tudi pet primerov:
• +*.++#-&/+ predstavlja geslo 3
• ++(..-!-%. predstavlja geslo 0
• --%$-+#-??* predstavlja geslo –3
• +-#$&+'+ predstavlja geslo 2
• -$#-.-?+$#.++%-/-+*-!#++-++/&&-%&+ predstavlja 1
Učni cilji
Znanje, ki ga želimo utrjevati pri prvi nalogi, je poleg osnovnih struktur pogojnih stavkov in
zank tudi štetje (prištevanje in odštevanje).
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
19
string podatki = "<naključni podatki>";
int dolzina = podatki.length();
int koda = 0;
for(int i = 0; i < dolzina; i++) {
if(podatki[i] == '+') {
koda++;
}
else if (podatki[i] == '-') {
koda--;
}
}
cout << koda;
return 0;
}
V tej nalogi uporabnik prejme daljši niz naključnih podatkov, sestavljen iz množice različnih
znakov, med katerimi pa nas zanimata le znaka + in –, pomen ostalih znakov lahko zanemarimo,
saj nimajo določenega nobenega pomena. Spremenljivki, ki šteje pluse in minuse (recimo ji
koda) na začetku priredimo vrednost 0, saj tako veleva naloga. Nato je potrebno iti čez vse
znake niza in za vsak posamezni znak preveriti, ali gre za '+', v tem primeru spremenljivko koda
povečamo za 1, ali gre za '–', v tem primeru pa spremenljivko koda zmanjšamo za 1, sicer pa
ne storimo ničesar, le nadaljujemo s pregledovanjem naslednjega znaka v nizu.
3.3.2 Iskanje ključa šifriranih podatkov
Zgodba
Besedilo druge naloge pravi: »Ponovno imaš dostop do sistema, vendar kmalu ugotoviš, da so
vsi podatki postali nesmiselni. Kar naenkrat se na ekranu začnejo izpisovati nesmiselna števila,
ki predstavljajo šifrirane podatke sistema. Ključ za pridobitev dešifriranih podatkov je seštevek
zmnožkov posamezne števke in števila njenih ponovitev.«
Podani so naslednji primeri:
• 2634356 = 1 ∙ 2 + 2 ∙ 3 + 1 ∙ 4 + 1 ∙ 5 + 2 ∙ 6 = 29
• 1451581 = 3 ∙ 1 + 1 ∙ 4 + 2 ∙ 5 + 1 ∙ 8 = 25
• 391379315913 = 3 ∙ 1 + 4 ∙ 3 + 1 ∙ 5 + 1 ∙ 7 + 3 ∙ 9 = 54
Učni cilji
Znanja, ki jih želimo utrjevati pri tej nalogi, so poleg pogojnih stavkov, zank in nizov, tudi
preštevanje različnih objektov s pomočjo tabele.
20
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
int ponovitve[10] = {};
int dolzina = podatki.length();
int znak;
int resitev = 0;
for (int i = 0; i < dolzina; i++) {
znak = int(podatki[i]) - int('0');
ponovitve[znak]++;
}
for (int i = 0; i < 10; i++) {
resitev += i * ponovitve[i];
}
cout << resitev;
return 0;
}
Naključni podatek v tej nalogi je niz števk. Ponovno se je potrebno sprehoditi čez podan niz in
pri tem preštevati posamezne števke. V ta namen uporabimo tabelo (poimenujmo jo pojavitve),
velikosti 10, saj želimo prešteti pojavitve desetih različnih števk. To bi lahko izvedli tako, da
bi zapisali blok pogojnih stavkov, v katerih bi preverjali, ali gre za eno ali drugo ali tretjo itd.
števko in posledično povečevali ustrezna mesta v tabeli pojavitve. Ker bi v tem primeru dobili
precej dolgo kodo, jo raje nadomestimo z izračunom:
znak = int(podatki[i]) - int('0');
ki odšteje ASCII-vrednost znaka posamezne števke in ASCII-vrednost znaka '0'. Tako
priredimo spremenljivki znak dejansko vrednost števke in povečamo ustrezno mesto v tabeli
pojavitve. V drugi zanki se nato le sprehodimo po tabeli pojavitve in množimo indeks, ki v tem
primeru predstavlja določeno števko s posamezno vrednostjo v tabeli, ki predstavlja število
ponovitev te števke.
3.3.3 GPS
Zgodba
Tretja naloga se glasi: »Tarča naslednjega napada je center, ki nadzira GPS-satelite. Hekerji
so z napadom zmedli uro in tako tudi onesposobili navigacijo. Če želiš ponovno določiti točen
21
čas, moraš 1000 na videz nesmiselnih števil, ki predstavljajo sekunde, sešteti in jih pretvoriti v
dni, ure, minute in sekunde. Pri tem te število dni ne zanima, saj želiš ponovno nastaviti le uro.
Končen zapis naj bo oblike h:min:sek. Koliko je ura?«
Podani so trije primeri:
• 50 31 43 89 45 90 4 23 predstavlja 0 dni, 0 ur, 6 minut in 15 sekund – to pomeni uro
0:6:15
• 1561 2421 1144 5133 178 190 63 463 predstavlja 0 dni, 3 ure, 5 minut in 53 sekund –
to pomeni uro 3:5:53
• 3434 7896 97676 54389 8234 3651 986223 56743 43256 68932 predstavlja 15 dni, 9
ur, 33 minut in 54 sekund – to pomeni uro 9:33:54 (števila dni ne upoštevamo).
Učni cilji
Pri tej nalogi ponovno utrjujemo pogojne stavke, zanke in tabele, hkrati pa tudi pretvarjamo
med številskimi zapisi ter vadimo deljenje in deljenje z ostankom.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int podatki[] = <naključni podatki>;
int vsota = 0;
int dolzina = 1000;
for (int i = 0; i < dolzina; i++) {
vsota += podatki[i];
}
int sekunde = vsota % 60;
vsota /= 60;
int minute = vsota % 60;
vsota /= 60;
int ure = vsota % 24;
cout << ure << ":" << minute << ":" << sekunde;
return 0;
}
Naključni podatki so podani v obliki elementov tabele, ki jih moramo najprej sešteti, da dobimo
skupno število sekund. Potrebno je torej pregledati tabelo in vsak posamezen element tabele
prišteti spremenljivki vsota. V naslednjem koraku pa moramo pretvarjati v različne časovne
enote. Ker je pri pretvarjanju iz sekund v minute in iz minut v ure enota 60, gre pri tem v bistvu
za pretvarjanje v 60-tiški številski zapis in podobno pri pretvarjanju iz ur v dneve. Za takšno
22
pretvarjanje potrebujemo deljenje z ostankom (%), ki – kot pove ime samo – izračuna ostanek
pri deljenju dveh števil.
int sekunde = vsota % 60;
3.3.4 Poišči geslo
Zgodba
Pri četrtem napadu nas pričaka naslednja naloga: »Svetovna ura je rešena. Na ekranu pa so se
začeli pojavljati nesmiselni znaki, iz katerih moraš sestaviti pravilno geslo. Geslo je sestavljeno
iz vseh znakov, ki se nahajajo med { in }. Besedilo, ki je izven oklepajev, je nepomembno.
Ugotovi, kolikokrat se znotraj oklepajev pojavijo črke v, i, r, u in s.«
Podan je naslednji primer:
A computer virus a type of {malicious software} that, when executed, replicates itself by
{modify}ing other computer programs and inserting its own {code}. When this replication
succeeds, the affected areas are then said to be infected with a computer virus.
Učni cilji
Pri tej nalogi utrjujemo pogojne stavke, zanke in nize ter štetje, iskanje nekega znaka v nizu in
vadimo koncept stanja (smo ali nismo znotraj oklepaja).
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
int dolzina = podatki.length();
int resitev = 0;
int koda = false;
for(int i = 0; i < dolzina; i++) {
if (podatki[i] == '{') {
koda = true;
}
else if (podatki[i] == '}') {
koda = false;
}
if (koda == true) {
if (podatki[i] == 'v' || podatki[i] == 'i' ||podatki[i] == 'r'
23
|| podatki[i] == 'u' || podatki[i] == 's') {
resitev++;
}
}
}
cout << resitev;
return 0;
}
Naključni podatki so podani v obliki niza poljubnih znakov, med katerimi moramo poiskati
znaka { in } ter vse znake, ki se pojavijo med njima. Pregledati je torej potrebno celoten niz in
iskati {, saj se tam začne naše geslo. Kako pa bomo v nadaljevanju vedeli, da se nahajamo
znotraj oklepajev? Tukaj si lahko pomagamo s konceptom stanja, torej z eno spremenljivko
(recimo koda), ki je binarna (preklaplja le med 0 in 1 oz. true in false) in nam služi zgolj za to,
da v vsakem trenutku vemo, ali se nahajamo v oklepaju (koda ima vrednost true) ali izven njega
(koda ima vrednost false). To pomeni, da moramo pri prehajanju čez niz najprej preveriti, ali je
posamezen znak enak– v tem primeru spremenimo vrednost koda v true; če ni znaka '{' ,
preverimo, ali je znak enak '}'; v tem primeru spremenimo vrednost koda v false. S tem smo
torej omogočili, da s pomočjo spremenljivke koda v vsakem trenutku vemo, ali se nahajamo
znotraj oklepajev ali ne. Morda omenimo le še to, da se na začetku programa seveda še ne
nahajamo v oklepaju, zato spremenljivko koda nastavimo na false.
Zdaj torej ostane le še, da preverimo, ali se nahajamo v oklepaju.
if (koda == true)
Če se nahajamo v oklepaju, preverimo, ali je znak enak kateremu izmed znakov 'v', 'i', 'r', 'u',
's'. Če je, povečamo spremenljivko resitev, ki šteje naštete znake v geslu.
3.3.5 Dešifriraj geslo
Zgodba
Besedilo pete naloge se glasi: «Ugotovil si pravilno geslo, ki pa ga moraš, da ga boš razumel
in uporabil v nadaljevanju boja proti hekerjem, še dešifrirati. Sporočilo lahko dešifriraš po
naslednjem ključu: vsak soglasnik zamenjaj s črko, ki temu soglasniku sledi po abecedi, vsak
samoglasnik pa zamenjaj po pravilu: a → e → i → o → u → a. Presledki niso kodirani!
24
Kolikšen je seštevek ASCI-vrednosti posameznih znakov (brez presledkov!) dešifriranega
sporočila?«
Podana sta primera:
• ykimulaqmegajaq dešifriramo v zlonamerniheker; seštevek je 1614
• qubomukmej dešifriramo v racunalnik; seštevek je 1064.
Učni cilji
Pri tej nalogi utrjujemo pogojne stavke, zanke in nize ter računanje vsote.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
int dolzina = podatki.length();
char desifriran;
int resitev = 0;
char znak;
for (int i = 0; i < dolzina; i++) {
znak = podatki[i];
//Ne kodiraj presledkov
if (znak != ' ') {
switch (znak) {
case 'a':
desifriran = 'e';
break;
case 'e':
desifriran = 'i';
break;
case 'i':
desifriran = 'o';
break;
case 'o':
desifriran = 'u';
break;
case 'u':
desifriran = 'a';
break;
case 'z':
desifriran = 'a';
break;
default:
desifriran = znak + 1;
break;
}
resitev += int(desifriran);
}
}
cout << resitev;
25
return 0;
}
Naključni podatki so podani v obliki črk in presledkov, ki predstavljajo kodirano besedilo. Z
zanko se je potrebno sprehoditi po tem nizu in pri tem zanemariti presledke.
if (znak != ' ')
Nato pa po navodilu zamenjati posamezen samoglasnik z njegovim dekodiranim nadomestkom
ter zamenjati vse soglasnike z njihovimi nasledniki po abecedi.
desifriran = znak + 1;
Pri tem je potrebno paziti, da konec abecede sklenemo z začetkom; z drugimi besedami,
poskrbimo, da se črka z preslika v črko a.
Na koncu le še prištejemo ASCII-vrednosti dešifrirane črke spremenljivki resitev:
resitev += int(desifriran);
3.3.6 Pretvarjanje v binarni zapis
Zgodba
Šesta naloga nam zastavi problem pretvarjanja v binaren zapis: »Iz dešifriranega sporočila si
prejel 1000 števil v desetiškem številskem sistemu, ki pa jih računalnik ne razume, saj deluje v
svetu ničel in enic. Pretvori vsa desetiška števila v dvojiški številski sistem. Dvojiško število
dobiš z ostanki pri deljenju s številom 2. Postopek je potrebno ponavljati, dokler količnik ni
enak 0! Dvojiško število je število, sestavljeno iz ostankov, prepisanih od spodaj navzgor.
Koliko je vseh enic v dvojiških številih?«
Podana sta primera:
• Pretvorimo število 135:
135 = 2 ∙ 67 + 1
67 = 2 ∙ 33 + 1
33 = 2 ∙ 16 + 1
16 = 2 ∙ 8 + 0
26
8 = 2 ∙ 4 + 0
4 = 2 ∙ 2 + 0
2 = 2 ∙ 1 + 0
1 = 2 ∙ 0 + 1
Zapis dvojiškega sistema: 10000111. Število ima 4 enice.
• Pretvorimo število 1567:
1567 = 2 ∙ 783 + 1
783 = 2 ∙ 391 + 1
391 = 2 ∙ 195 + 1
195 = 2 ∙ 97 + 1
97 = 2 ∙ 48 + 1
48 = 2 ∙ 24 + 0
24 = 2 ∙ 12 + 0
12 = 2 ∙ 6 + 0
6 = 2 ∙ 3 + 0
3 = 2 ∙ 1 + 1
1 = 2 ∙ 0 + 1
Zapis dvojiškega sistema: 11000011111. Število ima 7 enic.
Učni cilji
Pri tej nalogi utrjujemo pogojne stavke, gnezdene zanke, tabele, štetje, pretvarjanje med
številskimi zapisi, deljenje in ostanek.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int podatki = <naključni podatki>;
int dolzina = 1000;
27
int stevilo, ostanek;
int resitev = 0;
for(int i = 0; i < dolzina; i++) {
stevilo = podatki[i];
for(; stevilo > 0; stevilo /= 2) {
resitev += stevilo % 2;
}
}
cout << resitev;
return 0;
}
Naši naključni podatki so predstavljeni v obliki tabele števil. Podobno kot pri 3. nalogi moramo
pretvarjati med različnimi številskimi zapisi, a moramo v tem primeru pretvoriti v dvojiški zapis
več kot le eno število, natančneje 1000 števil. Potrebujemo torej zanko, s katero se bomo
sprehodili po tabeli in vsako število pretvorili v dvojiški zapis. Glede na to, da ne vemo, koliko
mest ima določeno število, ga bomo delili z 2, dokler ne postane njegova vrednost enaka 0 oz.
dokler je njegova vrednost večja od 0.
for(; stevilo > 0; stevilo /= 2)
Da pa število pretvorimo v dvojiški številski zapis in preštejemo vse enice v tem zapisu,
moramo, poleg deljenja števila z 2 računati še ostanek pri deljenju števila z 2 ter preveriti, ali
je ta ostanek enak 1.
ostanek = stevilo % 2;
if(ostanek == 1) {
resitev++;
}
Namesto tega pa lahko, kot smo prikazali v naši rešitvi, samo seštevamo vse števke binarnega
zapisa; sestavljen je namreč zgolj iz ničel in enic.
resitev += stevilo % 2;
3.3.7 Analiza besedil glede na iskano besedo
Zgodba
Problem sedme naloge se glasi: »Ugotovljena koda ti je priskrbela dostop do dokumentov, ki ti
bodo v nadaljevanju pomagali rešiti napade na sistem. Opravi analizo teh dokumentov in
preveri, katera beseda po vrsti je iskana beseda.«
28
Podana sta primera:
• V spodnjem besedilu iščemo besedo omrežja.
Hekerji so skupina računalniških strokovnjakov, ki se ukvarjajo z vdori oziroma
nepooblaščenimi dostopi v računalniška omrežja ter z rušenjem, njihovim
onemogočanjem ali preizkušanjem varnostnih sistemov.
Beseda omrežja se nahaja na 16. mestu.
• V spodnjem besedilu iščemo besedo izziv.
To počnejo iz različnih vzrokov. Za nekatere je poglaviten zaslužek ali pridobitev
zaupnih informacij, drugi pa to počnejo za zabavo in iščejo pomanjkljivosti v
varnostnem sistemu. Nekaterim to predstavlja tudi intelektualni izziv in preizkušanje
različnih možnosti v zvezi z novimi tehnologijami.
Beseda izziv se nahaja na 32. mestu.
Učni cilji
Pri tej nalogi utrjujemo pogojne stavke, zanke, nize in štetje.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
string iskana = "<naključna beseda>";
int st_mest;
int resitev = 0;
st_mest = podatki.find(iskana);
// Štetje besed
for (int i = 0; i < st_mest; i++) {
if(podatki[i] == ' ') {
resitev++;
}
}
resitev++;
cout << resitev;
return 0;
}
Nalogo si lahko olajšamo z metodo find(), ki v nizu išče poljubni podniz.
st_mest = podatki.find(iskana);
29
V primeru, da se iskani podniz iskana nahaja v nizu podatki, nam metoda find() vrne indeks
prvega znaka besede iskana. Vendar nas naloga ne sprašuje po zaporednem indeksu ali mestu
začetka te besede, pač pa po tem, katera beseda po vrsti je beseda iskana. V ta namen je potrebno
prešteti vse presledke do indeksa, kjer se ta beseda nahaja, presledki namreč opredeljujejo
mesto, kjer se ena beseda konča in druga začne.
3.3.8 Analiza besedil glede na dolžino besed
Zgodba
Osma naloga na kratko pravi: »Opravi še dodatno analizo besedila glede na dolžino besed« in
v nadaljevanju za uporabnika izbere eno naključno število, uporabnik pa mora prešteti, koliko
besed ima enako dolžino oziroma število črk, kot je vrednost tega števila.
Podana sta primera:
• Preštej besede, ki so zgrajene iz 7 znakov.
Hekerji so skupina računalniških strokovnjakov, ki se ukvarjajo z vdori oziroma
nepooblaščenimi dostopi v računalniška omrežja ter z rušenjem, njihovim
onemogočanjem ali preizkušanjem varnostnih sistemov.
Besed, ki so sestavljene iz sedmih znakov, je 5.
• Preštej besede, ki so zgrajene iz 2 znakov.
To počnejo iz različnih vzrokov. Za nekatere je poglaviten zaslužek ali pridobitev
zaupnih informacij, drugi pa to počnejo za zabavo in iščejo pomanjkljivosti v
varnostnem sistemu. Nekaterim to predstavlja tudi intelektualni izziv in preizkušanje
različnih možnosti v zvezi z novimi tehnologijami.
Besed, ki so sestavljene iz dveh znakov, je 10.
Učni cilji
Znanja, ki jih želimo utrjevati pri tej nalogi, so pogojni stavki, zanke, nizi in koncept štetja z
vmesno ponastavitvijo števca ob zagotavljanju določenega pogoja.
30
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
int st_znakov = <naključno število>;
int dolzina = podatki.length();
int resitev = 0, beseda = 0;
for(int i = 0; i <dolzina; i++) {
// Konec besede
if(podatki[i] == ' ') {
//Ali je beseda ustrezno dolga?
if (beseda == st_znakov) {
resitev++;
}
beseda = 0;
}
// Če še nismo na koncu besede
else {
beseda++;
}
}
//Ali je morda ustrezno dolga beseda zadnja, ki na koncu nima
presledka?
if (beseda == st_znakov) {
resitev++;
}
cout << resitev;
return 0;
}
Ključno pri tej nalogi je ugotoviti, da je potrebno šteti tako število znakov v posamezni besedi,
kot tudi število besed, ki ustrezajo določeni dolžini. Z zanko moramo torej šteti število črk v
besedi. Pri prejšnjih nalogah smo že ugotovili, da si lahko pri takšnih izzivih pomagamo z
iskanjem presledkov; ti namreč določajo zaključek ene besede in začetek druge. Vendar pa
moramo pri tej nalogi poleg iskanja presledkov, vsakič ko presledek najdemo, preveriti še, ali
je število znakov v tistem trenutku enako podanemu številu znakov dolžine, ki je podano v
nalogi. Če je tako, moramo povečati naš števec resitev, ki je namenjen štetju besed ustrezne
dolžine. V vsakem primeru pa moramo, vedno ko najdemo presledek, ponastaviti števec beseda,
ki služi za štetje znakov v besedi, na 0, saj se bomo v naslednji ponovitvi zanke nahajali že na
začetku naslednje besede. Seveda pa ne smemo pozabiti na to, da se zadnja beseda ne konča s
presledkom in jo moramo obravnavati kot poseben primer.
31
3.3.9 Napad na ključe za podpisovanje certifikatov
Zgodba
Deveta naloga: »Napadeni so bili ključi za podpisovanje certifikatov. Skriti so v številkah, ki se
izpisujejo v obliki tabele dimenzij 1000 x 10. Obnoviš jih lahko tako, da za vsako vrstico
izračunaš razliko med največjim in najmanjšim številom. Kolikšna je vsota teh razlik?«
Podani so primeri:
• {23, 144, 123, 64, 33, 356, 243, 75}: razlika števil 23 in 356 je 333
• {245, 235, 123, 34, 567, 234, 43, 21, 432}: razlika števil 21 in 567 je 546
• {237, 233, 432, 43, 65, 14, 456, 674, 123, 456, 432}: razlika števil 14 in 674 je 660.
Učni cilji
Koncepti, ki jih želimo utrditi v tej nalogi, so gnezdene zanke, dvodimenzionalne tabele ter
iskanje največjega in najmanjšega elementa.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int podatki[][10] = <naključni podatki>;
int dolzina = 1000;
int resitev = 0;
int najvecji, najmanjsi;
for(int i = 0; i < dolzina; i++) {
najvecji = 0;
najmanjsi = 1000;
for(int j = 0; j < 10; j++) {
// Iskanje najvecjega v vrsti
if (podatki[i][j] > najvecji) {
najvecji = podatki[i][j];
}
// Iskanje najmanjskega v vrsti
if (podatki[i][j] < najmanjsi) {
najmanjsi = podatki[i][j];
}
}
resitev += (najvecji - najmanjsi);
}
cout << resitev << endl;
return 0;
}
32
Naši naključni podatki so dvodimenzionalna tabela celih števil. Morali bomo pregledati vrstice
te dvodimenzionalne tabele in poiskati največji ter najmanjši element v posamezni vrstici.
Ugotoviti je treba, da je zunanja zanka tista, ki določa vrstice in notranja zanka tista, ki določa
elemente v posamezni vrstici. Iz tega razloga moramo iskati največji in najmanjši element
znotraj notranje zanke, nato pa pred prehodom v naslednjo vrstico (nova ponovitev zunanje
zanke) izračunati razliko med najdenima največjim in najmanjšim elementom vrstice ter ju
prištevati v spremenljivko resitev.
3.3.10 Napad na pomnilnik
Zgodba
Pri deseti nalogi imamo podan naslednji problem: «Hekerji so napadli naš pomnilnik in
ponastavili vse spremenljivke na 0. Spremenljivke so poimenovane po zadnjih petih črkah
angleške abecede (v, w, x, y, z). V treh tabelah se nahaja po 1000 potrebnih podatkov, da
spremenljivke vrneš na začetne vrednosti. V prvi tabeli se nahaja ime spremenljivke, ki jo moraš
spremeniti. V drugi tabeli se nahaja podatek o tem, ali moraš spremenljivko povečati (P) ali
zmanjšati (Z) in v tretji tabeli podatek, za koliko se mora spremenljivka iz druge tabele
povečati/zmanjšati. Koliko znaša največja vrednost spremenljivke?«
Podan je tudi naslednji primer:
{w, v, x, x}
{P, P, Z, P}
{5, 1, 10, 20}.
Spremenljivka w se poveča za 5 (w = 5).
Spremenljivka v se poveča za 1 (v = 1).
Spremenljivka x se zmanjša za 10 (v = –10).
Spremenljivka x se poveča za 20 (v = 10).
33
Učni cilji
Koncepti, ki jih želimo utrditi v tej nalogi, so odločitveni stavki, zanke in tabele.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int spr[] = <naključni podatki>;
int PZ[] = <naključni podatki>;
int za_koliko[] = <naključni podatki>;
int v = 0, w = 0, x = 0, y = 0, z = 0;
int dolzina = 1000;
int resitev, spre;
for(int i = 0; i < dolzina; i++) {
if(PZ[i] == 'P') {
if (spr[i] == 'v') {
v += za_koliko[i];
}
else if (spr[i] == 'w') {
w += za_koliko[i];
}
else if (spr[i] == 'x') {
x += za_koliko[i];
}
else if (spr[i] == 'y') {
y += za_koliko[i];
}
else {
z += za_koliko[i];
}
}
else {
if (spr[i] == 'v') {
v -= za_koliko[i];
}
else if (spr[i] == 'w') {
w -= za_koliko[i];
}
else if (spr[i] == 'x') {
x -= za_koliko[i];
}
else if (spr[i] == 'y') {
y -= za_koliko[i];
}
else {
z -= za_koliko[i];
}
}
}
resitev = max(v, w);
resitev = max(resitev, x);
resitev = max(resitev, z);
resitev = max(resitev, z);
cout << resitev;
34
return 0;
}
V tej nalogi imamo podane tri različne tabele, po katerih moramo z zanko pregledati posamezen
istoležni element, nato pa ukrepati v skladu z navodili naloge, in sicer preveriti, ali se na nekem
določenem indeksu v prvi tabeli nahaja črka P in v trem primeru povečati ustrezno
spremenljivko, katere ime dobimo na istem indeksu druge tabele, za vrednost, ki pa jo dobimo
na istem indeksu tretje tabele. In podobno ukrepati, tj. zmanjšati ustrezno spremenljivko, če se
v prvi tabeli nahaja črka Z. Ko tabele pregledamo, pa moramo glede na navodila naloge poiskati
še največjo vrednost spremenljivke. To lahko opravimo s pomočjo odločitvenih stavkov, ali pa
s pomočjo metode max(), ki vrne vrednost večjega izmed dveh danih parametrov.
3.3.11 Pošiljanje sporočila guvernerju
Zgodba
Pri enajstem problemu bomo kodirali sporočila guvernerju: »Uspelo ti je rešiti prvih deset
napadov, zato moraš to sporočiti guvernerju za državno varnost, vendar pa moraš to storiti
tako, da sporočila ne bodo prestregli hekerji, ki nas napadajo. Edina možnost za varno
pošiljanje je, da sporočilo zakodiraš in ga pošlješ zakodiranega. Izdelaj tri funkcije:
• L(sporocilo, n); – ta funkcija bo prestavila prvih n znakov na konec niza
• D(sporocilo, n); – ta funkcija bo prestavila zadnjih n znakov na začetek niza
• Z(sporocilo, znak1, znak2); – ta funkcija bo znak1 zamenjala v znak2 in znak2
zamenjala v znak1.
Kakšno je zakodirano sporočilo?«
Podani so naslednji primeri:
Sporočilo, ki ga želiš poslati: prvihdesetnapadovjepremaganih
• L(sporocilo, 2); – vihdesetnapadovjepremaganihpr
• Z(sporocilo, 'n', 'd'); – vihnesetdapanovjepremagadihpr
• D(sporocilo, 5); – dihprvihnesetdapanovjepremaga
35
Učni cilji
Koncept, ki ga želimo utrditi pri tej nalogi, so predvsem funkcije.
Predvidena rešitev
#include <iostream>
using namespace std;
// Funkcija D(sporocilo, n): prestavimo zadnjih n znakov na začetek niza
string D(string sporocilo, int n) {
string kodiran = "";
int dolzina = sporocilo.length();
// Zadnjih n na začetek
for(int i = (dolzina - n); i < dolzina; i++) {
kodiran += sporocilo[i];
}
// Še preostali znaki
for(int i = 0; i < dolzina - n; i++) {
kodiran += sporocilo[i];
}
return kodiran;
}
// Funkcija L(sporocilo, n): prestavimo prvih n znakov na konec niza
string L(string sporocilo, int n) {
string kodiran = "";
int dolzina = sporocilo.length();
// Od n-tega znaka dalje
for(int i = n; i < dolzina; i++) {
kodiran += sporocilo[i];
}
// Prvih n na konec
for(int i = 0; i < n; i++) {
kodiran += sporocilo[i];
}
return kodiran;
}
string Z(string sporocilo, char crka1, char crka2) {
string kodiran = "";
int dolzina = sporocilo.length();
for(int i = 0; i < dolzina; i++) {
if (sporocilo[i] == crka1) {
kodiran += crka2;
}
else if (sporocilo[i] == crka2) {
kodiran += crka1;
}
else {
kodiran += sporocilo[i];
}
}
return kodiran;
}
int main() {
36
string sporocilo = "<naključni podatki>";
<naključni podatki>
cout << sporocilo << endl;
return 0;
}
Zapisati želimo tri funkcije, ki zakodirajo neko naključno besedilo. Prva funkcija D(sporocilo,
n) mora prestaviti zadnjih n znakov na začetek niza sporocilo. Potrebno je ustvariti prazen niz
kodiran, v katerega bomo zlagali znake tako, kot zahteva navodilo. S prvo zanko bomo torej šli
čez zadnjih n znakov
for(int i = (dolzina - n); i < dolzina; i++)
in te znake enega za drugim prenašali v niz kodiran.
kodiran += sporocilo[i];
Nato pa v spremenljivko kodiran po vrsti od začetka do n-tega znaka niza sporocilo prenesemo
še preostale znake.
for(int i = 0; i < dolzina - n; i++) {
kodiran += sporocilo[i];
}
Z drugo funkcijo L(sporocilo, n) želimo prenesti prvih n znakov na konec niza. Ponovno
potrebujemo prazen niz kodiran ter eno zanko, s katero po vrsti, enega za drugim, v
spremenljivko kodiran prenašamo znake sporočila, od n-tega do zadnjega.
for(int i = n; i < dolzina; i++) {
kodiran += sporocilo[i];
}
Nato pa po analogiji v kodiran z drugo zanko prenesemo vseh prvih n znakov.
for(int i = 0; i < n; i++) {
kodiran += sporocilo[i];
}
Ideja tretje funkcije je nekoliko drugačna od prvih dveh, z njo želimo namreč zamenjati vse
znake crka1 z znakom crka2 in obratno. Pomembno pri tem je, da to naredimo znotraj iste
zanke, saj sicer v drugem prehodu čez sporocilo ne bi več vedeli, kateri znaki so že zamenjane
crke2, katere pa je še potrebno zamenjati v crka1. Torej potrebujemo samo en prazen niz
37
kodiran in eno zanko, s katero se sprehodimo čez niz sporocilo in preverjamo, ali je posamezni
znak enak znaku crka1 ter v tem primeru v niz kodiran vstavimo znak crka2.
if (sporocilo[i] == crka1) {
kodiran += crka2;
}
Nato preverimo še, ali je posamezni znak enak znaku crka2 in v tem primeru v niz kodiran
vstavimo znak crka1.
else if (sporocilo[i] == crka2) {
kodiran += crka1;
}
Če ugotovimo, da znak ni enak niti znaku znak1 niti znaku znak2, ga le prenesemo v niz
kodiran.
else {
kodiran += sporocilo[i];
}
3.3.12 Lokacije državnih skrivališč
Zgodba
V dvanajsti nalogi bomo iskali znake X: »Hekerji so v bazi s podatki o lokacijah državnih
skrivališč izbrisali nekatere koordinate in jih nadomestili z znakom X. Baza podatkov je
oblikovana v obliki tabele velikosti 200 x 50. Poišči vse izbrisane koordinate in seštej vsa mesta
v tabeli, na katerih se nahaja izbrisan podatek. Mesto določiš kot seštevek zaporedne številke
vrstice in stolpca. Koliko znaša seštevek vseh mest manjkajočih podatkov?«
Podan je primer:
64738921
563X7836
73925174
6498X837
5361837X
38
Mesta manjkajočih podatkov so 6, 9 in 13. Skupni seštevek je torej 28.
Učni cilji
Koncept, ki ga želimo utrditi v tej nalogi, so dvodimenzionalne tabele, še posebej prehod čez
njene elemente, delo z indeksi dvodimenzionalne tabele in iskanje elementa znotraj takšne
tabele.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
char podatki[][50] = <naključni podatki>;
int st_vrstic = 200;
int st_elementov = 50;
int resitev = 0;
int stevilo;
for(int i = 0 ; i < st_vrstic; i++) {
for (int j = 0; j < st_elementov; j++) {
if (podatki[i][j] == 'X') {
resitev += ((i + 1) + (j + 1));
}
}
}
cout << resitev << endl;
return 0;
}
Prva stvar, ki jo moramo vedeti pri delu z dvodimenzionalnimi tabelami, je, da potrebujemo
gnezdeno zanko in da z zunanjo zanko nadziramo vrstice ter z notranjo zanko elemente znotraj
neke vrstice.
for(int i = 0 ; i < st_vrstic; i++) {
for (int j = 0; j < st_elementov; j++) {
Nato pa za iskanje znaka X uporabimo navadno iskanje, s katerim preprosto pregledamo vse
elemente tabele in za vsak element preverimo, ali je enak črki X.
if (podatki[i][j] == 'X')
Če je, pogledamo, na katerem mestu se nahaja (ne v indeksu) in ti dve mesti (vodoravno in
horizontalno) prištejemo v spremenljivko resitev.
resitev += ((i + 1) + (j + 1));
39
3.3.13 Kodiranje po metodi RLE
Zgodba
V trinajsti nalogi želimo kodirati in dekodirati dolžino po RLE-metodi: »Naslednji trik, ki so se
ga poslužili hekerji, je uporaba kodiranja in dekodiranja dolžin – RLE (angl. Run-Length
Encode and Decode). Gre za preprosto obliko stiskanja podatkov, kjer ponavljajoča se
zaporedja črk nadomestimo z zapisom para, ki vsebuje število znakov v zaporedju in znak.
Kakšno je zakodirano sporočilo?«
Podana sta primera:
• www wwwwwwwwwbwwwwwwwwwwwwbbb wwwwwwwwwwwwwwwwwwww
wwwwb lahko kodiramo z 3w1 9w1b12w3b1 24w1b
• aabc ccdeeee lahko kodiramo z 2a1b1c1 2c1d4e
Učni cilji
Koncept te naloge je primerjanje dveh znakov v nizu in s tem štetje enakih zaporednih znakov
niza.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatki>";
int dolzina = podatki.length();
char znak = podatki[0];
int stevec = 0;
for(int i = 0; i < dolzina; i++) {
if(znak == podatki[i]) {
stevec++;
}
else {
cout << stevec << znak;
// Nastavimo na nov znak
znak = podatki[i];
stevec = 1;
}
}
cout << stevec << znak;
return 0;
}
40
V tej nalogi moramo preveriti, ali je nek znak v nizu enak enemu ali več svojim predhodnikom.
Z zanko torej pregledamo niz podatki in si v spremenljivko znak vedno zapomnimo prvi znak,
ki je različen od prejšnjega. Na začetku je to kar prvi znak v nizu podatki. Če je torej tekoči
znak v nizu podatki enak tistemu v spremenljivki znak,
if(znak == podatki[i])
potem le povečamo števec, saj smo našli znak, ki je enak svojemu predhodniku ali več svojim
predhodnikom. Sicer pa smo očitno našli znak, ki je različen od svojega predhodnika, zato
moramo, preden si zapomnimo, za kateri znak gre, izpisati število ponovitev prejšnjega in si
zapomniti tudi, kateri znak se je ponavljal. Šele potem si s pomočjo spremenljivke znak
zapomnimo ta nov znak in na vrednost 1 ponastavimo vrednost števca, saj želimo z novim
najdenim znakom začeti šteti od začetka.
else {
cout << stevec << znak;
znak = podatki[i];
stevec = 1;
}
Seveda pa ne smemo na koncu pozabiti izpisati tudi zadnjega znaka in števila njegovih
ponovitev.
cout << stevec << znak;
3.3.14 Napad na telefonske številke
Zgodba
Štirinajsti napad je napad na telefonske številke: »Ogrožen je telefonski imenik oddelka za
državno varnost s 600 telefonskimi številkami. Hekerji so napadli podatke o telefonskih
številkah v sistemu, tako da so nekaterim številkam dodali nepotrebna ločila (oklepaje, / in -)
in začetno mednarodno klicno kodo (npr. +386 ali 00386). Zaradi teh dodatkov v številkah je
onemogočeno neposredno klicanje, zato jih moraš ustrezno očistiti, kar pomeni, da moraš iz
številk odstraniti vsa ločila in mednarodno klicno kodo, če je prisotna. Mednarodno klicno kodo
prepoznaš po tem, da se začne bodisi z znakom +, bodisi z števili 00. V koliko primerih se v
telefonskih številkah pojavljajo številke 3, 8 ali 6?«
41
Primeri:
• +386(051)567-345
• 051-567-345
• 00386051567345
• 051/567345
Vse zgornje številke se morajo pretvoriti v številko: 051567345.
Učni cilji
Želimo utrditi delo s tabelami nizov in iskanje določenih znakov v teh nizih, pri čemer moramo
ugotoviti, da moramo ponovno uporabiti dvodimenzionalne tabele.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki[] = <naključni podatki>;
int dolzina = 600;
int resitev = 0;
int j;
for(int i = 0; i < dolzina; i++) {
if (podatki[i][0] == '+') {
j = 4;
}
else if (podatki[i][0] == '0' && podatki[i][1] == '0') {
j = 5;
}
else {
j = 0;
}
for(; j < podatki[i].length(); j++) {
if(podatki[i][j] == '3' || podatki[i][j] == '8' ||
podatki[i][j] == '6') {
resitev++;
}
}
}
cout << resitev;
return 0;
}
Naloga pravi, da je potrebno iz telefonskih številk odstraniti vse znake, ki niso števila, in
mednarodne klicne kode. Mednarodne klicne kode se vedno začnejo z 00 ali z znakom +, zato
je potrebno najprej preveriti, ali se posamezna številka začne z znakom +.
42
if (podatki[i][0] == '+')
Če se začne s tem znakom, pomeni, da mednarodna klicna koda poleg znaka + vsebuje še tri
druga števila in se tako telefonska številka začne šele s petim znakom, tj. četrtim indeksom,
zato števec j, ki nadzira prehod čez posamezne znake znotraj telefonske številke, nastavimo na
vrednost 4.
Če pa se telefonska številka ne začne z znakom +, pa se mogoče začne s števili 00, ki prav tako
določata začetek mednarodne klicne kode.
else if (podatki[i][0] == '0' && podatki[i][1] == '0')
V tem primeru tema ničlama prav tako sledijo tri druge številke, ki so del te kode, zato se prava
telefonska števila začne z znakom na šestem mestu, tj.. petem indeksu, zato števec j nastavimo
na vrednost 5.
Sicer (če se številka ne začne niti z znakom + niti s števili 00) pa pomeni, da telefonska številka
nima mednarodne klicne kode, zato števec j nastavimo na vrednost 0.
Sledi zanka, s katero bomo pregledali celotno telefonsko številko (od j do konca številke).
for(; j < podatki[i].length(); j++)
Tukaj pa naloga od nas želi, da zanemarimo ali odstranimo vse znake, ki niso števila, in
preverimo, koliko števk znotraj telefonske številke je enakih 3, 8 ali 6. Z malo razmisleka
ugotovimo, da v tem primeru sploh ni treba razmišljati o odvečnih znakih, ampak le preverimo,
ali je posamezen znak enak zgornjim trem števkam.
if(podatki[i][j] == '3' || podatki[i][j] == '8' || podatki[i][j] == '6')
Ter v tem primeru povečamo števec resitev, s katerim štejemo te števke.
3.3.15 Izbris besed v zaupnih dokumentih
Zgodba
Pri petnajsti nalogi se bomo ukvarjali s prepoznavanjem izbrisanih besed v besedilu: »Hekerji
so izbrisali nekatere besede v zaupnih dokumentih oddelka za varnost. Na zaslonu se prikažejo
43
te besede skupaj z besedami, ki niso bile izbrisane in se prikazujejo le, da ti ponagajajo. Za
posamezno besedo moraš ugotoviti, ali je bila izbrisana ali ne. Določena beseda je bila
izbrisana, če se v besedilu nikoli ne pojavi. Preštej vse ponovitve dane besede. Kolikokrat se
beseda ponovi?«
Primer:
Kolikokrat se v sporočilu fgjktbugcncnbrmpqxbugjkupcnmbnegthbugwbtyzjgtuldlerpgpobug
pojavi beseda bug?
Beseda bug se ponovi štirikrat.
Učni cilji
Cilj te naloge je iskanje določenega podniza znotraj drugega niza in štetje teh ponovitev.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string sporocilo = "<naključni podatki>";
string sporocilo = "<naključna beseda>";
int dolzina = sporocilo.length();
int resitev = 0;
int najdena;
for(int i = 0 ; i < dolzina; i++) {
najdena = sporocilo.find(iskana, i);
if(najdena == -1) // Je ni našel {
i = dolzina;
}
else {
i = najdena + 1;
resitev++;
}
}
cout << resitev << endl;
return 0;
}
Cilj te naloge je, kot že v veliko prejšnjih nalogah, štetje, vendar v tem primeru štetje pojavitev
določenega podniza, ne le posameznega znaka. V ta namen lahko uporabimo metodo find() in
z njo od i-tega indeksa dalje znotraj niza sporocilo poiščemo morebitne pojavitve niza iskana.
najdena = sporocilo.find(iskana, i);
44
Če se bo pojavil kakšen tak podniz, nam bo metoda find() v spremenljivko najdena vrnila indeks
prvega znaka najdenega niza. Če takšnega podniza ne bo, pa nam bo vrnila vrednost –1. Če bo
torej vrednost najdena enaka –1, to pomeni, da znotraj niza sporocilo ni podniza iskana.
if(najdena == -1)
In zato z iskanjem zaključimo.
i = dolzina;
Sicer pa smo našli en takšen podniz, kar pomeni, da povečamo števec resitev in v naslednji
ponovitvi zanke iščemo nov takšen podniz od tega podniza naprej.
i = najdena + 1;
3.3.16 Dodane besede v zaupnih dokumentih
Zgodba
Pri šestnajsti nalogi se bomo ukvarjali s prepoznavanjem dodanih besed: »Da bi hekerji v
zaupnih dokumentih povzročili še večjo zmedo, so vanje dodali besede. Te so povzročile, da so
dokumenti postali neuporabni in jih je zato potrebno najti ter izbrisati. Dodane besede lahko
prepoznaš po ponovitvah črk. Natančneje, dodane besede so tiste, v katerih se neka črka (vsaj
ena) ponovi večkrat. Poišči te dodane besede, da bodo dokumenti ponovno uporabni. Katero
besedilo izmed 1000 besed je dodano?«
Primer:
jekorija, program, grožnja, napad, računalnik, varnost, vdor, hekerji, električni, mrk
Dodano besedilo: jekorijaprogramnapadračunalnikhekerjielektrični
Učni cilji
Cilj te naloge je delo s tabelo nizov, iskanje črk znotraj teh nizov in štetjem teh ponovitev črk.
45
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki[] = <naključni podatki>;
int dolzina = 1000;
int dolzina_besede;
int stevec;
for(int i = 0; i < dolzina; i++ {
dolzina_besede = podatki[i].length();
// Posamezna beseda
for(int j = 0; j < dolzina_besede; j++) {
// Primerja črko z vsemi drugimi črkami v besedi
stevec = 0;
for (int k = 0; k < dolzina_besede; k++) {
if(podatki[i][j] == podatki[i][k]) {
stevec++;
}
}
// Če se je neka črka ponovila več kot enkrat
if(stevec > 1) {
cout << podatki[i];
break;
}
}
}
return 0;
}
S prvo zanko bomo pregledali vse besede v tabeli. Z drugima dvema zankama pa bomo vsako
črko znotraj besede primerjali z vsemi drugimi črkami ter povečevali spremenljivko stevec, ko
bosta dve črki enaki. Ker bomo v nekem trenutku vsako črko primerjali tudi samo s sabo,
moramo na koncu, da bi videli, ali se črka pojavi večkrat, preveriti, ali je stevec večji od 1 in v
tem primeru to besedo izpisati.
3.3.17 Leksikografsko urejanje besed
Zgodba
Pri sedemnajsti nalogi se bomo ukvarjali z leksikografskim urejanjem besed: »Hekerji še vedno
poskušajo napasti zaupne dokumente, zato so v njih pomešali vseh 300 besed. Poskusi jih
obnoviti tako, da bodo besede ponovno urejene leksikografsko od a do z.«
46
Primer:
hekerji vdor zaupno napadalci program varnost električni zmeda mrk napad
Urejeno: električni hekerji mrk napad napadalci program varnost vdor zaupno zmeda
Učni cilji
Namen te naloge je urejanje elementov v tabeli.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki[] = <naključni podatki>;
int dolzina = 300;
string trenutna;
for(int i = 0; i < dolzina; i++) {
for(int j = dolzina - 1; j > i; j--) {
if(podatki[j - 1] > podatki[j]){
trenutna = podatki[j - 1];
podatki[j - 1] = podatki[j];
podatki[j] = trenutna;
}
}
}
// Izpis
for(int i = 0; i < dolzina; i++) {
cout << podatki[i] << " ";
}
return 0;
}
Da bi besede uredili po abecednem vrstnem redu, bomo uporabili preprosto metodo urejanja,
mehurčkasto urejanje (angl. bubble sort). Metoda deluje tako, da zaporedoma zamenjuje
elemente v tabeli, ki se nahajajo na napačnem mestu, dokler niso urejeni vsi elementi v tabeli.
Pri vsem tem gre za to, da leksikografsko primerjamo dve sosednji besedi in ju, če nista
postavljeni v pravem vrstnem redu, zamenjamo.
if(podatki[j - 1] > podatki[j]){
trenutna = podatki[j - 1];
podatki[j - 1] = podatki[j];
podatki[j] = trenutna;
}
Ker ta vrsta urejanja deluje tako, da bo pri prvem prehodu največji oz. najmanjši element
(odvisno, ali urejamo padajoče ali naraščajoče) gotovo postavljen na pravem mestu, ni
47
potrebno, da z drugo zanko ponovno preverimo celotno tabelo. Tako lahko to zanko nekoliko
optimiziramo.
for(int j = dolzina - 1; j > i; j--)
3.3.18 Izbrisane črke
Zgodba
Osemnajsti problem: »Iz zaupnih dokumentov so bile izbrisane nekatere črke. Da boš lahko
dokumente obnovil in jih vrnil v prvotno stanje, moraš ugotoviti, katere črke so bile izbrisane.
Sestavi funkcijo izbrisana (beseda, črka), ki bo kot parameter prejela besedo in črko ter
preverila, ali je bila ta črka izbrisana iz te besede ali ne. Če se v tej besedi pojavi črka, naj
funkcija izpiše indeks, v katerem se nahaja (če se črka pojavi večkrat, naj izpiše indeks prve
pojavitve), sicer pa naj izpiše –1.«
Primer:
izbrisana("hekerji", 'e'); izbrisana("vdor", 'a'); izbrisana("zaupno", 'p'); izbrisana("napadalci",
'r'); izbrisana("program", 'p'); izbrisana("varnost", 't'); izbrisana("električni", 't');
izbrisana("zmeda", 'k'); izbrisana("mrk", 'a'); izbrisana("napad", 'a');
Izpis: 1-13-1064-1-11
Učni cilji
Namen te naloge je utrjevanje znanja za delo s funkcijami in iskanje znakov v nizu.
Predvidena rešitev
#include <iostream>
using namespace std;
void izbrisana(string beseda, char crka) {
int indeks = -1;
for(int i = 0; i < beseda.length(); i++) {
if(beseda[i] == crka) {
indeks = i;
break;
}
}
cout << indeks;
48
}
int main() {
<naključni podatki>;
return 0;
}
Sestaviti moramo funkcijo, ki bo v besedi poiskala neko črko in vrnila njen indeks. Potrebujemo
torej eno spremenljivko indeks, ki jo na začetku nastavimo na vrednost –1, saj naloga pravi, da
naj se v primeru, da se v besedi ne nahaja želena črka, izpiše vrednost –1. V nadaljevanju
funkcije bomo namreč s pomočjo zanke prešli čez vse črke besede in preverjali, ali se ta želena
črka nahaja v besedi; če se, bomo spremenljivko indeks ponastavili na vrednost i, ki predstavlja
trenutni indeks v besedi. In ker naloga določa, da je dovolj, da najdemo samo eno takšno
pojavitev črke, bomo, ko jo najdemo, z ukazom break zanko zaključili.
if(beseda[i] == crka) {
indeks = i;
break;
}
Izven zanke bomo nato izpisali spremenljivko indeks, v kateri se nahaja indeks pojavitve črke,
v primeru, da smo jo seveda sploh našli. Če pa črke v besedi nismo našli, se odločitveni stavek
nikoli ni izvedel in posledično vrednost spremenljivke indeks nikoli ni bila spremenjena, zato
ostaja enaka –1.
3.3.19 Napad na števila
Zgodba
Devetnajsta naloga se glasi: »Hekerji so napadli tudi števila v sistemu. Ugotovi, katera števila
so ostala nespremenjena in katera števila so hekerji ''pokvarili''. Število je nespremenjeno, če
ustreza pogoju: vsako drugo števko podvojimo, začenši s prvo števko z desne. Če je to
podvojeno število večje od 9, potem število zmanjšamo za 9. Nato dobljene številke seštejemo
in če je vsota deljiva z 10, potem je to število nespremenjeno. Koliko števil je nespremenjenih?«
Podana sta dva primera:
• 4539148803436467:
Vsaka druga števka: 4_3_ 1_8_ 0_4_ 6_6_
Število s podvojenim števkam: 8569247803833437
49
Vsota števk: 8 + 5 + 6 + 9 + 2 + 4 + 7 + 8 + 0 + 3 + 8 + 3 + 3 + 4 + 3 + 7 = 80
80 je deljivo z 10, zato je število 4539148803436467 nespremenjeno.
• 8273123273520569:
Vsaka druga števka: 8_7_ 1_3_ 7_5_ 0_6_
Število s podvojenim števkam: 7253226253120539
Vsota števk: 7 + 2 + 5 + 3 + 2 + 2 + 6 + 2 + 5 + 3 + 1 + 2 + 0 + 5 + 3 + 9 = 57
57 ni deljivo z 10, zato število 8273123273520569 ni nespremenjeno.
Učni cilji
Namen te naloge je urjenje odločitvenih stavkov, sestavljanje ustreznih pogojev in razstavljanje
števil na števke.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int podatki[] = <naključni podatki>;
int dolzina = 1000;
int stevilo;
int stevka, j, vsota;
int resitev = 0;
for (int i = 0; i < dolzina; i++) {
stevilo = podatki[i];
j = 0;
vsota = 0;
while(stevilo > 0) {
stevka = stevilo % 10;
if(j % 2 == 0) {
stevka = 2 * stevka;
if(stevka > 9) {
stevka = stevka - 9;
}
}
vsota += stevka;
stevilo = stevilo / 10;
j++;
}
if(vsota % 10 == 0) {
resitev++;
}
}
cout << resitev<< endl;
return 0;
}
50
Imamo tabelo števil, za katere želimo ugotoviti, ali so spremenjene ali ne. Najprej moramo
ugotoviti, kako razbiti število na števke. To storimo tako, da gledamo ostanek pri deljenju s
številom 10 in to počnemo, dokler je število večje od 0.
while(stevilo > 0) {
stevka = stevilo % 10;
Seveda pa moramo pred vsako ponovitvijo zanke najprej odstraniti zadnje števke, saj smo jo že
upoštevali.
stevilo = stevilo / 10;
Ko imamo dobljeno števko, pa moramo podvojiti vsako drugo števko, torej moramo preveriti,
ali se nahajamo na sodem ali lihem mestu. Če se nahajamo na sodem mestu, to števko
pomnožimo z 2.
stevka = 2 * stevka;
Če je dobljena vrednost večja od 9, pa to vrednost zmanjšamo za 9.
if(stevka > 9) {
stevka = stevka - 9;
}
Nato pa v vsakem primeru (če smo bodisi na sodem mestu bodisi na lihem) števko prištejemo
v spremenljivko vsota, ki je namenjena izračunanju vsote števk glede na v nalogi podane
pogoje.
vsota += stevka;
Ko se izvajanje zanke konča, pomeni, da smo dobili vse števke in tudi rezultat. Sedaj moramo
samo še preveriti, ali je vrednost spremenljivke vsota deljiva z 10. To preverimo tako, da
izračunamo ostanek pri deljenju z 10; če je ostanek 0, je število deljivo z 10.
if(vsota % 10 == 0) {
resitev++;
}
V tem primeru povečamo spremenljivko resitev, saj smo našli eno nespremenjeno število.
51
3.3.20 Napad na identifikacijske številke dokazov
Zgodba
Dvajseta naloga se glasi: »Do sedaj si uspešno preprečil že veliko napadov, s tem pa si se tudi
zelo približal hekerjem in zbral ogromno dokaznega materiala proti njim. Hekerji to dobro
vedo, zato so napadli in spremenili identifikacijske številke, s katerimi so popisani ti dokazi.
Identifikacijska številka je bila pred napadom sestavljena skladno s formulo:
𝑥1 · 10 + 𝑥2 · 9 + 𝑥3 · 8 + 𝑥4 · 7 + 𝑥5 · 6 + 𝑥6 · 5 + 𝑥7 · 4 + 𝑥8 · 3 + 𝑥9 · 2 + 𝑥10 · 1,
in sicer tako, da je moral biti rezultat te formule deljiv s številom 11. Z naključnimi števili smo
generirali nova identifikacijska števila. Zapiši funkcijo ID(število), ki bo v primeru, da število
ustreza pravilu identifikacijskega števila, izpisalo 1, sicer pa 0. Katera od števil ustrezajo
pravilu in jih lahko uporabimo kot identifikacijska števila?«
Podana sta dva primera:
• 103598215088
3 · 10 + 5 · 9 + 9 · 8 + 8 · 7 + 2 · 6 + 1 · 5 + 5 · 4 + 0 · 3 + 8 · 2 + 8 · 1 = 264, kar
je deljivo z 11, zato lahko število uporabimo kot identifikacijsko številko, funkcija pa
bi vračala 1.
• 103598215088
1 · 6 + 3 · 5 + 4 · 4 + 2 · 3 + 6 · 2 + 7 · 1 = 62, kar ni deljivo z 11, zato števila ne
moremo uporabiti kot identifikacijsko številko, funkcija pa bi vračala 0.
V primeru ID(103598215088); ID(103598215088) bi bil torej naš rezultat 10.
Učni cilji
S to nalogo želimo utrjevati delo s funkcijami in razstavljanje števil na števke.
Predvidena rešitev
#include <iostream>
using namespace std;
void ID(int stevilo) {
int stevka;
int i = 1;
int vsota = 0;
while(stevilo > 0) {
stevka = stevilo % 10;
52
vsota += (stevka * i);
i++;
stevilo = stevilo / 10;
}
cout <<((vsota % 11 == 0));
}
int main() {
<naključni podatki>
return 0;
}
Sestaviti moramo funkcijo, ki bo prejela neko celo število, ga razcepila na števke, izračunala
vsoto glede na formulo
𝑥1 · 10 + 𝑥2 · 9 + 𝑥3 · 8 + 𝑥4 · 7 + 𝑥5 · 6 + 𝑥6 · 5 + 𝑥7 · 4 + 𝑥8 · 3 + 𝑥9 · 2 + 𝑥10 ∗ 1.
in izpisala 1, če je ta vsota deljiva z 11 in 0, če ni.
Število razcepimo na števke podobno kot pri prejšnji nalogi, le da tokrat v spremenljivko vsota
prištevamo zmnožek števke in tekočega mesta števke (ne indeksa).
vsota += (stevka * i);
Na koncu preverimo, ali je vsota deljiva z 11 in izpišemo 1 oz. 0.
cout <<((vsota % 11 == 0));
3.3.21 Branje zakodiranega sporočila
Zgodba
Enaindvajseti problem se nanaša na branje zakodiranega sporočila: «Ker si sistem uspešno rešil
pred prvimi dvajsetimi napadi, si od guvernerja za državno varnost prejel navodila za tvoje
nadaljnje ravnanje. Sporočilo si zaradi varnosti prejel šifrirano v obliki tabele 50 x 50. Na
ekranu se izpiše to sporočilo po vrsticah, brati pa ga moraš od zgoraj navzdol in iz desne proti
levi. Kakšno je sporočilo?«
53
Podan je primer:
'p', 'n', 's', 'p', 'r', 's'
'a', 'a', 'i', 'o', 'e', 'r'
'n', 'p', 's', 'l', 'š', 'e'
'i', 'a', 't', 'n', 'i', 'č'
'k', 'd', 'e', 'o', 't', 'n'
'a', 'i', 'm', 'č', 'i', 'o'
Sporočilo: panikanapadisistempolnočrešitisrečno
Učni cilji
Cilj naloge je iz dvodimenzionalne tabele prebrati element, ki se nahaja na ustreznem mestu.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int dolzina = 50;
char podatki[dolzina][dolzina] = <naključni podatki>;
char resitev[dolzina][dolzina];
for(int i = 0; i < dolzina; i++) {
for(int j = 0; j < dolzina; j++) {
resitev[j][i] = podatki[i][j];
}
}
// Izpis
for(int i = 0; i < dolzina; i++) {
for(int j = 0; j < dolzina; j++) {
cout << resitev[i][j];
}
}
return 0;
}
Imamo dvodimenzionalno tabelo, v kateri želimo zamenjati vrstice in stolpce. To pomeni, da
želimo, da bi se podatki, ki se nahajajo v stolpcu, nahajali v vrstici. V ta namen najprej
ustvarimo novo dvodimenzionalno tabelo resitev.
char resitev[dolzina][dolzina];
54
Nato se z gnezdeno zanko sprehodimo po posameznih vrsticah tabele in preslikavamo elemente
v vrstici tabele podatki v stolpec tabele resitev.
for(int i = 0; i < dolzina; i++) {
for(int j = 0; j < dolzina; j++) {
resitev[j][i] = podatki[i][j];
}
}
3.3.22 Določitev novih identifikacijskih števil
Zgodba
V dvaindvajseti nalogi želimo določiti nova identifikacijska števila: »Dokazom proti hekerjem
si generiral nove identifikacijske številke, vendar pa moraš zanje določiti tudi nova mesta
shranjevanja. Sistem shranjevanja mora biti določen tako, da ga določa njegova
identifikacijska številka. Določi novo mesto posameznim dokazom tako, da poiščeš največji
produkt petih zaporednih števk iz 1000 števk identifikacijskega števila. Kakšno je novo mesto
dokaza?«
Primer:
1027839564
Največji produkt petih zaporednih števk je 7560 (= 7 · 8 · 3 · 9 · 5).
Učni cilji
Ta naloga utrjuje znanje dela s tabelami in iskanje po tabeli.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int dolzina = 1000;
int podatki[] = <naključni podatki>;
int produkt;
int najvecji = 0;
for(int i = 0; i <= dolzina - 5; i++) {
produkt = 1;
for(int j = i; j < i + 5; j++) {
produkt *= podatki[j];
55
}
if (produkt > najvecji) {
najvecji = produkt;
}
}
cout << najvecji << endl;
return 0;
}
Iščemo največji produkt petih zaporednih števil. Z gnezdeno zanko bomo šli čez tabelo in v
vsaki ponovitvi množili pet sosednjih elementov. Pri tem moramo paziti, da z zunanjo zanko
ne gremo do konca tabele, pač pa se ustavimo, ko je do konca tabele manj kot pet elementov.
for(int i = 0; i <= dolzina - 5; i++)
Z notranjo zanko pa poskrbimo, da vsakič dobimo pet zaporednih elementov, ki jih zmnožimo.
for(int j = i; j < i + 5; j++) {
produkt *= podatki[j];
}
Ob koncu zunanje zanke še preverimo, ali je dobljeni zmnožek morda dosedanji največji
zmnožek petih sosednjih števil in če je, to vrednost priredimo spremenljivki najvecji.
if (produkt > najvecji) {
najvecji = produkt;
}
Na ta način bomo imeli na koncu v spremenljivki najvecji zagotovo največji produkt petih
zaporednih števil.
3.3.23 Napad na računske operacije
Zgodba
V triindvajseti nalogi bomo preverjali, ali so oklepaji postavljeni pravilno: »Hekerski napad je
tokrat prizadel računske operacije sistema, in sicer je napadel oklepaje. Pred napadom je
sistem znal uporabljati in računati z oklepaji, sedaj pa tega ne zmore več. Pomagaj mu, da bo
ob prebiranju uklepajev in zaklepajev ugotovil, ali jih je zadostno število. Pravilo pravi namreč,
da ni dovoljeno postavljati zaklepaja pred uklepajem. Pri tem pa lahko uporabljamo različne
oklepaje (, ), [, ], {, }, med katerimi ne ločujemo. Na katerem indeksu se nahaja prvi zaklepaj,
ki ne ustreza zgornjemu pogoju?«
56
Primer:
[()]{)[}(]{[](())]}[{}[)
Prvi napačen zaklepaj se nahaja na indeksu 18.
Učni cilji
Pri nalogi vadimo štetje različnih elementov v nizih.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki[] = "<naključni podatki>";
int dolzina = podatki.length();
int stevec_oklepajev = 0;
int resitev;
for(int i = 0; i < dolzina; i++) {
if(podatki[i] == '(' || podatki[i] == '{' || podatki[i] == '[') {
stevec_oklepajev++;
}
else {
stevec_oklepajev--;
}
if (stevec_oklepajev < 0) {
resitev = i;
break;
}
}
cout << resitev<< endl;
return 0;
}
Z zanko se sprehodimo po elementih niza in za vsak element preverimo, ali je morda enak
kakšnemu od uklepajev.
if(podatki[i] == '(' || podatki[i] == '{' || podatki[i] == '[')
Če je, povečamo stevec_oklepajev, saj smo ravnokar našli nov uklepaj. Sicer pa smo očitno
našli zaklepaj, zato moramo stevec_oklepajev zmanjšati, pravkar smo namreč zaključili en
oklepaj.
Nato moramo upoštevati pravilo, ki pravi, da ni dovoljeno postavljati zaklepaja pred uklepajem.
To pomeni, da zaklepajev ne sme biti več kot uklepajev (oklepajev mora biti več kot 0), sicer
zaključimo s pregledovanjem elementov niza, torej z zanko.
57
if (stevec_oklepajev < 0) {
resitev = i;
break;
}
3.3.24 Mapa Fibonacci
Zgodba
V štiriindvajseti nalogi bomo računali elemente Fibonaccijevega zaporedja: »Dosegel si velik
preboj in se zelo približal napadalcu. Prišel si do vsebine na napadalčevem računalniku, ki ti
lahko pomaga na poti do razkritja napadalcev in popolne preprečitve napada. Na
napadalčevem računalniku si naletel na mapa z datotekami z imeni 1, 1, 2, 3, 5, 8, 13, 21, 34
... Našel pa si tudi datoteko README, v kateri piše, da se napadalčev IP-naslov skriva v
<naključno število> datoteki. Kakšno je njeno ime?«
Primeri:
• Ime 7. datoteke je 13.
• Ime 9. datoteke je 34.
• Ime 10. datoteke je 55.
Učni cilji
Potrebno je ugotoviti, da gre za zaporedje, pri katerem imata prva dva člena vrednost 1 ter da
se nato vsak naslednji člen izračuna tako, da se sešteje prejšnja dva člena.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
int podatek = <naključni podatek>;
int zadnji = 1;
int predzadnji = 1;
int nov;
for (int i = 2; i < podatek; i++) {
nov = zadnji + predzadnji;
predzadnji = zadnji;
zadnji = nov;
}
cout << zadnji;
58
return 0;
}
Pri tej nalogi gre za to, da vedno znova računamo nov člen zaporedja tako, da seštejemo prejšnja
dva člena zaporedja ter nato spreminjamo ta dva člena z namenom, da bomo lahko v naslednjem
koraku ponovno izračunali nov člen.
nov = zadnji + predzadnji;
predzadnji = zadnji;
zadnji = nov;
Vse to izvajamo v zanki, ki gre po indeksih od 2 do podatek, tj. člen, ki ga računamo. Z
indeksom 2 začnemo, ker sta prva dva člena zaporedja že podana in ju ni potrebno računati.
for (int i = 2; i < podatek; i++)
3.3.25 Koordinate napadalcev
Zgodba
V zadnji nalogi bomo razkrili koordinate napadalca in tako ugotovili, kje se napadalec nahaja:
»Pridobil si napadalčev IP-naslov, iz katerega lahko pridobiš še koordinate njegovega
položaja. Poskusi jih ugotoviti. Po koordinatnem sistemu se lahko premikaš vedno le naprej
(N), lahko pa tudi zaviješ na levo (L) ali na desno (D). Začetna pozicija je vedno (0,0) v smeri
severa. Kakšne so koordinate napadalcev?«
Primer:
Navodilo "DNNLNL" pomeni:
• zavij desno,
• naprej dvakrat,
• zavij levo,
• naprej enkrat,
• zavij levo.
Končni položaj v tem primeru je (2,1).
59
Učni cilji
Ta naloga utrjuje sestavljanje pogojev in uporabo koordinatnega sistema.
Predvidena rešitev
#include <iostream>
using namespace std;
int main() {
string podatki = "<naključni podatek>";
int x = 0;
int y = 0;
char smer = 'S';
int dolzina = podatki.length();
for(int i = 0; i < dolzina; i++) {
if (podatki[i] == 'N') {
if(smer == 'S') {
y++;
}
else if(smer == 'J') {
y--;
}
else if(smer == 'V') {
x--;
}
else if(smer == 'Z') {
x++;
}
}
else if (podatki[i] == 'L') {
if(smer == 'S') {
smer = 'V';
}
else if(smer == 'V') {
smer = 'J';
}
else if(smer == 'J') {
smer = 'Z';
}
else if(smer == 'Z') {
smer = 'S';
}
}
else if (podatki[i] == 'D') {
if(smer == 'S') {
smer = 'Z';
}
else if(smer == 'Z') {
smer = 'J';
}
else if(smer == 'J')
{
smer = 'V';
}
else if(smer == 'V') {
smer = 'S';
}
60
}
}
cout << "(" << x << "," << y << ")" << endl;
return 0;
}
Pri tej nalogi bomo s pomočjo zanke brali naše ukaze za premikanje po koordinatnem sistemu.
Koordinatni sistem bomo realizirali s pomočjo spremenljivk x in y, ki bosta ponazarjali abscisno
in ordinatno os. Hkrati pa si bomo ob vsakem premiku zapomnili, v katero smer gledamo. To
bomo storili s pomočjo spremenljivke smer, ki ima lahko vrednosti S (sever), J (jug), V (vzhod)
in Z (zahod). Skladno z navodili naloge bomo spremenljivki x in y na začetku nastavili na
vrednost 0, smer pa na vrednost S.
int x = 0;
int y = 0;
char smer = 'S';
Nato pa se bomo, v primeru, da smo v nizu našli črko N, premaknili naprej. Ampak, kaj pomeni
naprej? To je odvisno od naše trenutne smeri. Preveriti je torej potrebno še vrednost
spremenljivke smer in glede na njo za 1 povečati ali zmanjšati ustrezno spremenljivko (x ali y).
if (podatki[i] == 'N') {
if(smer == 'S') {
y++;
}
else if(smer == 'J') {
y--;
}
else if(smer == 'V') {
x--;
}
else if(smer == 'Z') {
x++;
}
}
Če smo našli črko L, pomeni, da se moramo obrniti na levo. Pri tem nas zanima, v katero smer
bomo obrnjeni po tem, ko se obrnemo na levo. Tudi za to bomo potrebovali podatek o tem, v
katero smer smo trenutno obrnjeni, ter posledično spremenili našo smer.
else if (podatki[i] == 'L') {
if(smer == 'S') {
smer = 'V';
}
else if(smer == 'V') {
smer = 'J';
}
else if(smer == 'J') {
smer = 'Z';
61
}
else if(smer == 'Z') {
smer = 'S';
}
}
Pri obratu v desno storimo podobno.
else if (podatki[i] == 'D') {
if(smer == 'S') {
smer = 'Z';
}
else if(smer == 'Z') {
smer = 'J';
}
else if(smer == 'J') {
smer = 'V';
}
else if(smer == 'V') {
smer = 'S';
}
}
Ob koncu pa nas seveda zanimata obe koordinati, torej vrednosti spremenljivk x in y, zapisani
v ustrezni obliki.
cout << "(" << x << "," << y << ")" << endl;
62
4. OPREDELITEV RAZISKOVALNEGA PROBLEMA,
NAMENA IN CILJEV RAZISKOVANJA
Učenci potrebujejo poleg dobro pripravljene literature in skrbne razlage učitelja predvsem
veliko praktičnega dela oz. veliko praktičnih primerov, na katerih lahko pridobljeno znanje
utrdijo. Pomembno pri tem je, da so naloge sestavljene tako, da učence motivirajo za učenje pri
pouku in predvsem za samostojno delo doma.
Naš namen je bil raziskati, kako učence vzpodbuditi za utrjevanje znanja. Pri tem nas je
zanimalo, ali jih lahko pritegnemo z nizom v zgodbo povezanih nalog in kakšne lastnosti
morajo imeti takšne naloge, da na učence delujejo motivacijsko. Prav tako nas je zanimalo, s
kakšnimi težavami se mora spopadati učitelj pri sestavljanju takšnih vrst nalog.
Po navadi učitelj z vsako nalogo preverja neko določeno znanje oz. koncept, ni pa nujno, da
učenci nalogo rešijo na način, ki ga je predvidel učitelj. Zato smo želeli raziskali tudi, na kakšen
način bodo učenci naloge reševali oz. kakšne pristope in koncepte bodo pri tem uporabljali. Ob
vsem tem pa smo lahko s pomočjo teh nalog ugotovili tudi, kateri koncepti v programiranju so
za učence najtežji.
Izdelali smo spletno stran z nalogami, ki učencu omogočajo, da pridobljeno znanje
programiranja nadgradi in utrdi s pomočjo skrbno pripravljenih nalog. Te naloge si logično
sledijo in se povezujejo v motivacijsko zgodbo, v kateri uporabnik igra neko vlogo. Zgodba se
odvija v pisarni guvernerja za državno varnost, ki sporoči, da so hekerji iz Severne Jekorije
vdrli v sistem in grozijo, da bodo ob polnoči povzročili električni mrk. Učenec v tej zgodbi
prevzame vlogo posameznika, ki mora svet rešiti pred propadom, tako da prepreči 25 hekerskih
napadov. Vsak od teh napadov je predstavljen v obliki ene od nalog, ki jo mora učenec uspešno
rešiti. Vsaka naloga pa se vsebinsko navezuje na idejo hekerskega napada na sistem, kar še
dodatno motivira učenca, da se vživi v pripovedovano zgodbo. Ker si napadi smiselno sledijo,
lahko učenec nadaljuje z naslednjo nalogo šele, ko pravilno reši prejšnjo. Vsak napad učencu
generira večje število naključnih podatkov, iz katerih mora dobiti pravilno rešitev. Pomembno
pri tem je, da je teh naključnih podatkov toliko, da problema ni mogoče rešiti ročno, brez
pravilno sestavljenega programa. Hekerski napad je preprečen, če je rešitev naloge enaka
rešitvi, ki jo izračuna predpripravljena metoda na spletni strani.
Glede na teoretična izhodišča, izsledke raziskav in praktične izkušnje predvidevamo, da bodo
problemske naloge, ki smo jih sestavili v obliki zgodbe na spletni strani, na učence vplivale
63
pozitivno in jih vzpodbudile k utrjevanju znanja iz programiranja. Raziskava vključuje
relativno majhen vzorec, zato pridobljenih rezultatov ne moremo posploševati na celotno
populacijo. V ta namen bi bilo potrebno v raziskavo vključiti večje število dijakov iz različnih
šol in regij. Namen naše raziskave je bil preveriti, ali je moč teoretična dognanja iz literature
opaziti že pri manjših vzorcih.
4.1 RAZSKOVALNA VPRAŠANJA
Glavni poudarek raziskave dajemo vsebini nalog in vzpodbujanju učencev za samostojno
reševanje čim večjega števila primerov, zato smo odgovarjali na naslednja raziskovalna
vprašanja:
• Kako bodo med seboj povezane problemske naloge vplivale na učenčevo vztrajnost pri
reševanju?
• S katerimi izzivi se spopada učitelj ob sestavljanju takšnih nalog?
• Ali bodo učenci naloge reševali na način, ki si ga je ob sestavljanju naloge zamislil
učitelj?
• Kateri koncepti v programiranju so za učence najtežji?
Na raziskovalna vprašanja zaradi njihove narave ne bomo podajali kvantitativnih (v smislu
preverjanja statističnih značilnosti razlik ipd.), temveč zgolj kvalitativne odgovore.
4.2 METODA IN RAZSIKOVALNI PRISTOP
Raziskovalne metode so bile študij literature, preverjanje znanja dijakov s pomočjo nalog in
spletne strani Hekerski napadi ter intervjuji z izbranimi dijaki, ki so reševali pripravljene
naloge.
Vprašanja za intervju so bila oblikovana na podlagi teoretičnih izhodišč in praktičnih izkušenj.
Spraševali smo predvsem o učenčevih splošnih izkušnjah programiranja in njihovih izkušnjah
z nalogami, povezanimi s hekerskimi napadi, v primerjavi z reševanjem tipičnih nalog
programiranja. Ostali podatki pa so bili pridobljeni s pomočjo baze uporabnikov spletne strani.
64
4.3 VZOREC
Vzorec v raziskavi je izbran priložnostno. V raziskavi je sodelovalo 77 dijakov 2. letnika. Ti
dijaki so med šolskim letom svoje znanje programiranja utrjevali na standardnih, precej
matematično obarvanih, nalogah. Ob koncu šolskega leta pa smo jim ponudili tudi naloge,
povezane s hekerskimi napadi.
Iz tega vzorca smo izbrali devet dijakov, s katerimi smo opravili intervjuju.
4.4 OKOLIŠČINE IZVEDBE RAZISKAVE
Dijaki, ki so sodelovali v raziskavi so se med šolski letom učili osnov programiranja, natančneje
odločitvene stavke, zanke, funkcije, tabele, nize in strukture. Ob koncu šolskega leta pa so
morali to znanje utrditi, pri tem so lahko izbirali med standardnimi, matematično obarvanimi,
nalogami in nalogami s spletne strani Hekerski napadi. Za dijake je bilo torej utrjevanje znanja
obvezno, vendar pa so lahko sami izbrali tip nalog, ki jih bodo reševali (standardne naloge oz.
naloge na temo hekerski napadi). Izbrane naloge so dijaki reševali pri pouku in samostojno
doma, ob tem pa jih nismo časovno omejevali.
4.5 OPIS POSTOPKA ZBIRANJA PODATKOV
Za kvalitativno raziskavo smo rezultate pridobivali tako, da smo beležili svoje težave pri
sestavljanju motivacijskih nalog in opravili intervjuje z dijaki, ki so naloge reševali, o tem,
kakšne so se jim zdele naloge, kaj jim je bilo všeč, kaj jih je motilo in kaj bi pri nalogah
spremenili.
Pri kvantitativni raziskavi pa smo do rezultatov dostopali preko beleženja podatkov s spletne
strani. To smo izvedli tako, da se je moral uporabnik pred začetkom reševanja registrirati, nato
pa so se vsi njegovi podatki beležili v bazo. V tej bazi smo poleg njegovih naključno dodeljenih
podatkov zbirali tudi podatke o nalogah, ki jih je posamezni učenec rešil, o številu poskusov
reševanja posamezne naloge in času reševanja. Poleg vseh teh podatkov pa smo zbirali tudi
njihove programe, na podlagi česa smo lahko sklepali, na kašen način in s katerim konceptom
so reševali posamezno nalogo.
65
5. REZULTATI IN INTERPRETACIJA
5.1 INTERVJU
Po uspešno zaključenem reševanju nalog smo izmed 77 dijakov naključno izbrali 9 dijakov, s
katerimi smo opravili krajše intervjuje. Spraševali smo jih predvsem po njihovem mnenju o
programiranju na splošno in mnenju o pripravljenih problemskih nalogah. Njihovi odgovori so
zaradi zagotavljanja anonimnosti oštevilčeni.
1. Koliko časa že programiraš oz. se učiš programiranja?
DIJAK 1: Odkar sem začel obiskovati srednjo šolo.
DIJAK 2: Od začetka šolskega leta.
DIJAK 3: Začel sem že lansko leto v okviru krožka, a večino znanja sem pridobil v
letošnjem letu.
DIJAK 4: Začel sem v 1. letniku, pri krožku.
DIJAK 5: C/C++ eno šolsko leto.
DIJAK 6: Eno šolsko leto.
DIJAK 7: Eno leto
DIJAK 8: Dve šolski leti, letošnje leto intenzivnejše.
DIJAK 9: Eno leto.
Večina dijakov se je prvič srečala s programiranjem in ga začela resneje uriti v 2. letniku, ko so
imeli po programu predmet osnove programiranja in se učili programirati v jeziku C++.
Nekateri dijaki pa so se s programiranjem srečali že leto prej, in sicer v okviru krožka
programiranja v Pythonu. Nihče izmed njih se ni učil programirati pred vpisom na srednjo šolo.
2. Kaj ti je pri programiranju všeč?
DIJAK 1: Všeč mi je, ko se naučim nekaj novega in rešim program ali nek problem, ki se
mi je na začetku zdel nerešljiv.
DIJAK 2: Pri programiranju mi je všeč ustvarjanje iger in programov, ki so uporabni.
DIJAK 3: Iskanje različnih rešitev.
66
DIJAK 4: Pri programiranju mi je všeč, ko po dolgem in napornem razmišljanju/reševanju
problema problem rešim in implementiram kodo, dobim končni izdelek.
DIJAK 5: Ker obstaja zelo veliko rešitev za določen problem ter seveda, ker je reševanje
problemov s programiranjem veliko lažje in učinkovitejše ...
DIJAK 6: Ko poskušam sestaviti čim krajši program.
DIJAK 7: Programiranje obožujem. Rad programiram in pri tem uporabim znanje o tem,
kako predstaviti č bolj zapletene programe na čim bolj optimiziran način. Ni večjega užitka
kot, ko se spomniš zelo pametnega načina delovanja programa.
DIJAK 8: Zadovoljstvo, ko pridem do pravilne rešitve.
DIJAK 9: Izdelava programov, ki se mi zdijo uporabni.
Vsi dijaki so se do programiranja opredelili zelo pozitivno in povedali, da jim je programiranje
všeč. To je tudi pričakovano, saj gre za dijake računalniške smeri, za katere se predvideva, da
jih bodo takšna znanja zanimala. V svojih odgovorih so večinoma navajali, da jim je
programiranje všeč, ker jim predstavlja izziv in ker se jim zdi uporabno.
3. Kaj ti je pri programiranju nadležno?
DIJAK 1: Ne morem navesti nič posebnega, mogoče to, da moram programirati, ko se
imam še veliko drugih stvari za učenje.
DIJAK 2: Pri programiranju mi ni nič nadležno – razen testov :)
DIJAK 3: Pri programiranju mi je nadležno predvsem ponavljanje, dolgo tipkanje kode.
DIJAK 4: Lažjih nalog ne rešujem rad, ampak se raje malce posvetim večjim projektom.
DIJAK 5: Tipkanje kode, ker se pogosto zatipkam.
DIJAK 6: Da zapišem dolgo kodo, s katero se zelo trudimf, potem pa ne deluje.
DIJAK 7: Ne maram se sam učiti programiranja, ker mi nikoli nič ne dela, poleg tega je
gradivo v angleščini in za večino programerskih izrazov ne vem, kaj pomenijo.
DIJAK 8: Napake, ki jih ne znam odpraviti.
DIJAK 9: Nič.
67
Večini dijakov ni všeč, ko pri programiranju naredijo napake in jih ne znajo odpraviti ali pa za
njihovo odpravljanje porabijo veliko časa. En dijak je povedal, da ima raje obsežnejše projekte,
ker so po navadi bolj praktično in uporabno zasnovani.
4. Kakšne se ti zdijo naloge, povezane s hekerskimi napadi, v primerjavi z nalogami, ki si jih
reševal med šolskim letom pri pouku?
DIJAK 1: Bile so zabavne, všeč mi je bilo, da so imele nek kontekst in niso zahtevale le
izpisovanja vsote ali nizov itd.
DIJAK 2: Hekerski napadi se mi zdijo zanimivi in za razliko od drugih nalog, ki smo jih
reševali med šolskim letom, si pred začetkom reševanja posamezne naloge dijak mora
narediti načrt in dobro razmisliti, kako se naloge lotiti, saj so nekatere naloge zelo zahtevne.
DIJAK 3: Veliko boljše, saj so vključene v nek kontekst, hkrati pa se ob njih tudi zabavamo,
medtem ko se naloge pri pouku večkrat ponavljajo.
DIJAK 4: Odlične, zanimive.
DIJAK 5: Hekerski napadi so mi bili všeč, bili so zabavni.
DIJAK 6: Všeč mi je bila zgodba, ki me je pritegnila, tako da sem v nalogah užival.
DIJAK 7: Všeč mi je bila spletna stran, ki je podprla zgodbo.
DIJAK 8: Zanimivejši kot druge matematične naloge.
DIJAK 9: Nekatere naloge so mi bile všeč, pri drugih sem se malo jezil.
Vsi dijaki so se do teh povezovalnih in problemskih nalog opredelili zelo pozitivno, predvsem
so se jim zdele zanimive in zabavne, všeč pa jim je bila tudi zgodba. Takšen odziv smo
pričakovali, saj so dijaki med letom reševali le tipične programerske in matematično obarvane
naloge, za katere menimo, da se dijakom zdijo nekoliko dolgočasnejše.
5. Te to, da je naloga povezana z zgodbo, kaj bolj vzpodbudi k temu, da bi jo rešil?
DIJAK 1: Ne morem reči, da me vzpodbudi k reševanju, ampak ko začnem z reševanjem,
se mi zdi zabavna.
DIJAK 2: Ja, ker so zabavnejše.
DIJAK 3: Da.
68
DIJAK 4: Da.
DIJAK 5: Če že rešujem naloge, so mi te vsaj zabavnejše.
DIJAK 6: Da.
DIJAK 7: Da.
DIJAK 8: Ko jih rešujem, se bolj zabavam.
DIJAK 9: Da, ker pozabim, da se učim.
Vsi dijaki menijo, da jih naloge, ki so povezane z zgodbo, bolj vzpodbudijo, da jih rešijo.
Večina dijakov namreč navaja, da se ob njihovem reševanju bolj zabavajo.
6. Katere naloge so se ti zdele najtežje in katere najlažje? Zakaj?
DIJAK 1: Najtežja se mi je zdela 8. naloga, ne vem, zakaj, saj sem jo razumel, samo ni se
mi hotelo pravilno izpisati. Ostale naloge so se mi zdele približno enako težke/lahke.
DIJAK 2: Najtežja se mi je zdela zadnja naloga, saj sem si moral ves čas predstavljati, kaj
se bo zgodilo, če karkoli naredim ali zamenjam. Najlažje pa so se mi zdele začetne naloge.
DIJAK 3: Zataknilo se mi je pri 8. nalogi. Do 8. naloge so se mi zdele vse naloge
razmeroma lahke, saj ni bilo kakšnih zelo zapletenih problemov.
DIJAK 4: Najtežje s stringi (recimo 8, 25, 23), najlažje s tabelami števil. Na splošno niso
bile zelo težke.
DIJAK 5: Zataknilo se mi je pri 8. in 25. nalogi, ostale so se mi zdele približno enako težke.
DIJAK 6: Najtežja osma, najlažja prva.
DIJAK 7: Največ časa sem porabil za 8. in za zadnjo nalogo.
DIJAK 8: Težave mi je povzročala samo sem 8 naloga. Najlažji sta bili 1. in 6.
DIJAK 9: Najtežje so se mi zdele naloge, kjer so bili podatki nizi, lažje so bile tiste, ki so
imele za podatke tabelo ali števila.
Večini dijakov sta se zdeli najtežji 8. in 25. naloga. Menimo, da jim je bil pri 8. nalogi najtežji
koncept ponastavitve števca ob zagotovitvi nekega pogoja, pri 25. nalogi pa si jim je bilo
69
najtežje predstavljati prostor in se po prostoru premikati ter obračati. Dva dijaka sta omenila,
da so se jima zdele težje naloge tiste, ki so podajale vhodne podatke v obliki nizov.
Večini dijakov so se ostale naloge zdele enako težke, nekateri pa so jih kljub vsemu opredelili
kot lahke. Drugim pa so se zdele lažje začetne naloge, posebej so omenili 1. in 6. nalogo. Prva
naloga je bila zelo osnovna, obravnavala je koncept prištevanja in odštevanja. Šesta naloga je
obravnavala koncept pretvarjanja iz desetiškega v dvojiški številski sistem.
7. Bi katero nalogo spremenil/zamenjal? Zakaj?
DIJAK 1: Ne, ker so se mi zdele vse v redu.
DIJAK 2: Ne. Vse so se mi zdele kar razumljive.
DIJAK 3: Spremenil bi 8. nalogo, ker program ni delal.
DIJAK 4: Tiste naloge s stringi, za katere sem porabil tudi do 2 uri na nalogo.
DIJAK 5: Nobene, ne bi jih zamenjal, bi pa dodal kakšen dodaten namig pri 8. nalogi.
DIJAK 6: Osmo, ker sem imel težave pri reševanju.
DIJAK 7: Ne, ker so v redu.
DIJAK 8: Pri nekaterih nalogah bi skrajšal navodila.
DIJAK 9: Ne, tudi če pri kateri nalogi nisem razumel navodil, sem pogledal primere, ki so
bili jasni.
Nekaj dijakov ne bi spremenilo nobene naloge, nekaj pa bi jih spremenilo ali z namigi dopolnilo
8. nalogo. Dva dijaka bi spremenila navodila pri nekaterih nalogah, ker so se jima zdela premalo
nazorna.
8. Želiš še kaj sporočiti glede nalog, povezanih s hekerskimi napadi?
DIJAK 1: Nekatera navodila so se mi zdela nerazumljiva in sem moral iz primerov
ugotoviti, kaj moram narediti.
DIJAK 2: /
DIJAK 3: /
70
DIJAK 4: Te naloge so se mi zelo zanimive, reševal sem jih z veseljem, motila me je samo
ena stvar: zgodba je bila sicer zelo dobro sestavljena, ampak se mi je zdelo moteče, ker
nismo mogli nalog reševati poljubno (šele potem ko smo rešili določeno nalogo, smo dobili
dostop do naslednje; težava je bila v tem, da če se nam je kje zataknilo, nismo mogli
reševati nalog, ki so sledile ...).
DIJAK 5: /
DIJAK 6: /
DIJAK 7: /
DIJAK 8: /
DIJAK 9: /
Na to vprašanje sta odgovorila samo dva dijaka, in sicer en dijak bi pri določenih nalogah želel
jasnejša navodila in drug dijak, ki predlaga možnost nadaljevanja z naslednjo nalogo, kljub
temu da prejšnje še ni pravilno rešil.
5.2 KAKO BODO MED SEBOJ POVEZANE PROBLEMSKE NALOGE
VPLIVALE NA VZTRAJNOST PRI REŠEVANJU?
Na raziskovalno vprašanje »Kako bodo med seboj povezane problemske naloge vplivale na
vztrajnost pri reševanju?« smo odgovarjali s pomočjo odgovorov intervjuvanih dijakov in s
pomočjo podatkov iz baze, ki so pokazali, koliko dijakov je rešilo vse naloge.
V intervjuju sta se na to raziskovalno vprašanje neposredno navezovali predvsem dve vprašanji:
• Kakšne se ti zdijo naloge hekerski napadi v primerjavi z nalogami, ki si jih reševal med
šolskim letom pri pouku?
• Te to, da je naloga povezana z zgodbo, kaj bolj vzpodbudi k temu, da bi jo rešil?
Intervjuvani dijaki so imeli o povezovalnih in problemskih nalogah zelo dobro mnenje,
poudarjali so, da so se jim zdele naloge zanimive in zabavne in da jim je bila všeč tudi zgodba.
Na splošno so menili, da jih te naloge bolj vzpodbudijo k reševanju.
Na podlagi naše baze uporabnikov smo ugotovili, da je od 77 registriranih dijakov vseh 25
nalog rešilo 71 dijakov, kar predstavlja kar 92,2 % vseh registriranih dijakov. Šest dijakov, ki
71
ni rešilo vseh nalog, se je ustavilo pri eni od prvih štirih nalog. Ko smo preverili, za katere
dijake gre, smo ugotovili, da so to v veliki meri dijaki, ki se želijo bodisi prepisati na drugo šolo
bodisi bodo letnik ponavljali.
Na podlagi zgoraj predstavljenih dejstev lahko zaključimo, da so med seboj povezane
problemske naloge zelo pozitivno vplivale na vztrajnost utrjevanja nalog iz programiranja
dijakov, ki so bili vključeni v našo raziskavo. Dijaki so bili za te naloge še toliko bolj motivirani,
ker so pred tem celo leto reševali le tipične programerske in matematično obarvane naloge.
5.3 S KATERIMI IZZIVI SE SPODADA UČITELJ OB SESTAVLJANJU
TAKŠNIH NALOG?
Do sedaj smo spoznali že veliko pozitivnih učinkov, ki jih imajo problemske in v zgodbo
povezane naloge na učence. V naši raziskavi smo ugotovili, da tako sestavljene naloge delujejo
na učence zelo vzpodbudno in da bi bilo takšne tipe nalog zelo smiselno čim bolj uporabljati
tudi pri pouku programiranja. Vendar pa je dejstvo tudi, da je za učitelje veliko težje in
zamudneje sestaviti takšne tipe nalog kot pripraviti medsebojno nepovezane, tipične
programersko obarvane naloge, ki brez kakršnekoli zgodbe zelo neposredno od učenca
zahtevajo rešitev po navadi nekega čisto matematičnega problema.
Preden smo sploh začeli sestavljati naloge, smo si morali izmisliti zgodbo, ki bi bila dovolj
zanimiva in aktualna za naše dijake in v katero bi se zlahka vživeli. Ker gre za dijake
računalniške smeri, smo izbrali računalniško obarvano zgodbo, ki od njih zahteva, da se
prelevijo v, zanje zelo aktualen in pogosto nekoliko skrivnosten lik, hekerja. Ko smo se odločili
za temo hekerskih napadov, se je začel proces sestavljanja nalog. Pri tem smo morali najprej
določiti, katera znanja želimo utrjevati in nato za ta znanja najti ustrezne naloge, ki se skladajo
z izbrano tematiko. Ob tem smo morali paziti še, da se problemi ne ponavljajo oz. da si niso
preveč podobni, saj bi to dijake precej odvrnilo od reševanja nalog. Želeli smo si tudi, da se
naloge navezujejo ena na drugo, kar je za nas predstavljalo svojevrsten izziv in zahtevalo veliko
naše domišljije. Po drugi strani pa naloge niso smele biti preveč domišljijske, ampak dovolj
življenjske, da so se dijaki brez težav vanje vživeli. Poleg vsega tega, smo morali ves čas
sestavljanja nalog misliti tudi postopnost, želeli smo torej, da si naloge sledijo od lažje k težjim.
72
5.4 ALI BODO UČENCI NALOGE REŠEVALI NA NAČIN, KI SI GA JE
OB SESTAVLJANJU NALOGE ZAMISLIL UČITELJ?
Na raziskovalno vprašanje »Ali bodo učenci naloge reševali na način, ki si ga je ob sestavljanju
naloge zamislil učitelj?« bomo odgovorili s pomočjo pregleda programov, ki so nam jih ob
reševanju nalog oddali dijaki.
Pregled programov je pokazal, da so dijaki naloge reševali na naslednje načine:
1. Varnostno geslo
o Večina programov je takšnih, kot smo predvidevali v naši rešitvi.
o Nekaj programov je takšnih, kot smo predvidevali v naši rešitvi, le namesto stavka
if so uporabljali stavek switch.
o En program dvakrat preverja enake pogoje:
if((geslo[x] == '-') || (geslo[x] == '+')) {
if(geslo[x] == '-' {
k--;
}
else {
k++;
}
}
2. Iskanje ključa šifriranih podatkov
o Pri večini programov je deklariranih deset spremenljivk ali tabela z desetimi
elementi in bodisi s switch bodisi z if-stavkom preverjajo, za kateri znak (števko)
gre, ter povečajo ustrezno spremenljivko. Na koncu množijo število pojavitev s
števkami.
o V nekaterih programih je prav tako deklariranih deset spremenljivk in se prav tako
preverja, za kateri znak (števko) gre, vendar pa se v spremenljivko vsota na koncu
preprosto prišteva ta števka. Kljub temu da so se dijaki s tem izognili preštevanju
števk, so na koncu dobili pravilno rešitev.
o Nekaj programov sproti prišteva ASCII-vrednost znaka:
st = st + niz[i] – 48;
ali
st = st + niz[i] – '0';
73
3. GPS
o Ideja vseh pregledanih programov je bila zelo podobna naši rešitvi, z manjšimi
razlikami v logiki pretvarjanja med časovnimi enotami. Te razlike so bile vezane
predvsem na to, ali je dijak najprej pretvarjal v sekunde, minute in nato v ure, ali pa
je pretvarjal v obratnem vrstnem redu.
4. Poišči geslo
o Manjšina programov je natanko takšnih kot v naši rešitvi.
o Ideja večine programov pa je popolnoma drugačna od naše rešitve:
string podatki = "<naključni podatki>";
int resitev = 0;
for(int i = 0; i < podatki.length(); i++) {
if(podatki[i] == '{') {
while(podatki[i] != '}') {
if (podatki[i] == 'v' || podatki[i] == 'i'
|| podatki[i] == 'r' || podatki[i] == 'u'
|| podatki[i] == 's') {
resitev++;
}
i++;
}
}
}
5. Dešifriraj geslo
o Nekaj programov je zelo podobnih naši rešitvi.
o Nekaj programov je takšnih, da se s stavkom if najprej preveri, ali je trenutni znak
različen od samoglasnikov in od znaka z, ki se mora preslikati v znak a. Šele nato
pa se preveri, za kateri znak gre in se ga ustrezno spremeni.
o V nekaterih programih so dijaki uporabili funkcijo, ki je ustrezno spremenila
samoglasnike, razen tega pa je bila ideja teh programov podobna naši rešitvi.
6. Pretvarjanje v binarni zapis
o Nekaj programov je zelo podobnih naši rešitvi.
o Nekaj programov se od naše rešitve razlikuje zgolj v tem, da namesto prištevanja
vseh binarnih števk, s stavkom if preverjajo, ali je posamezna binarna števka enaka
1 in v tem primeru ustrezno povečajo števec.
74
7. Analiza besedil glede na iskano besedo
o Vsi oddani programi so sledili enaki zamisli, in sicer pregledati celoten niz ter
posamezne črke primerjati z iskanim nizom, ki jim ga je generiral program. Na
primer za iskanje besede ''watu'':
for(int i = 0; i < 1000; i++ {
if(podatki[i] == 'w' && podatki[i + 1] == 'a'
&& podatki[i + 2] == 't' && podatki[i + 3] == 'u'
}
…
8. Analiza besedil glede na dolžino besed
o Vsi pregledani programi so sledili podobni zamisli, kot je naša. Vsi so namreč iskali
presledke, če jih niso našli, pa so šteli črke v besedi. Ko so našli presledek, so
preverili, ali je beseda ustrezne dolžine.
9. Napad na ključe za podpisovanje certifikatov
o Vsi pregledani programi sledijo isti zamisli, kot je naša rešitev, edina razlika pri
nekaterih od njih je, da so program sestavili v obliki funkcije.
10. Napad na pomnilnik
o Večina pregledanih programov za vsak element v prvi tabeli najprej preveri, če gre
za enega od znakov 'v', 'w', 'x', 'y', 'z'. Nato učenci preverijo, če je istoležni element
v drugi tabeli enak 'P'; če je, so učenci za vrednost istoležnega elementa v tretji tabeli
povečali ustrezno spremenljivko (v, w, x, y ali z), sicer pa so za vrednost istoležnega
elementa v tretji tabeli ustrezno spremenljivko zmanjšali.
for(int i = 0; i < 1000; i++ {
if(tab1[i] == 'v') {
if(tab2[i] == 'P' {
v += tab3[i];
}
else {
v -= tab3[i];
}
}
…
o Ostali so uporabili podobno idejo, le da so namesto stavkov if, uporabili stavke
switch.
75
11. Pošiljanje sporočila guvernerju
o V večini programov so si za premikanje znakov pomagali z metodami, kot so
push_back(), erase(), begin(), end().
o Ostali programi so uporabili idejo, kot smo jo predvideli v naši rešitvi.
12. Lokacije državnih skrivališč
o Vsi pregledani dokumenti so sledili ideji, ki smo jo predvideli v naši rešitvi.
13. Kodiranje po RLE-metodi
o Polovica dijakov je nalogo reševala enako, kot smo jo rešili mi.
o Polovica dijakov je primerjala dva zaporedna znaka in štela ponovitve, dokler se
znaka nista razlikovala, takrat so števec ponastavili.
14. Napad na telefonske številke
o Večina dijakov je v nizu iskala znake '+' in '00' ter nato naslednje tri znake zamenjala
s presledki ali jih zbrisala. Nato pa so z novo zanko pregledali vse nize in v njih šteli
ponovitve znakov '3', '6', '8'.
o Nekaj dijakov je nalogo rešilo, kot smo predvidevali.
15. Izbris besed v zaupnih dokumentih
o Vsi dijaki so nalogo rešili tako, da so primerjali konkretne črke njihove dane besede
s posameznimi znaki niza in povečevali števec, če so se črke ujemale.
16. Dodane besede v zaupnih dokumentih
o Ideja pregledanih programov se popolnoma sklada z idejo, ki smo jo predvideli v
naši rešitvi.
17. Leksikografsko urejanje besed
o Programi so identični naši rešitvi.
18. Izbrisane črke
o Programi so podobni naši rešitvi.
76
19. Napad na števila
o Ideja vseh pregledanih programov je bila podobna naši predvideni rešitvi. Razlika je
bila le, da je večina dijakov najprej z zanko preštela, koliko mestno je neko število.
Manjša razlika je bila tudi, da so nekateri dijaki namesto stavka if za podvojitev vsake
druge števke, povečali števec za 2.
20. Napad na identifikacijske številke dokazov
o Nekaj dijakov je izdelalo programe na podlagi iste zamisli, kot je naša.
o Večina dijakov je najprej preštela, za koliko mesto število gre, nato so ustvarili tabelo
takšne velikosti in potem v njo shranili posamezne števke števila. V naslednjem
koraku so množili te števke, shranjene v tabeli, z ustreznim številom in to vrednost
priredili nazaj na ustrezno mesto v tabeli. Na koncu so preverili deljivost s številom
11. Tako so uporabili kar tri zanke.
21. Branje zakodiranega sporočila
o Večina dijakov je le izpisala vrednosti v zaporedju, kot predvidevajo navodila:
for(int i = 0; i < dolzina; i++) {
for(int j = 0; j < dolzina; j++) {
cout << podatki[j][i];
}
}
o Nekateri dijaki so v svojih rešitvah uporabili metodo push_back():
string sporosilo;
for(int i = 0; i < dolzina; i++) {
for(int j = 0; j < dolzina; j++) {
sporocilo.push_back(podatki[j][i]);
}
}
cout << sporocilo;
22. Določitev novih identifikacijskih števil
o Programi imajo isto idejo kot naša rešitev.
23. Napad na računske operacije
o Programi so identični naši rešitvi.
77
24. Mapa Fibonacci
o Ideja večine pregledanih programov je bila enaka naši rešitvi.
o Nekaj programov je bilo izdelanih za točno določen člen, razen tega pa drugih
odstopanj od naše rešitve ni bilo.
25. Koordinate napadalcev
o Ideja pregledanih programov je identična naši rešitvi.
Pregled oddanih programov je pokazal, da so dijaki večino nalog reševali na način, kot smo ga
predvidevali ob sestavljanju nalog. To se je še posebej pokazalo pri nalogah 1, 2, 3, 5, 6, 8, 9,
10, 12, 16, 17, 18, 19, 22, 23, 24 in 25. Nekaj nalog, recimo naloge 13, 14 in 20, je bilo takšnih,
ki jih je nekaj dijakov reševalo na predviden način, del dijakov pa jih je rešil na nek svoj način.
V preostalih nalogah, naloge 4, 7, 11, 15 in 21, noben dijak ni uporabil predvidene ideje, ampak
so vsi oblikovali svoje ideje, ki so si bile med seboj podobne. Ti programi so se od predvidenih
rešitev največkrat razlikovali v tem, da:
• so bili so manj optimizirani,
• niso bili splošni, ampak so bili prilagojeni za točno določene podatke, ki so jim bili
dodeljeni,
• so uporabljali druge strukture (npr. stavek switch namesto stavka if ali različne vrste
zank),
• uporabljali so funkcije, tudi če naloga tega od njih ni zahtevala,
• so podvajali (večkrat preverjali) isto stvar.
5.5 KATERI KONCEPTI V PROGRAMIRANJU SO ZA UČENCE
NAJTEŽJI?
Na raziskovalno vprašanje »Kateri koncepti v programiranju so za učence najtežji?« bomo
odgovorili s pomočjo izračuna povprečnega števila oddanih napačnih rešitev. V naši bazi
imamo zabeleženo število napačnih rešitev pri posamezni nalogi za posameznega dijaka. Iz teh
podatkov smo za vsako nalogo izračunali povprečje napačnih rešitev in na podlagi teh
izračunov razvrstili naloge od najlažje do najtežje.
78
Zap. št.
nal.
Naslov naloge Koncept Povprečno
št. napačnih
rešitev
1 Varnostno geslo Štetje (prištevanje in
odštevanje), pogojni stavki,
zanke
0,146
6 Pretvarjanje v binarni zapis Štetje, pretvarjanje med
številskimi zapisi, deljenje,
ostanek, pogojni stavki,
gnezdene zanke, tabele
0,205
12 Lokacije državnih skrivališč Dvodimenzionalne tabele,
iskanje elementa
0,318
20 Napad na identifikacijske
številke dokazov
Razstavljanje števil na števke,
funkcije
0,384
18 Izbrisane črke Funkcije, iskanje znakov v nizu 0,400
21 Branje zakodiranega števila Branje elementa z določenega
mesta v tabeli,
dvodimenzionalne tabele
0,489
15 Izbris besed v zaupnih
dokumentih
Iskanje podniza v nizu, štetje 0,493
22 Določitev novih
identifikacijskih števil
Iskanje po tabeli, tabele 0,513
24 Mapa Fibonacci Algoritem zaporedja 0,605
9 Napad na ključe za
podpisovanje certifikatov
Iskanje največjega in
najmanjšega elementa, gnezdene
zanke, dvodimenzionalne tabele
0,638
13 Kodiranje po RLE-metodi Primerjanje dveh znakov v nizu,
štetje enakih zaporednih znakov
niza
0,818
16 Dodane besede v zaupnih
dokumentih
Tabele nizov, iskanje črk v nizih,
štetje
0,750
79
4 Poišči geslo Štetje, iskanje nekega znaka v
nizu, koncept stanja, pogojni
stavki, zanke, nizi
1,200
2 Iskanje ključa šifriranih
podatkov
Preštevanje različnih objektov,
pogojni stavki, zanke, nizi,
tabele
1,338
3 GPS Pretvarjanje med številskimi
zapisi, deljenje, deljenje z
ostankom, pogojni stavki, zanke,
tabele
1,444
11 Pošiljanje sporočila
guvernerju
Funkcije 1,477
19 Napad na števila Razstavljanje števil na števke,
odločitveni stavki, pogoji
1,564
10 Napad na pomnilnik Odločitveni stavki, zanke, tabele 2,021
23 Napad na računske operacije Štetje različnih elementov v
nizih
2,342
17 Leksikografsko urejanje
besed
Urejanje elementov v tabeli 2,350
5 Dešifriraj geslo Računanje vsote, pogojni stavki,
zanke, nizi
2,362
14 Napad na telefonske številke Tabele nizov, iskanje znakov v
nizih, dvodimenzionalne tabele
2,425
7 Analiza besedil glede na
iskano besedo
Štetje, pogojni stavki, zanke, nizi 2,674
8 Analiza besedil glede na
dolžino besed
Koncept štetja z vmesno
ponastavitvijo števca, pogojni
stavki, zanke, nizi
2,895
25 Koordinate napadalcev Sestavljanje pogojev, uporaba
koordinatnega sistema
2,943
Povprečno število napačnih odgovorov smo primerjali še z odgovori intervjuvanih dijakov in
na podlagi teh odgovorov ugotovili, katere naloge se jim zdijo najlažje in katere najtežje.
80
Omenili smo že, da so intervjuvani dijaki kot najtežji nalogi izpostavili 8. in 25. nalogo. Da sta
ti dve nalogi za dijake predstavljali največji izziv, smo potrdili tudi z izračunom povprečnega
števila oddanih napačnih rešitev. Ocenjujemo, da je dijakom 8. naloga težka zaradi koncepta
ponastavitve števca ob zagotavljanju določenega pogoja, 25. naloga pa zaradi miselne
ponazoritve koordinatnega sistema in premikanja po njem.
Dva intervjuvana dijaka sta omenila, da so se jima zdele težje tiste naloge, ki so vhodne podatke
podajale v obliki nizov. Tudi izračun povprečnega števila napačnih rešitev je potrdil, da so bile
naloge z nizi (recimo naloga 25, 8, 7, 14, 5, 17, 23) za dijake na splošno težje.
Izračun povprečnega števila napačnih rešitev je potrdil tudi, da sta najlažji nalogi 1. in 6., ki so
ju za najlažji opredelili tudi intervjuvani dijaki. Prva naloga je osnovna in obravnava zelo
enostaven koncept prištevanja in odštevanja, zato ni presenetljivo, da so jo dijaki označili za
lažjo. Šeste naloge sicer ne ocenjujemo kot lahke, a je za dijake predstavljala lahek izziv.
Sklepamo, da zato, ker so takšna pretvarjanja utrjevali že pri drugih predmetih, poleg tega pa
so podobne naloge reševali že v diagramih poteka pri predmetih prejšnjega šolskega leta, zato
jim je bil ta pristop znan.
Iz izračuna povprečnega števila napačnih rešitev je razvidno tudi, da se zdijo dijakom lažje
naloge tiste, ki imajo podatke podane v obliki tabele števil ali znakov (recimo naloge 6, 12, 21,
22, 9) in tiste, ki od dijakov zahtevajo delo s funkcijami (recimo naloge 20, 18).
81
6. ZAKLJUČEK
Programiranje je za učence težko predvsem zato, ker jih izpostavlja računalniškemu mišljenju,
s tem pa reševanju problemov z uporabo računalniških konceptov, ki so za učence praviloma
zelo zahtevni. Za učenje programiranja ni recepta oz. jasnih korakov, ki bi vsakega učenca
pripeljali do tega, da bi znal programirati. Z gotovostjo pa lahko trdimo, je, da je potrebo znanje
programiranja utrjevati. Ker je to samo po sebi dolgotrajen proces, pa veliko učencev med njim
izgubi začetno navdušenje in zanimanje za programiranje. Razlog za to so tudi, še posebej pri
začetnikih v programiranju, pogoste in ponavljajoče se napake v kodi in njihovo težavno
odkrivanje in odpravljanje. Le-te pa je v veliki meri mogoče odpraviti le z utrjevanjem. Pri
poučevanju programiranja moramo zato biti še posebej pozorni na vzpodbujanje motivacije
učencev. Za učence se je kot izjemno vzpodbuden izkazal pristop problemskega učenja,
katerega prednost je predvsem v tem, da zagotavlja veliko bolj učinkovito in smiselno učenje
ter od njih zahteva razumevanje problema, razvoj načrta za njegovo rešitev in preizkušanje tega
načrta. Ker je ravno sposobnost reševanja problemov ključni primanjkljaj začetnikov, je ta
pristop zelo primeren za poučevanje učencev začetnikov v programiranju.
V sklopu magistrskega dela smo izdelali spletno stran s 25 nalogami, povezanimi v zgodbo in
uspešno izvedli reševanje teh nalog na srednji računalniški šoli, v 2. letniku, saj se prav takrat
dijaki seznanijo z osnovami programiranja. Vseh 25 pripravljenih nalog je rešilo kar 92,2 %
(anketiranih je bilo 77 dijakov). To potrjuje, da so pozitivni učinki problemskega poučevanja
pri utrjevanju vidni že na majhnem vzorcu. S problemskim prostopom dijake namreč lahko bolj
vzpodbujamo k učenju in vztrajnosti, kar smo prepoznali tudi iz odgovorov anketiranih. Dijaki
so navajali, da so se jim zdele naloge zanimive in zabavne ter da jim je bila všeč zgodba, kar je
vsekakor pokazatelj, da problemske naloge in spletna stran dijake vzpodbujajo k utrjevanju
programiranja. Te naloge so primerne tako za uporabo pri pouku kot tudi za dodatno delo v
obliki domačih nalog.
Pri sestavljanju vsake izmed nalog smo želeli utrjevati določen koncept. Ker pa le-ta ni bil
eksplicitno podan, saj to ne bi bilo skladno z načeli problemskega učenja, pa je obstajala
nevarnost, da bodo dijaki reševali naloge na načine, ki bi bili drugačni od predvidenih, zato
naše skrbno sestavljanje nalog za posamezne koncepte ne bi bilo koristno. Pregled izdelanih
programov je pokazal, da je bila večina nalog rešena na predvideni način. Razlike so bile
največkrat v tem, da so bili ti programi nekoliko manj optimizirani ali pa prirejeni za rešitev
točno določenih vhodnih podatkov, ki so jim bili dodeljeni. Ugotavljamo torej, da je sestavljanje
82
programerskih nalog za posamične koncepte mogoče in smiselno tudi pri manj strogo vodenem
problemskem učenju.
Pri pregledu prejetih programov smo ugotovili tudi, da so bile za dijake najtežje tiste naloge, ki
so vsebovale podatke v obliki nizov in tiste, ki so od njih zahtevale zahtevnejše miselne
koncepte. Najlažje naloge pa so bile tiste, ki so imele podatke podane v obliki tabel števil ali
znakov in tiste, ki so zahtevale delo s funkcijami.
Čeprav imajo problemsko zasnovane naloge izjemno veliko pozitivnih učinkov na učenje
programiranja, pa predstavljajo za učitelje, ki jih sestavljajo, kar velik izziv. Takšne naloge je
namreč veliko težje in zamudneje sestaviti kot naloge, ki so med seboj nepovezane in ki so
tipično zelo matematično obarvane.
Rezultatov raziskave zaradi majhnosti vzorca ne moremo posplošiti na celotno populacijo. Prav
tako bi objektiven odgovor na vprašanje o tem, ali je podajanje nalog v tej obliki učinkovitejše
od klasičnega, tj. podajanja nalog v obliki nepovezanih nalog, zahtevalo kontrolno skupino, ki
bi reševala iste naloge, vendar brez zgodb v ozadju. Takšne študije zaradi praktičnih omejitev
nismo mogli izvesti. Veliko število dijakov, ki so pravilno rešili vse naloge in, predvsem,
njihovi osebni komentarji o klasičnih nalogah in nalogah v obliki zgodb, pa jasno nakazujejo,
da tovrstne naloge na učenje vplivajo vzpodbudno in nudijo celovitejše, bolj smiselno in
učinkovitejše učenje.
83
7. VIRI IN LITERATURA
Association. E. S. (2014). Essential Facts about the Computer and Video Game Industry: 2014
Sales, Demographic, and Usage Data. theesa.com.
Azmi, S., Iahad,N.A., Ahmad, N. (2015). Gamification in online collaborative learning for
programming courses: a literature review. ARPN Journal of Engineering and Applied Sciences,
10(23), 1–3.
Bransford, J. D., in Stein, B. S. (1984). The ideal problem solver: A guide for improving
thinking, learning, and creativity. New York: Freeman.
Bonwell, C. & Eison, J. (1991). Active Learning: Creating Excitement in the Classroom.
Washington DC: ASHE-ERIC Higher Education Reports.
Brusilovsky, P. (2001). WebEx: Learning from Examples in a Programming Course.
Proceedings of WebNet 2001 - World Conference on the WWW and Internet, Orlando.
Brusilovsky, P. in Yudelson M. V. (2008). From WebEx to NavEx: Interactive Access to
Annotated Program Examples. Proceedings of the IEEE, 96(6), 990–999.
Deterding, S., Dixon, D., Khaled, R., & Nacke, L. (2011). From Game Design Elements to
Gamefulness: Defining "Gamification". In A. Lugmayr et al. (Ed.), MindTrek 2011 (pp. 9–15).
Tampere, Findland: ACM.
Duffy, T. & Jonnasen, D. (1992). Constructivism and the Technology of Instruction: A
Conversation Philadelphia, PA: Lawrence Erlbaum.
Edutopia (2014). Five keys to rigorous project-based learning. Retrieved from
http://www.edutopia.org/video/five-keys-rigorous-project-based-learning.
Felicia, P. (2009). Digital games in schools: A handbook for teachers. Brussels, Belgium:
European Schoolnet.
Fletcher, G., in Lu, J. (2009). Education: Human computing skills: Rethinking the K12
experience. Communications of the ACM - Inspiring Women in Computing, 52, 23–25.
Gioia, D. A. in Brass., D. (1985). Teaching the TV generation: The case for observational
learning. Organizational Behavior Teaching Review, 10, 11–18.
84
Jakoš, F. in Veber, D. (2016). Learning Basic Programing Skills With Educational Games: A
Case of Primary Schools in Slovenia. Journal of Educational Computing, 55(5), 673–698.
Jenkins, T. (2001). The motivation of students of programming. In Proceedings of ITiCSE
2001: The 6th annual conference on innovation and technology in computer science education
(pp. 53–56).
Jermann, P., & Dillenbourg, P. (2008). Group mirrors to support interaction regulation in
collaborative problem solving. Computers & Education, 51(1), 279–296.
Jonassen, D. (2000). Toward a Design Theory of Problem Solving. Educational Technology
Design and Development, 48(4).
Jonassen, D. (2003). Designing research-based instruction for story problems. Educational
Psychology Review, 15(3), 267–296.
Jonassen, D. (2004). Learning to solve problems: An instructional design guide. San Francisco,
CA: John Wiley & Sons.
Kapp, K. (2012). Games, Gamification, and the Quest for Learner Engagement. T+D, 66(6),
64–68.
Kapp, K. (2012). The gamification of learning and instruction: game-based methods and
strategies for training and education, John Wiley & Sons.
Kark. R., (2011). Games managers play: Play as a form of leadership development. Academy
of Management Learning & Education, 10, 507–527.
Kay, J., Barg, M., Fekete, A., Greening, T., Hollands, O., Kingston, J., et al. (2000). Problem-
based learning for foundation computer science courses. Computer Science Education, 10, 109–
128.
Kirschner, P. Sweller, J. & Clark, R. (2006). Why Minimal Guidance During Instruction Does
Not Work: an Analysis of the Failure of Constructivist, Discovery, Problem-based,
Experiential, and Inquiry-based Teaching. Educational Psychologist. 41(2).
Lam, M. S. W., Chan, E. Y. K., Lee, V. C. S., & Yu, Y. T. (2008). Designing an automatic
debugging assistant for improving the learning of computer programming. Lecture Notes in
Computer Science, 5169, 359–370.
85
Larmer, J. (2014). Project-based learning vs. problem-based learning vs. X-BL. Retrieved from
http://www.edutopia.org/blog/pbl-vs-pbl-vs-xbl-john-larmer
Lau, W. W. F., & Yuen, A. H. K. (2009). Exploring the effects of gender and learning styles on
computer programming performance: Implications for programming pedagogy. British Journal
of Educational Technology, 40(4), 696–712.
Law, K. M. Y., Sandnes, F. E., Jian, H., & Huang, Y. (2009). A comparative study of learning
motivation among engineering students in South East Asia and beyond. International Journal
of Engineering Education, 25(1), 144–151.
Lewis, L., & Williams, C. (1994). Experiential learning: Past and present. New Directions for
Adult and Continuing Education, 62, 5–16.
Linn, M. C. in Clancy, M. J. (1992). Can experts' explanations help students develop program
design skills. International Journal on the Man-Machine Studies 36(4), 511–551.
Linn, M. C., Clark, D., & Slotta, J. D. (2003). Wise design for knowledge integration. Science
Education, 87(4), 517–538.
Lode, H., Franchi, G., & Frederiksen, N. (2012). Learning games for programming. (Master
thesis). Copenhagen, Denmark: IT University Copenhagen.
Maragos, K., & Grigoriadou, M. (2007). Designing an educational online multiplayer.
Proceedings of the Informatics Education Europe II Conference IEEII, 322–331.
Nah, F., Eschenbrenner, B., Zeng, Q., Telaprolu, V., Sepehr, S. (2014). Flow in Gaming:
Literature Synthesis and Framework Development. International Journal of Information
Systems and Management 1(1).
Norving, P. (2016). Teach yourself programming in ten years. Retrieved from http://
norvig.com/21-days.html.
Novick, L. R. in Holyoak, K. J. (1991). Mathematical problem solving analogy. Journal of
Experimental Psychology: Learning, Memory, and Cognition, 17(3), 398–415.
Proserpio, L. in Gioia, D. A. (2007). Teaching the Virtual Generation. Academy of
Management Learning and Education, 6, 69–80.
Rhem, J. (1998). Problem-Based Learning: An Introduction. The National Learning and
Teaching Forum. 8(1).
86
Robins, A., Rountree, J., & Rountree, N. (2003). Learning and teaching programming: a review
and discussion. Computer Science Education, 13(2), 137–172.
Savery, J. R. (2006). Overview of Problem-based Learning: Definitions and Distinctions.
Interdisciplinary Journal of Problem-Based Learning, 1(1).
Sedighian, K., & Sedighian, A. (1996). Can educational computer games help educators learn
about the psychology of learning mathematics in children? In 18th Annual Meeting of the
International Group for the Psychology of Mathematics Education - The North American
Chapter, Florida, USA (1996).
Sharp, L. (2012). Stealth learning: Unexpected learning opportunities through games. Journal
of Instructional Research, 87, 42–48.
UNESCO. (2013). Final recommendations towards knowledge societies. Geneva: Author.
Vygotsky, L. (1978). The development of higher psychological processes. Cambridge,
England: Harvard University Press.
Weber, G. (1996). Individual Selection of Examples in an Intelligent Learning Environment.
Journal of Artificial Intelligence in Education.
Wing, J. M. (2006). Computational thinking. Communications of the ACM, 49(3), 33–35.
Winslow, L. E. (1996). Programming pedagogy – A psychological overview. SIGCSE Bulletin,
28, 17–22.
Xinogalos, S., 2014. Designing and deploying programming courses: Strategies, tools,
difficulties and pedagogy. Education and Information Technologies, 1–30.