otanhan minä jalustan- videon tuottamista pikaisella aikataululla

Itsenäisyysjuhlaviikonlopun perjantaiaamuna seitsemän pintaan Whatsuppiini kilahti viesti Hyllin musiikinopettajalta Eriikalta – koulussa on pieni hätä. Soitin. Hyllin ylioppilasjuhliin oli tilattu ammattilainen kuvaamaan ja julkaisemaan Hyllin itsenäisyysjuhla. Molemmat tekijät olivat sairastuneet koronaan.

alku

Vielä unihiekkaa silmissä kerroin, että onhan siellä henkilöitä koulussa, joilla olisi nyt näytön paikka. Pohdittiin myös mahdollisia naapurin lukiolaisnaapureita ja serkunpojanäitejä, jotka voisivat hoitaa asian. Ajattelin itse pitää oppituntini normaalisti kotoa koronaeristyksestä.

Kun olin juonut aamukahvini ja hieman ajatellut asiaa, niin päätin, että jos kerran Eriikka kantaa varsinaisen, niin otanhan minä jalustan. Toisaalta ylioppilaissa oli monta oman ryhmäni oppilasta ja esiintyjät olivat harjoitelleet juhlaa varten. Noiden oppilaiden takiahan tätä työtä tehdään. Soitin rehtori Jussille ja kerroin että lähden ajelemaan koululle. Ennen lähtöä ehdin laittaa Classroomviestin ensimmäisen tunnin oppilaille, että laskekaa jotain. Lähtiessä tarkistin, että kaikki on mukana, mutta silti unohdin oman kamerani jalustan. Matkalla muistin sen. Tiesin, että kuviksessa on parikin jalustaa, mutta aina ei voi olla varma, että löytyykö ne helposti. Päätin myös, että vaikka kuinka paljon tilanne kiukuttaisi, niin en kiukuttele oppilaille ja yritän pitää positiivista henkeä yllä itselläni ja koko tiimillä.

Olin koululla noin puoli kahdeksan. Jarno soitteli ja tarjosi apua, kerroin pyytäväni, kun tarvitsen. Kun pääsin koululle, niin pyysin Samia hakemaan kuviksesta jalustan. Juhlasalissa näin, että joku, luultavasti Jorma oli käynyt hakemassa kukkia koristeluun, Tarja oli koristelemassa puhujapönttöä ja lakkiaispöytää. Eriikka ja Jussi olivat jo valmiina juhlasalissa. Aloitin Meetin ekan tunnin oppilaille, kerroin tilanteesta. Samalla laitoin viestiä toisen tunnin oppilaille, että en ole paikalla opettamassa.

kuvaus

Sami auttoi näyttämön valaistuksen kanssa ja Jorma sammutti ilmastoinnin. Varsinaiseen kuvaukseen päästiin noin 8.50. Parin testivideon jälkeen saatiin Jussin tervetulotoivotus ja puhe purkkiin. Tässä vaiheessa huomasin, että kameran akku on lopussa. Onneksi minulla on kamerakassissa toinen akku ja laturi, niinpä pystyin kuvauksien aikana latailemaan akkuja sitä mukaa kun ne tyhjenivät. Jussin puhe onnistui ensimmäisellä otolla. Tässä vaiheessa kello oli 9.30.

Koska en harrasta videokuvausta, niin hankaluuksia tulee mm. siitä, että minulla ei ole kokemuksia aukon säätämisestä videon yhteydessä yms. eli on pakko käyttää automaattiasetuksia. Toisaalta en voi käyttää automaattitarkennusta, koska se aiheuttaa videoon ääniä, jos kamera tarkentaa. Olen tottunut tarkentamaan normiokulaarista, niinpä kuvan tarkentaminen pikkunäytöltä on haastavaa. Vanhaa Nikon 5100-kameraa ei ole varsinaisesti suunniteltu videokuvaukseen. Myöskään keväällä hankkimani mikrofoni ei ole maailman parhaasta päästä.

Sitten oli vuorossa ylioppilaiden lakitus ja Gaudeamus Igidur tämänkin saimme nauhoitettua ensimmäisellä otoksella. Kello oli 10.52.

Seuraavaksi kuvattiin ylioppilaiden puhe, sekin onnistui yhdellä otolla. Kuvauksen aikana huomasin, että olin rajannut kuvan hölmösti, kuvasin lähinnä puhujapönttöä, en Ainoa ja Miikaa. Tässä vaiheessa kello oli noin 10.05. Kun laulajat ja bändi valmistelivat esityksiään otin muutamia kuvia. Arvelin, että kuville voi olla käyttöä itse videossa.

Tiituksen flyygelillä soittama kappale meni ensimmäisellä otolla. Kello oli tässä vaiheessa 10.17, tajusin, että alkaa tulla kiire.

Karjalan kunnailla (2 ottoa), se englannikielinen kappale, jonka nimeä en muista ja Himlen i min famn ja Maammelaulu olivat tallennettuna 10.52. Näiden kuvan laatua en ehtinyt tarkistaa, sillä piti lähteä leikkaamaan. Vein Eriikan tuottaman ohjelman Jussille ja pyysin, että joku tekee aiheesta uutisen koulun sivuille.

leikkaus

Pääsin aloittamaan leikkaamisen noin 11.00. Siirsin videoklipit MacBookPro:lleni iMovie-ohjelmaan ja siirtelin ne paikoilleen. Tässä vaiheessa huomasin, että yksi laulutiedosto oli rikki, veikkaan, että koska akku oli ollut välillä aika tyhjänä, niin tiedosto oli vioittunut.  Myös Maammelaulun tarkennus oli ikävästi pielessä. Lisäsin videon tilalle ottamiani valokuvia. Jokaisen klipin alusta ja lopusta leikkasin pois omat höpötykseni ja lisäsin siirroksen, häivytys mustaan. Rajasin Ainon ja Miikan puheen paremmaksi, tietäen että aiheuttaa videoon rakeisuutta. Lopuksi lisäsin alku- ja lopputekstit. Tässä vaiheessa kello oli 11.45. Tarkistin vielä kerran alun, siirroksien reunat ja lopun, korjasin pari ylimääräistä äännähdystä, jotka vielä olivat jääneet huomaamatta alkuperäisessä leikkauksessa. Video oli reilut puoli tuntia, iMovie tallensi sen mp4-tiedsotoksi alle 10 minuutissa.

youtube

Aloin siirtämään tiedostoa koulun YouTube-tilille. Kun kirjauduin sivulle, niin YouTube oli saksankielinen. Jos Hylliä etsi YouTuben sisältä, niin käyttöliittymä pysyi saksalaisena. Kun hain sanoilla youtube helsingin yhteislyseo, niin päädyin suomenkieliselle sivulle. Aloin tiedoston siirron. Tässä vaiheessa Jarno tuli auttamaan minua, sillä olin jo aika väsynyt. En meinannut löytää edes iMoviesta tallentamaani mp4-tiedostoa. Jarno myös tiesi, että kaikista YouTuben ilmoituksista ei pidä välittää. Noin 12.10 Jussi kuulutti, videon saatavuus voi hieman myöhästyä. Klo 10.14 saimme lopulta toimivan YouTube-linkin, jonka lähetimme koulun opettajille. Samalla linkki julkaistiin koulun vanhoilla (nämä näkyivät Helsingin opetusverkossa varmaankin jonkin välimuistin takia) ja uusilla kotisivuilla (minä pääsin ulkomaailmaan Freedomen avulla). 

Klo 10.15 käytävältä alkoi kuulua videon ääniä. Peruskoulun opettajat näyttivät videon omilta koneiltaan oppilaille. Samalla tajusin, että olin unohtanut oman opetusryhmäni. Kun menin ryhmäni Meetiin, huomasin, että Jesse oli paikkaamassa poissaoloani, kiitokset siitä.

Tässä vaiheessa huokaisin helpotuksesta. Onnistuin. 

opetuksia

Tämä ei olisi onnistunut, elleivät esiintyjät olisi valmistautuneet esityksiinsä huolella. Toisaalta se, että minulla oli mielessäni jonkinlainen suunnitelma aikataulusta ja pidin kiinni siitä, mahdollisti tuotoksen ajallisesti. Myös se, että niin moni henkilö toimi avustajana auttoi. Jos olen unohtanut mainita jonkun tuotantoon osallistuneen nimen, niin pyydän anteeksi.

Päätin, että en enää ikinä kuvaa ”virallisia” videokuvauksia ainakaan näillä välineillä. Meille pitää hommata asialliset kuvausvälineet, kouluttaa oppilaista kuvaajia ja leikkaajia. Kannattaisi hankkia myös tehokas Mac ja siihen Final Cut-ohjelma. Toki iMoviella pystyy helposti tekemään tällaisia projekteja, mutta tiedän iMovien rajallisuuden oikeissa isommissa projekteissa.

Kotona huomasin, että olin sittenkin siirtänyt videon omalle YouTube-tililleni. Tämä pitää korjata lähipäivinä. Jonkun hylliläisen somehenkilön pitää ottaa haltuun tilin hallinnointi. 

Kirjoitin tämän lähinnä itselleni muistiinpanoksi. Ehkä tästä lukijakin voi jotain oppia.

Lopullinen video löytyy YouTubesta. https://youtu.be/Q9iNEhwR2DI

Kombinatorinen ongelma Pythonilla

Eri vaihtoehtojen lukumäärien laskeminen käsin on suhteellisen hidasta. Esitän tässä, miten käytin Python ohjelmointikieltä pienen käytännön ongelman ratkaisemiseen. Samalla kerron miten minun aivoni pikkuhiljaa kehittivät parempia ratkaisuja ongelman ratkaisuun.

Ongelman kuvailu

Ystäväni, kutsutaan häntä vaikka nimellä Jussi, pyysi minua auttamaan erään konferenssin järjestelyissä. Ilmoittautumisen yhteydessä osallistujilta oli kysytty mihin kahteen työpajaan he haluaisivat ilmoittautua kahdeksasta eri vaihtoehdosta. Konferenssitilassa on neljä huonetta, niinpä nuo kahdeksan työpajaa järjestetään siten, että ensin on samaan aikaan neljä rinnakkaista työpajaa ja sen jälkeen loput neljä. Työpajojen väliajalla osallistujat voivat tietysti vaihtaa huonetta. Jussi oli laskenut ilmoittautumisista, millaisia valintoja osallistujat olivat tehneet ja kuinka monta kutakin valintaa oli. Nyt Jussi halusi tietää, mikä olisi paras vaihtoehto eli kokousohjelma, järjestää nuo kahdeksan työpajaa neljän ryhmissä. 

Jussi antoi minulle valinnat Excel-tiedostona, esitän tässä luvut Pythonin listoina muodossa [ensimmäinen valinta, toinen valinta, lukumäärä]. Kahdessa ensimmäisessä alkiossa olevat luvut ovat työpajojen numeroita 1, …, 8. Jos ensimmäinen luku on nolla, niin osallistuja oli valinnut vain yhden vaihtoehdon.

[0, 1, 2], [0, 2, 1], [0, 3, 1], [1, 2, 26], [1, 3, 2], [1, 4, 15], [1, 5, 3], [1, 6, 1], [1, 7, 16], [2, 4, 9], [2, 5, 1], [2, 7, 17], [2, 8, 1], [3, 4, 1], [3, 5, 6], [3, 6, 2], [3, 7, 3], [4, 5, 6], [4, 6, 2], [4, 7, 6], [5, 6, 3], [5, 7, 6], [5, 8, 5], [6, 7, 4], [6, 8, 1], [7, 8, 2]

ensimmäinen ratkaisu käsin

Kun sain kyseisen Excel-taulukon, otin avukseni kynän ja paperia. Hetken lukuja tuijotettuani, aloin järkeilemään suurin piirtein näin. Eniten on valintoja 1 ja 2. Niinpä niiden tulee olla eri aikaan.

1   
2   

Seuraavaksi eniten on 2 ja 7 eli 7 pitää olla eri puolella kuin 2.

17  
2   

Seuraavaksi eniten on 1 ja 7, mutta ne ovat jo taulukossa. Seuraavaksi on 1 ja 4, niinpä 4 tulee alemmalle riville.

17  
24  

Näin jatkaen päädyin taulukkoon

1756
2438

Laskin kuinka monta osallistujaa voi tällä tavoin järjestettynä osallistua haluamiinsa työpajoihin ja sain tulokseksi 98. Kokeilin muutamalla muulla eri tavalla ja en keksinyt parempaa valintaa.

Mieltäni jäi kuitenkin vaivaamaan, että jos sittenkin olisi jokin toinen kombinaatio, jossa saisi työpajat sopimaan suuremmalle osallistujamäärälle.

lukumäärän laskeminen

Päätinpä siis alkaa koodaamaan. Ensin laskin eri vaihtoehtojen lukumäärän. Samalla hahmottelin ohjelmaa päässäni. Jos raa’alla voimalla tekisi jokaisen mahdollisen ”lukujärjestyksen”, niin niitä tulisi olemaan 8! = 40320. Toki koneella laskien tuo onnistunee nopeasti, mutta ohjelmoidessa saa ja tulee käyttää myös järkeä. 

Loppujen lopuksihan on sama missä järjestyksessä kumpikin rivi on. Ensimmäisen rivin työpajat voivat olla jälkimmäisenä ja toisen rivin ensimmäisenä. Toisaalta ensimmäisen rivin jäsenet voivat olla missä järjestyksessä tahansa. Tällä tavoin ajatellen jos valitaan ensin kaikki mahdolliset neljän mittaiset kombinaatiot, niin näitä tulee nCr(8, 4) = 70 kappaletta ja jos jokaiseen liitetään jäljellä olevista luvuista permutaatiot joita on 4! = 24, niin eri vaihtoehtoja tulee olemaan 70*24 = 1680 kappaletta.

python koodin eka suunnitelma

Tein mielessäni ja paperilla suunnitelman Python ohjelmasta.

  • tuota vaihtoehdot
    • luo permutaatiot ekaksi riviksi taulukossa
    • määritä jäljelle jäävä nelikko joukko-opillisena erotuksena 
    • luo kombinaatiot alemmaksi riviksi
    • yhdistä yhdeksi listaksi
  • määrät listaksi
  • luo summa muuttuja
  • laske määrät summaan
    • tähän tulee hankala if-lause
  • luo tuloslista

Avasin Anaconda/Spyder-ohjelmoitiympäristön. Googlettelin aika paljon, jotta löysin tarvittavat apuohjelmat ja komennot, mutta muutamassa tunnissa ohjelma tuotti 1680 tulosta, joiden avulla pystyi valitsemaan parhaat aikataulut. Hankalin vaihe oli keksiä tarvittava if-lause, jonka avulla sai pääteltyä, pääseekö molempiin valitsemiinsa ohjelmiin. Alla on kyseinen for-silmukka, jolla varsinainen lasku suoritettiin. 

for j in range(1680):
for li in maarat:
   if(((li[0]==0 or (li[0] in listojenlista[j][0])) and (li[0]==0 or (li[1] in listojenlista[j][1]))) or ((li[0]==0 or (li[1] in listojenlista[j][0])) and (li[0]==0 or (li[0] in listojenlista[j][1]))) ):
        summa[j]+=li[2]

Oma alkuperäinen kynällä ja paperilla tuotettu aikatauluni oli tasapisteissä parhaana. Niinpä lähetin eri vaihtoehtojen lukumäärät Jussille. Tehtävä suoritettu.

aivotoimintaa

Jotenkin mieleeni jäi kaihertamaan, että olisi tuon voinut tehdä elegantimminkin. Pari päivää myöhemmin illalla, aloin pohdiskelemaan ongelmaa ja vilkaisin tuottamaani koodia. Ajattelin, että tuo if-lausehirvitys pitäisi sieventää nätimmäksi ihan harjoituksen vuoksi. Mutta sitten telkkarista tuli jotain tärkeää ja unohdin asian. Seuraavana yönä heräsin ja tajusin, että koko jutun voi tehdä paljon helpommin. 

Aikataulunhan määrää nuo ensimmäisen rivin luvut. Toisella rivillä ovat ne luvut, jotka eivät ole ensimmäisellä rivillä. Näin tutkittavia listoja tulee olemaan vain 70 kappaletta. Kirjoitin ajatukseni muistiin aamulla, mutta en palannut asiaan, kun oli kaikkia muita kiireitä, pitäähän opettajan käydä koululla opettamassa. Pari päivää myöhemmin aamusuihkussa oivalsin yksinkertaisemman tavan, miten if-lause kannattaa kirjoittaa. Ihmisen aivot toimivat kummallisesti.

lopullinen koodi

Näytän alla lopullisen koodin ilman kommentointia, kommentoin rivejä koodin lopussa.

rivit 1-5: Spyderin tuottamaa metatietoa

rivi 7: Goolettamalla löysin tiedon, että kombinaatiot saa tuotettua itertools-kirjaston combinations funktiolla.

rivi 9: range(1,9,1) tuottaa listan [1, 2, …, 8], combinations(range(1,9,1),4) tuottaa näistä listan, jossa ovat kaikki 70 kombinaatiota tyyliin [(1, 2, 3, 4), (1, 2, 3, 5), …, (4, 6, 7, 8), (5, 6, 7, 8)].

rivi 10: map(list, ekattuplet) muuntaa monikot (tuplet) (1, 2, 3, 4) listoiksi. Combinations-komennon jäljiltä edellä esitetty lista on tyypiltään iterable (mitähän tämä on suomeksi), se muuttuu todelliseksi listaksi tyyliin [[1, 2, 3, 4], …, [5, 6, 7, 8]] list-funktiolla. Map on saman tyyppinen komento kuin GeoGebran Zip, sillä saa toistettua komennon syötelistan jokaiselle alkiolle. Koodin olisi saanut toimimaan, vaikka listan alkiot olisivat olleet monikkoja, mutta halusin testata map-komentoa :o)

rivi 11-14 Valinnat ja vastaavat määrät, kuten luvussa ”Ongelman kuvailu” on esitetty. Kenoviiva katkaisee rivin.

rivit 16-18: Luodaan summa-lista = [0, 0, 0, …0]. Sinne kerrytetään ekatlistan alkioihin sopivien osallistujien lukumäärien summat.

rivit 20-21: Sisäkkäiset silmukat, jossa käydään läpi jokainen ekatlistan alkio ja lasketaan niille kullekin, miten maaratlistan valinnat sopivat.

rivi 22-23: Jos maarat-listassa on 0, niin valinta kelpaa, lisätään osallistujien määrä summaan.

rivi 24-27: Varsinainen ehtorivi. Tässä selvitetään, onko vain jompikumpi valinnoista ekassa listassa. Ehtolause on ehkä hieman paremmin luettavissa, jos sen rivittää eri riveille

rivit 29-31: Yhdistetään ekatlistan järjestykset ja niitä vastaavat summat yhdeksi, jotta ne saa järjestettyä suuruusjärjestykseen. Metodi append lisää listan perään alkioita.

rivi 33: Järjestetään tuloslista summien mukaiseen järjestykseen.

rivit 35-36: Tulostetaan lopputulos.

Koodin tuottama lopputulos on tämän tarinan lopussa.

jatkopohdintaa

Tällaiset pienet ongelmat pitävät ainakin minun aivoni virkeinä. Tätä kirjoitettaessa tuli mieleen, parikin uutta pohdinnan aihetta. Mitä jos kaikki 148 osallistujaa olisivat tehneet valintansa satunnaisesti, mikä tällöin olisi ollut parhaan aikataulun osallistujien lukumäärä ja vastaavasti heikoimman. Pitänee tehdä simulointi tai sitten yrittää laskea todennäköisyyslaskennan avulla.

Lähteet

Itertoolsin komennot, combinations https://docs.python.org/2/library/itertools.html

Map-komento https://docs.python.org/3/library/functions.html#map

Hyvät esimerkit Mapistä https://www.w3schools.com/python/ref_func_map.asp

Sorting How to https://docs.python.org/3/howto/sorting.html

Koodi Replissä https://repl.it/@MikkoRahikka/jussinongelma#main.py

Ohjelman tuotos

([1, 3, 7, 8], 98)

([1, 5, 6, 7], 98)

([2, 3, 4, 8], 98)

([2, 4, 5, 6], 98)

([1, 2, 5, 6], 96)

([1, 5, 7, 8], 96)

([2, 3, 4, 6], 96)

([3, 4, 7, 8], 96)

([1, 6, 7, 8], 95)

([2, 3, 4, 5], 95)

([1, 3, 4, 8], 93)

([1, 3, 5, 7], 93)

([1, 5, 6, 8], 93)

([2, 3, 4, 7], 93)

([2, 4, 6, 8], 93)

([2, 5, 6, 7], 93)

([1, 3, 6, 7], 92)

([2, 4, 5, 8], 92)

([1, 3, 6, 8], 91)

([1, 4, 7, 8], 91)

([2, 3, 5, 6], 91)

([2, 4, 5, 7], 91)

([1, 3, 5, 6], 90)

([1, 4, 6, 8], 90)

([2, 3, 5, 7], 90)

([2, 4, 7, 8], 90)

([1, 2, 3, 5], 89)

([1, 4, 5, 6], 89)

([2, 3, 7, 8], 89)

([4, 6, 7, 8], 89)

([1, 2, 5, 8], 88)

([1, 3, 4, 7], 88)

([1, 3, 5, 8], 88)

([2, 4, 6, 7], 88)

([2, 5, 6, 8], 88)

([3, 4, 6, 7], 88)

([1, 3, 4, 6], 87)

([1, 4, 5, 8], 87)

([2, 3, 6, 7], 87)

([2, 5, 7, 8], 87)

([1, 2, 3, 6], 86)

([1, 2, 3, 8], 86)

([1, 4, 5, 7], 86)

([2, 3, 6, 8], 86)

([4, 5, 6, 7], 86)

([4, 5, 7, 8], 86)

([1, 2, 6, 8], 85)

([1, 4, 6, 7], 85)

([2, 3, 5, 8], 85)

([3, 4, 5, 7], 85)

([1, 3, 4, 5], 84)

([2, 6, 7, 8], 84)

([1, 2, 4, 5], 70)

([3, 6, 7, 8], 70)

([1, 2, 3, 4], 68)

([5, 6, 7, 8], 68)

([1, 2, 4, 6], 67)

([1, 2, 4, 8], 67)

([1, 2, 5, 7], 67)

([3, 4, 6, 8], 67)

([3, 5, 6, 7], 67)

([3, 5, 7, 8], 67)

([1, 2, 3, 7], 61)

([4, 5, 6, 8], 61)

([1, 2, 6, 7], 60)

([1, 2, 7, 8], 60)

([3, 4, 5, 6], 60)

([3, 4, 5, 8], 60)

([1, 2, 4, 7], 36)

([3, 5, 6, 8], 36)