Coding Challenge Grazissa: Ja voittaja on..
Graz Linux Days -tapahtumassa grommunio järjesti paljon kiitosta saaneen koodaushaasteen. 23 osallistujasta 9 pystyi esittämään onnistuneita tuloksia. Arvalla valittu pääpalkinnon voittaja on nyt noutanut palkintonsa grommunion toimistolta.
Kuulostaa oikeastaan aika yksinkertaiselta, eikö vain?
“Tätä tehtävää varten sinun on kirjoitettava C/C++-koodia tiedostoon \src\main.cpp ratkaistaksesi tämän Readme-tiedoston lopussa olevan koodaushaasteen. Käytetään MinGW64:ää gcc/g++ 15.2:lla, joka asetetaan automaattisesti paikalliseen hakemistoon ja jota voidaan käyttää seuraavilla komennoilla. ”
Se, mikä saattaa kuulostaa monista ei-teknisistä ihmisistä käsittämättömältä, ei vaikuta ohjelmoijista vaikealta - ainakaan ensi silmäyksellä. Periaatteessa grommunion neljä tehtävää olivat varmasti ratkaistavissa, ja niinpä 23 Linux-asiantuntijaa otti haasteen vastaan eräänä huhtikuisena lauantaina Grazissa.
Ohjelmointi aikapaineen alla
Monet osallistujat kamppailivat aikarajan kanssa, jonka puitteissa heidän oli löydettävä oikea ratkaisu itse kirjoittamallaan koodilla. Alun perin arvioitu 20 minuuttia osoittautui aivan liian optimistiseksi; jopa 40 minuutin kuluessa vain 9 osallistujaa pystyi löytämään oikean ratkaisun.
Tämän seurauksena Grazin kaksi erityisesti valmisteltua Windows-konetta olivat lauantaina lähes jatkuvasti käytössä, ja itse haasteeseen käytettiin yli seitsemän tuntia.
Koodaushaasteen järjestelyt
grommunion työntekijät olivat luoneet tietokoneisiin uudet käyttäjätunnukset, asettaneet editoriksi VSCoden ja automatisoineet erilaisia komentoja Windowsin cmd-skriptien avulla nopeuttaakseen kääntämistä ja lähettämistä.
“Asetimme pienen HTTP-päätepisteen, joka yhdistettynä haastetietokoneiden shell-skriptiin antoi meille mahdollisuuden luoda jokaiselle osallistujalle henkilökohtaisen syötteen hänen sähköpostiosoitteensa perusteella ja vastata palautteella hänen yrityksistään ratkaista ongelma ”, selittää Fabian Ortner grommuniosta (kuvassa yllä). “Readme-tiedosto sisälsi sitten yksityiskohtaisemman kuvauksen siitä, mitä ohjelmointitehtävässä piti tehdä, ja näin luotiin melko yksinkertainen, automatisoitu prosessi, jotta osallistuminen olisi mahdollisimman helppoa. ”
Mutta “mahdollisimman yksinkertainen” ei kestänyt kauan. Haasteessa osallistujien oli korjattava toimimaton sähköpostipalvelin kirjoittamalla pieni muunnosskripti. README:ssä ensimmäinen neljästä ratkaistavasta tehtävästä alkaa seuraavasti:
“Näyttää siltä, että jokainen rivi sisältää kokonaislukuna 8 merkin kerrannaisia, joten yritetään tulkita nämä yksittäisinä tavuina. Esimerkiksi:
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Tiedämme, että vanha sähköpostipalvelin käytti hyvin yksinkertaista salausmenetelmää sähköpostin viennin jälkeen:
- Kertaa jokainen tekstirivi, eli jokainen tavu
- Suorita jokaiselle riville XOR-salaus avaimella `grommunio` merkki merkiltä
- Jos rivi on pidempi kuin avain, sovita avain yksinkertaisesti uudelleen, alkaen ensimmäisestä merkistä. ”
Seuraavaksi tuli lisää vaatimuksia ja tehtäviä, jotka saivat heidän päänsä todella pyörimään. Vain harvat osallistujat pystyivät keksimään oikeita ratkaisuja.
Mutta niilläkin, jotka eivät onnistuneet, oli jotain, mitä odottaa: lopulta kaikkien osallistujien kesken arvottiin satunnaisesti, kuka saisi luvatun PlayStationin. Voittaja Andreas kutsuttiin noutamaan se Wienissä sijaitsevan DC Towerin 30. kerrokseen, grommunion pääkonttoriin.
Ratkaisu? Sitä ei julkaista täällä, mutta README-tiedosto, jossa on koko ongelman selitys, on saatavilla tämän viestin alla. Ilman palvelinta, jonka grommunio rakensi Graz Linux Days -tapahtumaa varten, se vaatii kuitenkin hieman mielikuvitusta..
Lue lisää grommunion toiminnasta Graz Linux Days -tapahtumassa tästä artikkelista.
Koodaushaasteen ohjeet
Tämä haaste edellyttää, että kirjoitat C/C++-koodia tiedostoon .\src\main.cpp ratkaistaksesi tämän ohjeen lopussa olevan haasteen. Tehtävässä käytetään MinGW64:ää ja gcc/g++ 15.2:ta, joka asetetaan automaattisesti paikalliseen hakemistoon ja jota voidaan käyttää seuraavilla komennoilla.
Mukana olevassa skriptissä on neljä tärkeää komentoa:
1. Sähköpostiosoitteen rekisteröinti ja 20 minuutin ajastimen käynnistäminen:
\glt.cmd start`
2. Voit vain rakentaa koodisi:
.\glt.cmd build: .\glt.cmd build
3. Voit rakentaa ja ajaa koodisi ja tulostaa sen tulosteen terminaaliin:
.\glt.cmd build_and_run: .\glt.cmd build_and_run
4. Voit rakentaa, ajaa ja lähettää ratkaisusi:
.\glt.cmd submit: .\glt.cmd submit
Ratkaisun rakentamiseen käytettävässä komennossa ei ole oletusarvoisesti käytössä mitään optimointeja:
g++.exe -static -O0 -g -std=c++17 src\main.cpp -o build/app.exe
Haaste
Käynnistääksesi haasteen ** ensin** laita sähköpostiosoitteesi tiedostoon user.txt ja käytä sitten komentoa start saadaksesi syötteen. Käytämme sitä vain, jotta voimme ottaa sinuun yhteyttä, jos voitat arvonnan. Sinun tarvitsee vain muuttaa result-muuttujaa koodissasi ja sitten suorittaa submit-komento tarkistaaksesi, onko se oikein.
WOW. Mitä tuolle sähköpostille tapahtui siirron aikana? Yksi sähköpostiviesteistäsi vahingoittui jotenkin uuden sähköpostipalvelimen asennuksen aikana. Se näyttää koostuvan vain binäärisymboleista, jotka on jaettu muutamalle riville (syötteesi). Rivillä näyttäisi olevan kokonaislukuna 8 symbolia, joten yritetään tulkita ne yksittäisinä tavuina. Esimerkiksi:
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Tiedämme, että vanha sähköpostipalvelin käytti todella yksinkertaista salausta sähköpostin viennin jälkeen:
- Otetaan jokainen tekstirivi, eli jokainen tavu
- XOR jokainen rivi grommunio-avaimen kanssa merkkikohtaisesti
- Jos rivi on pidempi kuin avain, käytä avainta uudelleen ensimmäisestä merkistä alkaen.
0x44 ^ g = 0x23 0x51 ^ r = 0x23 0x4A ^ o = 0x25
0x44 ^ g = 0x23 0x50 ^ r = 0x22 0x4C ^ o = 0x23
0x42 ^ g = 0x25 0x51 ^ r = 0x23 0x4C ^ o = 0x23
Tuo näyttää jo lupaavammalta, mutta edelleen on paljon sekavia merkkejä..
Vanhalla postipalvelimella oli jo aiemmin ongelmia yksittäisten merkkiarvojen offsetien kanssa, jolloin offset riippui kahdesta asiasta:
- Sähköpostiosoitteen vaakasuorasta tarkistussummasta
- merkin indeksistä rivillä ja rivinumerosta, jossa merkki on
Tuolloin palvelin laski horisontaalisen tarkistussumman yksinkertaisesti laskemalla yhteen kaikki sähköpostiosoitteesi tavuarvot.
[email protected] => (m=109) + (a=97) + (x=120) + ... = 2888..
Tämän jälkeen jokaiselle merkille laskettiin positiivinen offset ottamalla tarkistussumma modulo sen sijainnin perusteella rivillä. Tämän virheen korjaamiseksi meidän on siis vähennettävä offset-arvot jokaisesta tavusta. Lisäksi näitä offset-arvoja siirretään vasemmalle yhdellä merkillä jokaisen rivin jälkeen.
0x23 - (2888 % 1) = '#' 0x23 - (2888 % 2) = '#' 0x25 - (2888 % 3) = '#'
0x23 - (2888 % 2) = '#' 0x22 - (2888 % 3) = ' ' 0x25 - (2888 % 1) = '#' 0x23 - (2888 % 2) = '#' 0x22 - (2888 % 3) = ' ' 0x25 - (2888 % 1) = '#'
0x23 - (2888 % 3) = '#' 0x23 - (2888 % 1) = '#' 0x25 - (2888 % 2) = '#' 0x23 - (2888 % 1) = '#' 0x25 - (2888 % 2) = '#'
Nyt tämä näyttää oikealta viestiltä! Mutta varmistaaksemme, että algoritmimme on oikea, meidän on laskettava alkulukujen viisaan tulon tulo offset-arvojen ja kunkin käytetyn avainmerkin merkkiarvojen välillä ja laskettava ne yhteen viestin jokaisen #-merkin osalta. (\n ja \r on hylättävä)”
(g=103)*0 + (r=114)*0 + (o=111)*2
+ (g=103)*0 + (o=111)*0
+ (g=103)*2 + (r=114)*0 + (o=111)*0 = 428
Sinun täytyy kirjoittaa tämä alkuaineviisaiden tuotteiden summa tulosmuuttujaan saadaksesi koodaushaasteen valmiiksi!