Maailmantutkijan kasvatuskirja

Luku 7: Ohjelmoinnin alkeet

7.3 Jos-ehto

Tarvikkeet Kynä ja A4-paperia. Paljon paperilappuja (esim. muistilappuja).

Ohjeet

Aiempien komentojen lisäksi nyt on käytössä uusi jos-komento.

Uusi komento: Jos. Jos-komentoa käytetään seuraavasti:

jos a < b:
    a → c

Tämä kirjoittaa lapun $a$ luvun lappuun $c$ jos lapussa $a$ oleva luku on pienempi kuin lapun $b$ luku.

Jos-lausekkeissa saa siis käyttää vertailuoperaatioita: $a < b$, $a > b$, $a = b$, $a \le b$, $a \ge b$.

Uusien komentojen määrittely. Lisäksi lapsi saa nyt määritellä omia komentojansa sen jälkeen, kun hän on kerran osannut toteuttaa ne itse. Esimerkiksi viime osiossa keksittiin, että lappujen $a$ ja $b$ kertolaskun saa tehtyä seuraavasti:

0 → c
toista a:
    b + c → c

Nyt kun lapsi osaa tehdä tämän, ei samaa asiaa tarvitse kirjoittaa joka kerta uudestaan, vaan hän käyttää kertolaskun merkitsemiseksi merkintää $×$ tai $\ast$ tai $⋅$, kuten alla:

a * b → c

Vastaavasti esimerkiksi kolmen luvun yhteen laskeminen tehtiin jo aiemmin, joten on kohtuullista ottaa käyttöön komennot kuten $a + b + c \to d$. (Lyhennysmerkintöjä käytettäessä pitää kuitenkin aina pystyä kirjoittamaan sama asia kokonaan auki.)

Aktiviteetti 1: sääntöjen ymmärrys

Tässä on taas kolme komentosarjaa, joilla voi testata ymmärrystä uudesta jos-komennosta. Pyydä lasta selittämään, mitä sarjoissa tapahtuu ja miten lapuissa olevat luvut muuttuvat. Keksi jälleen lisää, jos nämä tuottavat vaikeuksia tai epäselvyyksiä.

2 → a
3 → b
jos a < b:
    a + 2 → a
jos a < b:
    a + 3 → a
jos a ≤ b:
    a → c
jos a > b:
    b → c
0 → a
0 → b
toista 30:
    jos a < 10:
        a + 1 → a
    b + 1 → b

(Ensimmäisessä sarjassa ensimmäinen jos-ehto toteutuu, ja $a$:n lukua kasvatetaan kahdella. Tämän seurauksena toinen jos-ehto ei enää toteudu ja siten komentoa $a + 3 \to a$ ei suoriteta. Toinen sarja kirjoittaa pienemmän lappujen $a$ ja $b$ luvuista lappuun $c$. Kolmannessa sarjassa toistosilmukassa lapun $b$ lukua kasvatetaan aina. Lapun $a$ lukua kasvatetaan vain ensimmäisellä kymmenellä kerralla, kunnes luku on $10$. Siis sarjan lopuksi $a$:ssa lukee $10$ ja $b$:ssä lukee $30$.)

Aktiviteetti 2: peruspalikoita

Näillä komennoilla saa kasattua monenlaisia hyödyllisiä peruspalikoita, joita ei vielä aiemmilla komennoilla saanut rakennettua.

  1. Kirjoita komentosarja, joka kirjoittaa lapulle $d$ pienimmän luvun, joka lukee lapuissa $a, b$ ja $c$.
  2. Kirjoita komentosarja, joka kirjoittaa lapulle $c$ lappujen $a$ ja $b$ lukujen vähennyslaskun. (Voi olettaa, että lapussa $a$ oleva luku on vähintään yhtä suuri kuin $b$:n.) Tämän tehtävän jälkeen lapsi saa käyttää vähennyslaskukomentoa suoraan seuraavasti: $a - b \to c$. Tätä komentoa saa myös käyttää luvuilla ($a - 2 \to c$), koska tämän voisi tehdä kirjoittamalla $2 \to b$ ja sitten $a - b \to c$.
  3. Kirjoita komentosarja, joka kirjoittaa lapulle $c$ jakolaskun tuloksen, kun lapun $a$ luku jaetaan lapun $b$ luvulla. Tässä saa olettaa, että $b$:n luku jakaa $a$:n. (Tämän jälkeen lapsi saa käyttää jakolaskukomentoa: $\frac{a}{b} \to c$ tai $a/b \to c$ tai $a ÷ b \to c$.)
  4. Kirjoita komentosarja, joka kirjoittaa lapulle $c$ luvun $1$ jos $a$ on jaollinen luvulla $b$ ja joka muuten kirjoittaa lapulle luvun $0$. (Tämän jälkeen lapsi saa käyttää jos-komentoja muotoa “jos $b$ jakaa $a$”.)

Aktiviteetti 3: järjestäminen

Tässä tehtävässä lapsen tavoitteena on järjestää annetut luvut pienimmästä suurimpaan. Edellisessä osiossa oli tehtävä, jossa piti vaihtaa kahden lapun luvut toisin päin. Tämä onnistui komentosarjalla

a → c
b → a
c → b

Lyhennetään tämä komentosarja yksinkertaisesti muotoon

a ⟷ b

Nyt kahden lapun luvut saisi järjestettyä seuraavasti:

jos a > b:
    a ⟷ b

Lapsen tehtävänä on kirjoittaa komentosarja, jolla saa järjestettyä kolmen lapun $a, b$ ja $c$ luvut. Komentosarjan pitää toimia kaikissa mahdollisissa tapauksissa. Tätä voi testata niin, että vanhempi tutkii komentosarjaa, miettii sen toimivuutta ja yrittää sitten keksiä tapauksen, jossa se toimii väärin. Jos vanhempi ei onnistu, ratkaisu toiminee kaikissa tapauksissa ja ratkaisu hyväksytään.

Voitte kokeilla samaa myös useammalla lapulla. Lapsen voi myös haastaa käyttämään mahdollisimman pienen määrän jos-komentoja.

Aktiviteetti 4: hankalia ongelmia

Nyt käytössä olevilla komennoilla saa ratkaistua monimutkaisiakin ongelmia. Tässä on muutama, joista voit valita lapselle kiinnostavia ja sopivan haastavia:

  1. Kirjoita komentosarja, joka laskee, monellako tavalla $10$ samanlaista palloa voi jakaa kolmen ihmisen kesken.
  2. Kirjoita komentosarja, joka laskee, monellako tavalla $20$ pitsatäytteestä voi valita kolme täytettä. (Samaa täytettä ei saa valita useampaan kertaan ja täytteiden järjestyksellä ei ole väliä.)
  3. Kirjoita komentosarja, joka laskee, kuinka monta kertaa paperi pitää taittaa, jotta siinä on yli miljoona kerrosta. Toisin sanoen laske, mikä on pienin luku $n$, jolla $2^n$ on suurempi kuin miljoona.
  4. Kirjoita komentosarja, joka laskee, montako lukua $100$ pienempää alkulukua on olemassa. (Jos lapsi ei vielä tiedä, mitä alkuluvut ovat, hyppää tämän esimerkin yli. Voitte palata alkulukuihin ja lukujen tekijöihinjakoon jossakin muussa tilanteessa.)

Selitys

Uuden jos-komennon avulla voi ratkoa monia sellaisia ongelmia, joita aiemmin ei voinut. Esimerkiksi nyt on saatu rakennettua kaikki peruslaskutoimitukset (yhteen-, vähennys-, kerto- ja jakolasku).

Lapsi saattaa ihmetellä, miksi näitä komentosarjoja kirjoitetaan. Eikö niitä ole ihan mahdottoman työlästä suorittaa? Tätä kysymystä käsitellään tarkemmin seuraavassa osiossa.

Ratkaisuja

Pienin luku: Pienimmän lapuissa $a, b$ ja $c$ esiintyvän luvun saa laskettua seuraavasti:

a → d
jos b < d:
    b → d
jos c < d:
    c → d

Tämä laittaa lappuun $d$ aluksi lapun $a$ luvun ja sitten kokeilee, onko lappujen $b$ tai $c$ luvut pienempiä. Jos on, pienempi luku kirjoitetaan lapulle $d$.

Vähennyslasku: Vähennyslaskun voi laskea seuraavasti:

0 → c
toista a:
    jos b < a:
        c + 1 → c
        b + 1 → b

Tämä kasvattaa $b$:n lukua yksitellen, kunnes $b$:n luku on yhtä suuri kuin $a$:n. Lapun $c$ luku pitää kirjaa siitä, montako kertaa $b$:tä on pitänyt kasvattaa, jotta luku on yhtä suuri kuin $a$:n. Se on siis lukujen vähennyslasku.

Jakolasku: Jakolaskun saa laskettua kertolaskun avulla seuraavasti:

1 → d
toista a:
    b * d → e
    jos a = e:
        d → c
    d + 1 → d

Tässä $d$ käy läpi luvut $1, 2, \ldots , a$. Joka kerralla tarkistetaan, onko nykyinen lapun $d$ luku jakolaskun tulos, eli päteekö $b ⋅ d = a$. (Tämä tehdään lisälapun $e$ avulla, jotta ei tarvitse kirjoittaa jos-komentoa “$\text{jos } a = b ⋅ d$”, jossa esiintyy kertolasku.) Jos se on, vastaus kirjataan lappuun $c$.

Jaollisuus: Jaollisuus onnistuu hyvin samanlaisella komentosarjalla:

0 → c
1 → d
toista a:
    b * d → e
    jos a = e:
        1 → c
    d + 1 → d

Ainoa ero on, että vastauksen sijaan lappuun $c$ kirjoitetaan $1$, jos vastaus löytyi.

Järjestäminen: Kolmen lapun luvut saa järjestettyä seuraavalla komentosarjalla:

jos a > b:
    a ⟷ b
jos a > c:
    a ⟷ c
jos b > c:
    b ⟷ c

Näistä ensimmäiset kaksi vaihtoa varmistavat, että lapusta $a$ löytyy pienin luku. Viimeinen vaihto vielä varmistaa, että lappujen $b$ ja $c$ luvut ovat oikein päin. Komentosarja on lyhyin mahdollinen: kahdella vertailulla ongelmaa ei pysty ratkaisemaan, vaan silloin jäisi aina jokin tapaus, jossa luvut eivät järjesty oikein.

Yksi tapa tarkistaa, että komentosarja varmasti toimii, on kokeilla sen toiminta niissä kuudessa eri tapauksessa, joissa laput sisältävät luvut $1, 2$ ja $3$ jossakin järjestyksessä.

Sama strategia toimii myös neljällä lapulla: siirretään ensin pienin luku lappuun $a$. Jäljelle jäävät kolme lappua saadaan järjestettyä tismalleen samaan tapaan kuin yllä.

jos a > b:
    a ⟷ b
jos a > c:
    a ⟷ c
jos a > d:
    a ⟷ d
jos b > c:
    b ⟷ c
jos b > d:
    b ⟷ d
jos c > d:
    c ⟷ d

Ensimmäiset kolme vaihtoa siis varmistavat, että lapussa $a$ on pienin luku. Seuraavat kaksi varmistavat, että lapussa $b$ on toiseksi pienin luku. Viimeinen vaihto varmistaa lappujen $c$ ja $d$ lukujen olevan oikein päin.

Nokkelammalla ratkaisulla saman saa tehtyä vain viidellä vertailulla.

jos a > b:
    a ⟷ b
jos c > d:
    c ⟷ d
jos b > d:
    b ⟷ d
jos a > c:
    a ⟷ c
jos b > c:
    b ⟷ c

Ei ole aivan helppo selittää, miksi tämä komentosarja toimii, mutta ensimmäiset kaksi vertailua varmistavat, että laput $a$ ja $b$ ovat oikein päin, kuten myös $c$ ja $d$. Kolmas vertailu varmistaa, että lappuun $d$ tulee suurin luku. Viimeiset kaksi komentoa järjestävät laput $a, b$ ja $c$. On oleellista, että ensimmäisen kolmen komennon jälkeen lappujen $a, b$ ja $c$ luku järjestyksestä “tiedetään” jotakin, nimittäin se, että lapun $b$ luku ei ole pienin näistä kolmesta luvusta (paitsi mahdollisesti jaetulla sijalla). Tämä mahdollistaa näiden kolmen lapun järjestämisen vain kahdella komennolla.

Viisi vertailua on pienin määrä: mikään neljän vertailun komentosarja ei toimi oikein kaikissa mahdollisissa tapauksissa.

Kymmenen pallon jakaminen kolmelle hengelle: Voimme käydä läpi mahdollisia tapoja jakaa pallot. Jokainen saa vähintään nolla ja enintään kymmenen palloa. Lisäksi yhteensä palloja jaetaan kymmenen kappaletta. Seuraavassa komentosarjassa laput $a$, $b$ ja $c$ vastaavat mahdollista pallojen jakoa, lappuun $d$ lasketaan jaettujen pallojen määrä ja lapussa $e$ lasketaan kelpaavien jakojen määrä.

0 → e
0 → a
toista 11:
    0 → b
    toista 11:
        0 → c
        toista 11:
            a + b + c → d
            jos d = 10:
                e + 1 → e
            c + 1 → c
        b + 1 → b
    a + 1 → a

Kahdestakymmenestä pitsatäytteestä kolmen valitseminen: Täytteet voi numeroida luvuin $1, 2, \ldots , 20$. Täytteet voi siten esittää kolmella luvulla, esimerkiksi $3, 8$ ja $15$. Pitää varoa, että samaa täyteyhdistelmää ei lasketa useampaa kertaa (esim. $3, 8, 15$ ja $8, 3, 15$). Tämä saadaan varmistettua niin, että täytteiden numerot aina kasvavat. Alla komentosarjassa $a$, $b$ ja $c$ ovat täytteet ja $d$ pitää kirjaa kelpaavien yhdistelmien määrästä.

0 → d
1 → a
1 → b
1 → c
toista 20:
    toista 20:
        toista 20:
            jos a < b:
                jos b < c:
                    jos c ≤ 20:
                        d + 1 → d
            c + 1 → c
        b + 1 → b
    a + 1 → a

Pienin luku $n$, jolla $2^n$ ylittää miljoonan: Tässä voi yksinkertaisesti laskea $2^n$ kasvavilla luvuilla $n$ ja pysähtyä, kun löydetään riittävän suuri luku.

1 → b
0 → c
toista 1000:
    jos b ≤ 1000000:
        b * 2 → b
        c + 1 → c

Alkulukujen laskeminen: On kätevintä ensin määritellä komento, joka kertoo, onko luku alkuluku vai ei. Seuraava komentosarja kirjoittaa lappuun $b$ luvun $1$, jos lapun $a$ luku on alkuluku, ja muutoin $0$. (Luku $1$ ei ole alkuluku, ja se käsitellään ohjelmassa erikseen.)

1 → b
jos a = 1:
    0 → b
2 → c
toista a:
    jos c jakaa a:
        jos c < a:
            0 → b
    c + 1 → c

Nyt voimme laskea, montako alkulukua on alle sadan.

0 → d
1 → a
toista 99:
    jos a on alkuluku:
        d + 1 → d
    a + 1 → a

Vaikka se olisi hieman sotkuisempaa, nämä kaksi komentosarjaa voisi myös kirjoittaa yhtenä. Komentojen määrittely aiemmista komentosarjoista on sallittua vain käytännöllisyyden vuoksi, ja sillä ei siten saa tehtyä mitään “uutta”, mitä ei voisi tehdä muuten. Kokonaisuudessaan komentosarja näyttäisi tältä:

0 → d
1 → a
toista 99:
    1 → b
    jos a = 1:
        0 → b
    2 → c
    toista a:
        jos c jakaa a:
            jos c < a:
                0 → b
        c + 1 → c
    jos b = 1:
        d + 1 → d
    a + 1 → a