Kohta avautuu joulukalenterin ensimmäinen luukku!
Sitä odotellessa voi tehdä vanhoja kalentereita.
Todella hieno on kyllä tämä Joulukalenteri!
Kalenteri on avautunut!
Putkan selviytyjät löytyy täältä.
TapaniS kirjoitti:
Kalenteri on avautunut!
Aloitus ainakin näyttäisi olevan mukavan pehmeä ja ratkeaa parilla lyhyellä koodirivillä. Katsotaan, jos sitä jokusen tehtävän näitäkin kokeilisi suorittaa!
Putkan listaan liitytään edelleenkin Private Leaderboard -sivulta koodilla 1142475-414cff12
, eli uudetkin ilmoittautujat ovat tervetulleita.
Parista vanhasta tehtävästä viisastuneena päätin tällä kertaa tallentaa ratkaisut, koska välillä on tullut myöhemmässä vaiheessa tehtäviä, joissa käytännössä jatketaan edellisen tehtävän ratkaisusta.
Kakkospäivän tehtävä soveltui erityisen hyvin 8th:lla ratkaistavaksi. Alla oma ratkaisuni tehtävän kakkososioon, mikä näyttää miten tehtävän data tiedoston tulkkauksen ja ratkaisemisen voi jättää kokonaan 8th:n tulkin vaivoiksi...
ns? ns: driver with: driver var depth var horizontal-position var aim : forward parsews >n dup horizontal-position n:+! aim @ n:* depth n:+! ; : down parsews >n aim n:+! ; : up parsews >n n:neg aim n:+! ; : drive "2.txt" f:slurp ns:driver only eval null only ; : result depth @ horizontal-position @ n:* ; ;with ns : app:main driver:drive driver:result . cr bye ;
Minusta on hupsua kehua, miten kaikki aina ”soveltuu erityisen hyvin 8th:lle”, kun ihan samalla tavalla voi tehdä lukuisilla muilla kielillä.
Eli 8th:n slurp slörp eval -rivin voi tehdä JavaScriptilla vaikka näin:
eval(document.body.textContent.replace(/(.*) (\d+)/g, "$1($2);"));
Ihan sama onnistuu myös vaikka PHP:llä tai Perlillä.
Bashille tehtävä sopisi vielä paremmin kuin 8th:lle, koska ei tarvitse mitään esikäsittelyä tai edes eval-kutsua vaan syötetiedoston voi suoraan ajaa.
AIM=0 DOWN=0 POS=0 forward() { DOWN=$(($DOWN + $1 * $AIM)) POS=$(($POS + $1)) } up() { AIM=$(($AIM - $1)) } down() { AIM=$(($AIM + $1)) } source ./2.txt echo $(($POS * $DOWN))
Metabolix kirjoitti:
Minusta on hupsua kehua, miten kaikki aina ”soveltuu erityisen hyvin 8th:lle”, kun ihan samalla tavalla voi tehdä lukuisilla muilla kielillä.
Eli 8th:n slurp slörp eval -rivin voi tehdä JavaScriptilla vaikka näin:
eval(document.body.textContent.replace(/(.*) (\d+)/g, "$1($2);"));Ihan sama onnistuu myös vaikka PHP:llä tai Perlillä.
Bashille tehtävä sopisi vielä paremmin kuin 8th:lle, koska ei tarvitse mitään esikäsittelyä tai edes eval-kutsua vaan syötetiedoston voi suoraan ajaa.
On siinä se ero, että oma toteutukseni voi ajaa netistä ladatun tiedoston eikä tarvitse pelätä sen suorittavan siitä mitään mitä en halua. Ajatko JavaScriptillä eval() funktiolla tai Bashillä koneellasi root oikeuksilla minkä tahansa tiedoston minkä lähetän? Miksi pitää kaikesta tehdä joku kilpailu? Laitoin koodin näytille, kun mielestäni oli kätevä ja selkeä tapa toteuttaa ratkaisu.
jalski kirjoitti:
Ajatko JavaScriptillä eval() funktiolla tai Bashillä koneellasi root oikeuksilla minkä tahansa tiedoston minkä lähetän?
No pitikö tehtävässä ajaa? Tehdään pieni muutos sitten, jos pitää. Ei ole iso ongelma.
Kylläpä menee taas tunteisiin, kun 8th ei ole kaikkein hienoin ja paras kieli. Ota ihan rennosti. Totesin vain, että "erityinen" oli viestissäsi liioittelua.
Metabolix kirjoitti:
Kylläpä menee taas tunteisiin, kun 8th ei ole kaikkein hienoin ja paras kieli. Ota ihan rennosti. Totesin vain, että "erityinen" oli viestissäsi liioittelua.
En minä tästä mitään ohjelmointikielien välistä sotaa tehnyt. Oma tapasi kommentoida kärkkäästi, päteä ja olla epäkunnioittava muita ihmisiä kohtaan tappaa tämän foorumin yhdessä muutaman muun tänne kirjoittelevan kiusaaja raukan kanssa.
jalski kirjoitti:
Oma tapasi kommentoida kärkkäästi, päteä ja olla epäkunnioittava muita ihmisiä kohtaan tappaa tämän foorumin yhdessä muutaman muun tänne kirjoittelevan kiusaaja raukan kanssa.
Nyt on kyllä äärimmäisen outo tulkinta tästä keskustelusta (tai muistakaan viimeaikaisista keskusteluista). Jos on jokin tietty asia, joka on mielestäsi asiattomasti sanottu, niin anna esimerkki (kyseisessä keskustelussa eikä täällä, tässä piti puhua joulukalenterista!) äläkä heittele satunnaiseen väliin syytöksiä. Muuten tuo on kyllä tämän keskustelun ensimmäinen ja toivottavasti viimeinen asiaton ja epäkunnioittava kommentti. (Ja jos on ideoita, miten ihan konkreettisesti ne ”muutama muu kiusaaja” pitäisi laittaa kuriin, niin siitäkin saa mielellään esittää ehdotuksia vaikka palautteen kautta tai erillisessä keskustelussa.)
jalski kirjoitti:
Miksi pitää kaikesta tehdä joku kilpailu?
Niin siis kuka täällä on tehnyt asiasta kilpailun? Jos kukaan, niin sinä, kun sanoit että tuo "tehtävä soveltui erityisen hyvin 8th:lla ratkaistavaksi". Metabolix kommentoi siihen lähinnä, että oma näkemyksesi 8thin pärjäämisestä itse määrittämässäsi kilpailussa ei ole ihan kirkossa kuulutettu juttu.
Jos osaa parhaiten käyttää vasaraa, eikä silleen ole tutustunut muihin työkaluihin, niin sattaa lipsauttaa kommentin "laudan katkaisemiseen vasara olikin erityisen näppärä. Käytin sitä terävää puolta ja...". Saattaa olla että joku kommentoi että ei se nyt niin erityisen helppoa ole, sahallakin onnistuisi kätevästi. Silloin on aika turha vetää hernettä nenään, että on laitettu pystyyn kilpailu työkalujen välille.
Kiva että tehtävän voi ratkaista 8th:lle luonteenomaisella menetelmällä kätevästi. Sama lähestymistapa ei välttämättä ole luonteenomainen muille kielille, mutta silti ratkaiseminen muilla kielillä voi olla vähintään yhtä näppärää niille luonteenomaisilla menetelmillä.
Esim. tässä yksi tapa tehdä asia C#:lla.
var sums = System.IO.File.ReadAllLines("/usr/grez/2.txt") .Select(row=>row.Split(' ')).GroupBy(col => col[0]) .ToDictionary(g => g.Key, g => g.Sum(col => int.Parse(col[1]))); Console.WriteLine(sums["forward"] * (sums["down"] - sums["up"]));
Tuntui helpolta ja vaivattomalta. En silti ala sanomaan että tämä olisi "sopisi erityisen hyvin C#:lle", koska tiedän että tämä tehtävä on erittäin helppo ratkaista millä tahansa kielellä.
P.S. Koska murehdit tuota netistä ladattavan tiedoston käyttämistä syöteensä suoraan, niin kirjoitin koodin alun perin noutamaan ohjeet suoraan osoitteesta https://adventofcode.com/2021/day/2/input , mutta se ei valitettavasti ollut saatavilla ilman kirjautumista, koska "Puzzle inputs differ by user. Please log in to get your puzzle input."
Now when Xmas itself is only a big business and competition so why wouldn't xmas advent calendar be the same thing, especially for the developers? I would say that boo combined with c (in Finnish puucee) would be the best solution for developing these kind of programs.
Good Night, and Good Luck
Sukellusveneharjoituksesta on ilmeisesti kaksi eri versiota, mutta vain ensimmäinen näkyy ilman kirjautumista.
Soveltuu erityisen hyvin Perlille (tai vaikka awk:lle)!
perl -anE '$x{$F[0]} += $F[1] } { say $x{forward} * ($x{down} - $x{up})' tmp.txt
jlaire kirjoitti:
Sukellusveneharjoituksesta on ilmeisesti kaksi eri versiota, mutta vain ensimmäinen näkyy ilman kirjautumista.
Joo, siis jokaisen päivän tehtävissä on kaksi vaihetta, joista ensimmäinen näkyy heti ja toinen vasta kun ensimmäinen on suoritettu. Ja suorittaa ei voi ilman kirjautumista.
Hyvää joulua kaikille! Täällä onkin jo aitoa joulun tunnelmaa, kun kaikki ovat toistensa kurkuissa kiinni ja ▒▒▒▒▒▒ ilmeisesti humalassa
Tämä on kyllä hyvä joulukalenteri, kun tehtävät tulevat aamulla niin, että jaksaa herätä tekemään. Harmi vain, että joka päivä on pitänyt hukata pari minuuttia jonkin ihan turhan virheen vuoksi (esim. väärä muuttujanimi tai alkeellinen moka syötteen purkamisessa). Tavoitteena on päästä edes jonain päivänä tuloslistalle, mutta jään pari minuuttia kärjestä jo luku- ja kirjoitusnopeuden takia (kuka ehtii 1,5 minuutissa edes lukea nuo tehtävät ajatuksella?), joten ei olisi varaa mihinkään virheisiin.
jlaire kirjoitti:
Soveltuu erityisen hyvin Perlille
Aika ovelaa, en olisi arvannut, että aaltosulut ja -n toimivat tuolla tavalla yhdessä.
Metabolix kirjoitti:
kuka ehtii 1,5 minuutissa edes lukea nuo tehtävät ajatuksella?
Luulisin, että englantia äidinkielenään puhuvilla on pieni etu. Itsekin luin sen verran huolimattomasti eilisen tehtävät, että ratkaisin käytännössä ensin 2. tehtävän, ja sitten ihmettelin miksei se täsmää...
Tosin jälkikäteen ajatellen ainakin eilisen päivän tehtävät olisi varmaan saanut suoritettua lukematta tekstiä, katsomalla esimerkkisyötettä ja sitä miten se tulkataan ja lukemalla ne pari riviä mitä siitä pitää laskea.
Huono puoli tuollaisessa tehtävänannon arvaamisessa on, että jo arvaus menee pieleen, niin tulee heti minuutin penalti. Siinähän sitten onkin aikaa tavata tehtävänanto kunnolla :D
Nyt alkaa tehtävät jo vaikeutumaan. Tämän päivän tehtävä piti viimeistellä excelillä, kun ei aivosolu ymmärtänyt, miten tuon saisi koodilla siististi pakettiin. :(
TapaniS kirjoitti:
Nyt alkaa tehtävät jo vaikeutumaan.
Nää on tietysti henkiökohtaisia asioita, mutta mun mielestä taas tää päivä oli helpoimmasta päästä tähän mennessä.
Jos eri päivien leaderboardia katsoo niin vaikeusaste (missä ajassa 100 nopeinta ehtii saada molemmat tähdet) näyttäisi menevän järjestyksessä:
2:44 1. pv
2:57 2. pv
5:47 6. pv
8:53 5. pv
10:17 3. pv
11:13 4. pv
Grez kirjoitti:
Tosin jälkikäteen ajatellen ainakin eilisen päivän tehtävät olisi varmaan saanut suoritettua lukematta tekstiä, katsomalla esimerkkisyötettä ja sitä miten se tulkataan ja lukemalla ne pari riviä mitä siitä pitää laskea.
Juuri tämä on yhden todella nopean ratkojan strategia: https://old.reddit.com/r/adventofcode/comments/
xiaowuc1 kirjoitti:
When the day starts, I open the link and scroll straight to the sample inputs and see what is being generated. From there, I look back through the problem to figure out the problem specifications, avoiding reading as much of the flavortext as possible.
Joissain muissa kilpailuissa on todettu, että jos nopea ratkominen vaatii tällaista arvailua, on mielekkäämpää kirjoittaa mahdollisimman lyhyitä tehtävänantoja ilman taustatarinoita.
Niin voisi tietysti myös sanoa että tekstin määrä näissä on suhteellisen suuri tehtävän vaikeuteen nähden. Jos olisi tehtävä jossa parhaimmillakin menee tunteja, niin ei olisi niin väliä lopputulosten kannalta vaikka tehtävänantoa lukisikin 5 minuuttia.
Itse en ole ryhtynyt kisamoodiin, yleensä aloitan koko tehtävien tekemisen vasta niin myöhään että kaikki pistesijat on jo viety. En sit tiedä pitäisikö laittaa kellon soimaan vähän ennen seiskaa ja yrittää...
Tänään oli selkeästi yleisellä tasolla työläin tehtävä toistaiseksi
(Kauanko 100. nopeimmalla on mennyt aikaa molempiin tehtäviin)
2:44 1. pv
2:57 2. pv
3:33 7. pv
5:47 6. pv
8:53 5. pv
10:17 3. pv
11:13 4. pv
20:51 8. pv
Joo, aika paha oli! Just sain tuon läpi.
Tehtävä erosi edellisistä siinä, että muissa on pitänyt toteuttaa suoraan tehtävänannossa kuvattuja asioita mutta tässä digitaalinäytön korjailussa piti itse käsityönä muodostaa oikea ehtolause joka numerolle (0–9). Itse tuhlasin reilusti aikaa siihen, että ratkaisin ensin yksittäiset palat a–g, vaikka pelkkä numeroiden tunnistus onnistui lyhyemmällä koodilla ilman näitä. (Spoiler alert: wbxn ahzrebba evvggv xnxfv rugbn: zbagnxb cnynn ba xnvxxvnna wn zbagnxb ba fnzbwn xhva fbcvinffn nvrzzva ghaavfgrghffn ahzrebffn, fvvf cvgv gbgrhggnn zrexxvwbhxxbwra yrvxxnhf ryv vagrefrpgvba.)
Nämä kärjen aikamäärät korreloivat kohtalaisesti ainakin omien koodieni pituuteen, eli ehkä pitäisi puhua työläästä eikä vaikeasta. Alkupuolen tehtävissä on vielä ollut niin pienet syötteet, että brute force on riittänyt pääasialliseksi ratkaisuksi, jos nyt ei ihan jokaista ravun askelta pyöritä jollain for-silmukalla.
Metabolix kirjoitti:
ehkä pitäisi puhua työläästä eikä vaikeasta.
Hyvä pointti. Itseänikin ärsyttää kun kysytään "onko tällainen vaikea toteuttaa" jostain ihan triviaalista mutta työläästä asiasta.
Grez kirjoitti:
Metabolix kirjoitti:
ehkä pitäisi puhua työläästä eikä vaikeasta.
Hyvä pointti. Itseänikin ärsyttää kun kysytään "onko tällainen vaikea toteuttaa" jostain ihan triviaalista mutta työläästä asiasta.
Päätyikö joku laskemaan hash-arvon ja käyttämään sitä dekoodaukseen? Ei ole silloin edes kauhean työläs tehtävä...
jalski kirjoitti:
Päätyikö joku laskemaan hash-arvon ja käyttämään sitä dekoodaukseen? Ei ole silloin edes kauhean työläs tehtävä...
Mitä tarkoitat?
”Työläs” vaihe tehtävässä on keksiä (ja toteuttaa), millä ehdoilla merkkijonot tunnistetaan numeroiksi eli mistä tietää vaikka, onko abcdef numero 6 vai numero 9. Voiko tähän hyödyntää hasheja jotenkin, tai oliko mielessä ihan muu ratkaisumalli koko tehtävään?
Kun annetut 10 numeroa saa tunnistettua, kyllä useimmissa kielissä on jokin ihan helppo tapa hoitaa vielä ne neljä kysyttyä numeroa niin, ettei tarvitse itse laskea yhtään hashia. Esimerkiksi JS:n objekti toimii suoraan merkkijonoavainten kanssa, eli kun joka sanan merkit laittaa ensin aakkosjärjestykseen, numeron liittäminen merkkijonoon on näin helppoa:
let numeroksi = {}; numeroksi["ab"] = 1; numeroksi["abc"] = 7; // jne. // Lopuksi muutetaan neljä sanaa numeroiksi, yhdistetään luvuksi ja summataan: tulos += parseInt(rivin_diginumerot.map(sana => numeroksi[sana]).join(""));
Metabolix kirjoitti:
Nämä kärjen aikamäärät korreloivat kohtalaisesti ainakin omien koodieni pituuteen, eli ehkä pitäisi puhua työläästä eikä vaikeasta.
Olikohan tämänpäiväinen taulukosta kuoppien etsiminen sitten ensimmäinen ”vaikea” tehtävä, kun oman kellotuksen mukaan olisin voinut päästä tuonne yleiselle tuloslistalle, jos olisin ollut ajoissa tekemässä. No aina voi selitellä. :D Pitää toivoa vielä toista tilaisuutta, onhan tässä päiviä jäljellä.
Metabolix kirjoitti:
Mitä tarkoitat?
”Työläs” vaihe tehtävässä on keksiä (ja toteuttaa), millä ehdoilla merkkijonot tunnistetaan numeroiksi eli mistä tietää vaikka, onko abcdef numero 6 vai numero 9. Voiko tähän hyödyntää hasheja jotenkin, tai oliko mielessä ihan muu ratkaisumalli koko tehtävään?
Laskemalla kuinka monta kertaa segmenttiä merkitsevä kirjain esiintyy kokonaisuudessaan voidaan kirjaimelle määrittää pistearvo. Nyt kun lasketaan 7-segmentti näytön kirjaimien pistearvot yhteen, saadaan hash-arvo millä saadaan ratkaistua kyseinen numero suoraan (jokaiselle numerolle tulee uniikki hash-arvo ainakin tässä tehtävässä).
Itse en nopeuskilpailuun kykene ja työpäivätkin venyvät yli 12-tuntisiksi. Tämän päivän tehtävääkään en vielä ole ehtinyt kurkistaa...
jalski kirjoitti:
Laskemalla kuinka monta kertaa segmenttiä merkitsevä kirjain esiintyy kokonaisuudessaan
Ovelaa! Eli yksinkertaisesti voi korvata kirjaimet niiden lukumäärällä ja laittaa nämä suuruusjärjestykseen, niin saa joka numeroa vastaavan lukuarvon (esim. 4677889 = 8). Hämäännyin nimityksestä, mutta kai tätäkin voi hashiksi kutsua... Koodi lyheni tuolla puoleen.
jalski kirjoitti:
Tämän päivän tehtävääkään en vielä ole ehtinyt kurkistaa...
Tuli mieleen, olisiko siihen jokin hauska kikka vaikka PL/I:llä. :) :) :) Jotenkin vähän samanhenkinen tehtävä kuin jotkin muut taulukko- tai bittikikkailut, joita joskus muinoin esittelit.
Metabolix kirjoitti:
jalski kirjoitti:
Laskemalla kuinka monta kertaa segmenttiä merkitsevä kirjain esiintyy kokonaisuudessaan
Ovelaa! Eli yksinkertaisesti voi korvata kirjaimet niiden lukumäärällä ja laittaa nämä suuruusjärjestykseen, niin saa joka numeroa vastaavan lukuarvon (esim. 4677889 = 8). Hämäännyin nimityksestä, mutta kai tätäkin voi hashiksi kutsua... Koodi lyheni tuolla puoleen.
Kirjoittelin 8th toteutuksen puhtaaksi äsken:
[ "abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg" ] constant digits : score-hash \ m s -- n ( "" swap s:+ 2 pick swap m:@ nip a:len nip n:+ ) 0 s:reduce ; : build-groups \ a -- m "" a:join "" s:/ ' noop a:group ; m:new digits build-groups digits ( swap >r score-hash 2 pick swap r> m:! drop ) a:each 2drop constant decode-lookup : decode-line \ s -- a decode-lookup a:new rot " | " s:/ ( " " s:/ ) a:map a:open >r build-groups r> ( score-hash 2 pick swap a:push drop ) a:each! 2drop m:@ nip ; : app:main \ Part A a:new a:new "8.txt" f:slurp dup -rot ( decode-line a:+ ) s:eachline ' noop a:group [1, 4, 7, 8] m:@ nip ( a:len nip ) a:map ' n:+ 0 a:reduce "Part A: %d\n" s:strfmt . \ Part B ( decode-line ' >s a:map "" a:join >n a:push ) s:eachline ' n:+ 0 a:reduce "Part B: %d\n" s:strfmt . bye ;
lainaus:
jalski kirjoitti:
Tämän päivän tehtävääkään en vielä ole ehtinyt kurkistaa...
Tuli mieleen, olisiko siihen jokin hauska kikka vaikka PL/I:llä. :) :) :) Jotenkin vähän samanhenkinen tehtävä kuin jotkin muut taulukko- tai bittikikkailut, joita joskus muinoin esittelit.
Täytyypä katsoa, saako tuosta mitään kivaa ideaa. Jälkijunassa näitä tehtäviä teen omaa rauhallista tahtiani, kun työasiat tällä hetkellä syövät vapaa-ajan minimiin...
Päivä 10 oli tehtävänä aika tylsä... Päädyin kirjoittelemaan taulukkopohjaisen yksinkertaisen parserin.
needs file/getc a:new constant stack-array [ 10, 13, 40, 91, 123, 60, 41, 93, 125, 62 ] constant chars [ 41, 93, 125, 62 ] constant expected-index [ 40, 91, 123, 60 ] constant expected [ 3, 57, 1197, 25137 ] constant scores1 [ 1, 2, 3, 4 ] constant scores2 var score1 a:new var, score2 : skip \ f -- f repeat f:getc null? not if 10 n:= if ;then else drop then f:eof? not while! ; : LF drop score2 @ 0 stack-array ( a:pop expected swap ' n:= a:indexof nip scores2 swap a:@ nip rot 5 n:* n:+ swap ) over a:len nip times drop a:push drop ; : CR drop ; : push-char \ n -- stack-array swap a:push drop ; : pop-char \ n -- expected-index swap ' n:= a:indexof nip dup >r expected caseof stack-array a:pop nip n:= not if r> scores1 caseof score1 n:+! stack-array a:clear drop skip else rdrop then ; [ ' LF , ' CR , ' push-char , ' push-char , ' push-char , ' push-char , ' pop-char , ' pop-char , ' pop-char , ' pop-char ] constant actions : app:main "10.txt" f:open repeat f:getc null? not if dup chars swap ' n:= a:indexof nip null? if "Unknown character encountered" throw then actions caseof else drop then f:eof? not while! f:close score1 @ . cr score2 @ ' n:cmp a:sort a:len 2 n:/ a:@ . cr bye ;
Itse käytin 10. päivään silmukkaa ja pinoa, mutta tajusin jälkikäteen, että näin pienellä syötteellä riittäisi vielä lyhyempi idioottiratkaisu, että ensin silmukassa poistetaan 100 kertaa peräkkäiset sulkuparit, minkä jälkeen rivin ensimmäinen sulkeva sulku lisätään ykkösosan ratkaisuun tai sen puutteessa pelkät avoimet sulut käännetään 5-kantaiseksi luvuksi kakkososan ratkaisua varten. Tästä jälkimmäisestä tuli vain 12 riviä, tosin rivimäärä sinänsä on vertailukelpoinen vain muiden samalla tyylillä tehtyjen koodien kanssa, kun mukana on tällaisia monen mielestä ei-niin-yksirivisiä hirviöitä:
part2.push(parseInt(s.match(/./g).reverse().map(m => '-([{<'.indexOf(m)).join(""), 5));
Tänään oli taas suoraviivainen ja vähätöinen päivä. Itselle meni yli puolet ajasta siihen perinteiseen, että ymmärsin tehtävänannon hieman väärin ja debuggasin sitten olematonta bugia.
Joo, määkin posautin aina kaikki ysit ja ihmettelin, kun ei vaan toimi!
Hahaa! :D Vihdoinkin perinteinen hakualgoritmi. Ehkä tämä on sitten sellainen ”vaikea” tehtävä, kun ajat ovat isompia kuin päivinä 3–4 mutta oma koodi ainakin on puolet lyhyempi eikä tuntunut yhtään niin ikävältä kirjoittaa.
Grez kirjoitti:
Tänään oli taas suoraviivainen ja vähätöinen päivä. Itselle meni yli puolet ajasta siihen perinteiseen, että ymmärsin tehtävänannon hieman väärin ja debuggasin sitten olematonta bugia.
Itse muokkasin vanhan Minesweeper pelini pohjalta tähän tehtävään soveltuvan toteutuksen. Rekursiivisen toteutuksen sijaan tein iteratiivisen version käyttämällä jonoa apuna:
a:new "11.txt" f:slurp ( "" s:/ ' >n a:map a:+ ) s:eachline constant board 10 constant BRDSZ BRDSZ BRDSZ n:* n:1- constant LAST-INDEX [ 0, -1 ] constant NORTH [ 0, 1 ] constant SOUTH [ 1, 0 ] constant EAST [ -1, 0 ] constant WEST NORTH EAST ' n:+ a:2map constant NORTHEAST SOUTH EAST ' n:+ a:2map constant SOUTHEAST SOUTH WEST ' n:+ a:2map constant SOUTHWEST NORTH WEST ' n:+ a:2map constant NORTHWEST [ @NORTH , @SOUTH , @EAST , @WEST , @NORTHEAST , @SOUTHEAST , @SOUTHWEST , @NORTHWEST ] constant DIRECTIONS BRDSZ BRDSZ n:* q:new constant flash-queue var flashes var steps-taken : >xy \ offs -- [ x, y ] dup BRDSZ n:mod swap BRDSZ n:/ n:int 2 a:close ; : >offs \ [ x, y ] -- n a:open BRDSZ n:* n:+ ; : in-bounds? \ [ x, y ] -- T ( dup 0 n:< not swap BRDSZ n:< and ) a:filter a:len nip 2 n:= ; : add-queue \ n -- flash-queue swap q:push drop ; : uncover-queue \ n -- >xy ' dup 7 times 8 a:close DIRECTIONS ( ' n:+ a:2map ) a:2map ' in-bounds? a:filter ' >offs a:map ( board over a:@ dup 0 n:> if n:1+ dup 9 n:> if drop 0 2 pick add-queue 1 flashes n:+! then _swap a:! drop else 2drop drop then ) a:each! drop ; : cascade 0 flash-queue repeat q:len 0 n:= if drop break else q:pop uncover-queue swap n:1+ swap then again 1 steps-taken n:+! 100 n:= if true else false then ; : step board ( n:1+ dup 9 n:> if drop 0 then ) a:map= ( 0 n:= if add-queue 1 flashes n:+! else drop then ) a:each drop cascade ; : app:main ( step drop ) 100 times flashes @ "Part A: Flashes after 100 steps: %d\n" s:strfmt . repeat step if break then again steps-taken @ "Part B: All octopuses flash at step: %d\n" s:strfmt . bye ;
Metabolix kirjoitti:
Hahaa! :D Vihdoinkin perinteinen hakualgoritmi. Ehkä tämä on sitten sellainen ”vaikea” tehtävä, kun ajat ovat isompia kuin päivinä 3–4 mutta oma koodi ainakin on puolet lyhyempi eikä tuntunut yhtään niin ikävältä kirjoittaa.
Onneksi olkoon ensimmäisistä pisteistäsi kansainvälisellä Leaderboardilla!
Itse olen vissiin vaan hidas. Tämän päiväinen ei omasta mielestäkään tuntunut yhtään ikävältä kirjoittaa enkä tehnyt ensimmäisessä tähdessä yhtään mokaa, mutta silti aikaa meni 16m 14s, eli yli tuplasti sen mitä Metabolixilla. Toinen tehtävä olisi ollut helppo korjaus, mutta siinä sitten taas mokasinkin ja aikaa meni reilusti hukkaan.
Tein muuten tällaisen ruman pikaisen JS-härpäkkeen, joka tulkitsee Private Leaderboardista saatavaa JSONia niin, että jokaisen päivän järjestyksen saa helposti näkyville.
Ensin JSON täytyy sijoittaa muuttujaan s
Tulokset tulevat tulos -muuttujaan. Viiminen rivi toimii ainakin Chromen konsolissa ja kopioi tulos-muuttujan sisällön leikepöydälle. Muilla selaimilla täytyy ehkä käyttää muuta tapaa.
fs = function(x) { if (x==0) { return ''; } return ' +' + (x>=3600 ? (Math.floor(x/3600) + 'h') : '') + (x>=60 ? ('0'+Math.floor((x%3600)/60) + 'm').slice(-3) : '') + ('0' + x%60).slice(-2) + 's'; } tulos=''; for (d=1; d<26; d++) for (p=1;p<3; p++) { so = Object.entries(s.members).map(c=>c[1]) .filter(c=>c.completion_day_level[d]!==undefined && c.completion_day_level[d][p]!==undefined) .sort((a,b)=>a.completion_day_level[d][p].get_star_ts - b.completion_day_level[d][p].get_star_ts); if (so.length>0) { bts = so[0].completion_day_level[d][p].get_star_ts; tulos += d + '-' + p + ': ' + so.map(c=>c.name + fs(c.completion_day_level[d][p].get_star_ts - bts)).join(', ') + '\r\n'; } } copy(tulos)
Eilisen jälkeen listalle liittynyt anonyymikäyttäjä tuossa näkyy kyllä nyt ikävästi nullina, mutta senhän voisi korjata sitten jos useampia muumeja tulee.
Metabolix kirjoitti:
Hahaa! :D Vihdoinkin perinteinen hakualgoritmi. Ehkä tämä on sitten sellainen ”vaikea” tehtävä, kun ajat ovat isompia kuin päivinä 3–4 mutta oma koodi ainakin on puolet lyhyempi eikä tuntunut yhtään niin ikävältä kirjoittaa.
Itse jäin jumiin, kun nää rekursiot ovat aina olleet niin hankalia. Mikähän tässä menee pieleen? Tuossa siis "end" on kaupunki nro 12 ja ok-taulukkon alkuarvot ovat kaikki right (false, jos kaupunkiin ei enää pääse). Oon katsonut, että ohjelma lukee lähtöarvot muuttujiin oikein.
Tilannekaavio täällä.
Lähtöarvot täällä.
private static void getroutes(int city1, boolean[] ok3) { boolean[] ok4 = ok3; if (city1 == 12) { tulos++; return; } for (int i1 = 0; i1 < town[city1].rQty; i1++) { int kohde = town[city1].cnum[i1]; if (ok3[kohde]) { if (!town[kohde].BIG) ok4[kohde] = false; getroutes(kohde, ok4); } } return; }
####### Edit #####
Äääh! No nyt tajusin! Tuossahan tulee tsiljoona i1 -muuttujaa samaan luuppiin! Oioioijoi!
TapaniS, pieleen menee se, että Javassa taulukko on olio ja tuossa siis ok3 ja ok4 ovat edelleen sama taulukko ja näin ollen et pysty käyttämään samaa kohdetta edes eri reiteillä. Eli ok4 pitäisi luoda for-silmukan sisällä (juuri ennen rekursiota) ja nimenomaan kopiona ok3:sta, jos nyt tuolla idealla jatkaisi. Mutta ei kannata edes yrittää kopioida taulukkoa, vaan tehokkaampaa olisi käyttää vain yhtä taulukkoa ja rekursiokutsun jälkeen peruuttaa sinne tehty merkintä (eli laittaa uudestaan ok = true). Laittaisin tämänkin tiedon suoraan town-taulukkoon (visited), ja laittaisin myös lopetustiedon johonkin vakioksi, ettei tarvitse tuollaista yllätyslukua kirjoittaa koodiin.
Ei tule mitään i1-muuttujia samaan luuppiin, se on nyt juuri sitä rekursion väärinymmärtämistä. Paikalliset muuttujat ovat ikään kuin funktiokutsun yksityisiä jäseniä, ja niiden kannalta ei ole merkitystä, kutsutko funktion sisällä samaa funktiota vai jotain toista funktiota. Eli rekursio toimii käytännössä ihan samalla tavalla kuin se, että tekisit 1000000 kopiota tuosta funktiosta (get1, get2, get3) ja kutsuisit aina niistä seuraavaa.
VilleVal kirjoitti:
Tein muuten tällaisen ruman pikaisen JS-härpäkkeen, joka tulkitsee Private Leaderboardista saatavaa JSONia niin, että jokaisen päivän järjestyksen saa helposti näkyville.
Hyvä idea! Parantelin koodia niin, että sen voi ajaa suoraan Private Leaderboard -sivulla ja tulokset näytetään sivun lopussa. Jätin siihen myös oikeat ajat (eikä erotusta), niin on helpompi vertailla myös globaaliin listaan.
Eli tuloslista auki (kuten yllä neuvottu), sitten F12:lla JS-konsoli auki ja alla oleva koodi siihen.
function aoc_text_results(data) { const time = s => new Date(1000 * s).toLocaleString(); let members = Object.entries(data.members).map(x => x[1]); let results = []; for (let d = 1; d <= 25; ++d) for (let p = 1; p <= 2; ++p) { const star = m => (((m.completion_day_level[d] || [])[p] || {}).get_star_ts || 0); const daymem = members.filter(m => star(m)).sort((a, b) => star(a) - star(b)); results.push(`${d}-${p}:\n${daymem.map(c => `${time(star(c))}\t${c.name || `anon #${c.id}`}`).join("\n")}`); } return results.join("\n\n"); } function aoc_show_results(data) { const pre = document.querySelector("pre.leaderboard-all-times") || document.createElement("pre"); pre.className = "leaderboard-all-times"; document.querySelector("article").appendChild(pre); pre.textContent = aoc_text_results(data); pre.scrollIntoView(); } (async _ => aoc_show_results(await (await fetch(location.pathname + ".json")).json()))();
Metabolix kirjoitti:
... ei kannata edes yrittää kopioida taulukkoa, vaan tehokkaampaa olisi käyttää vain yhtä taulukkoa ja rekursiokutsun jälkeen peruuttaa sinne tehty merkintä (eli laittaa uudestaan ok = true)...
Kiitos paljon! Nyt lähti taas koodi rullaamaan! Tarjoan kakkukahvit, kun sopiva tilaisuus tulee! :)
Itekki pääsen koht ratkoo näit luukkui. Tj2 eikä paljoa paina
Tänään ei aivosolu raksuttanut ja piti googlettaa ratkaisuidea. Nyt pitäisi sitten kyllä onnistua!
14. päivä arvasin sitten väärin ja tein ensin sen "helpon" merkkijonon korvaukseen perustuvan ratkaisun, mutta toisen osan luvut olivat liian suuria ja piti tehdä sitten uusi ratkaisu (spoiler: erilaisten parien määrän laskeminen; jokainen korvaus tekee yhdestä parista kaksi uutta paria).
15. päivän tehtävän esimerkissä on hämäävästi reitti, joka kulkee vain oikealle ja alas, joten tein ensin perinteisesti tähän erityistapaukseen sopivan ratkaisun, mutta paljastuikin sitten, että ainakin omassa syötteessä kakkostapauksen oikea ratkaisu tekee mutkan taaksepäin. Toki tehtävän tekstissä ei ole kielletty tätä ja oma lähtöoletus oli tavallaan tietoinen riski. Näissä tehtävissä ei voi varmasti tietää etukäteen, mikä olisi riittävä ratkaisu eli paljonko vaivaa kannattaa nähdä. Toivottavasti on edes tasapuolisesti varmistettu, että kaikille tulee yksi mutka.
Metabolix kirjoitti:
ainakin omassa syötteessä kakkostapauksen oikea ratkaisu tekee mutkan taaksepäin.
Samoin oli minun syötteessä ja ihan samalla lähestymistavalla itsekin etenin. Piti oikein piirtää itselle kuvio että sai vakuututtua että joskus saattaa joutua tekemään mutkaa...
1 9 9 9 9 9 1 9 1 1 1 9 1 9 1 9 1 9 1 1 1 9 1 9
Mielestäni tämän päivän tehtävä oli sikäli huonosti laadittu, että harjoitusaineistossa ei ollut mutkaa. Tai no, saattaahan se olla tietoistakin, eli karsitaan vähän pois näitä jotka ei lue ohjeita ja katsoo vaan esimerkkisuorituksesta mallia.
Tänään en ole vieläkään ymmärtänyt, miten saan datapaketit eriteltyä. Luetun ymmärtäminen ei tahdo onnistua.
TapaniS kirjoitti:
Tänään en ole vieläkään ymmärtänyt, miten saan datapaketit eriteltyä. Luetun ymmärtäminen ei tahdo onnistua.
Erittely on silleen helppoa: Aina kun datapaketti loppuu, alkaa seuraava. Paitsi jos jäljellä on alle 6 bittiä, jolloin paketteja ei enää ole enempää.
Niitä ei voi erotella etukäteen paketeiksi ja sitten vasta käsitellä, vaan vasta 1. paketin käsiteltyäsi tiedät mistä 2. alkaa jne..
Vähänkuintämätekstijostapystytpäättelemäänmissäsanojenvälitovat.
Mutta joo, tylsä tehtävä oli. Pelkkää työtä, ei lainkaan hupia (eli tarvetta päätellä tai keksiä itse)
Joo, nyt taisin tajuta! Kiitti taas paljon! Tarjoan pullakahvit, kun sopiva tilaisuus koittaa! :)
----
Ei tää oo ollenkaan tylsä! Tässähän pitää rakentaa jonkinlainen rekursio! Ne ovat aina niin abstrakteja, hankalia hahmottaa. En oo vieläkään saanut toimimaan, mutta idea on jo päässä.
Hauska tämän päivän eka tehtävä, kun ei tarvinnut koodata ollenkaan.
Onpa kummallista, miten tämän 18. päivän kärkitulokset ovat noin hitaita. Minusta tehtävä oli taas mekaaninen suoritus ja ehdin jopa koodata bugin siihen (listaani jäi ”aukko” räjähtävän luvun kohdalle) ja kaivella tehtävänantoa uudestaan. Silti vielä aamupuuron jälkeenkin tuloslistalla on puolet tyhjää.
Onnittelut Metabolixille TOP-10 sijoituksesta tämän päivän tehtävässä!
Itseä alkoi nyt ahdistamaan, kun alkoi tuntumaan niiiin turhalta tämmöinen. No katsotaan nyt, jos intoa vielä löytyy ...
Metabolix kirjoitti:
(18.12.2021 07:36:10): Onpa kummallista, miten tämän 18. päivän...
En tiedä. Minulla on ongelmana että en löydä ohjeistuksesta selkeää määritystä mitä pitää tehdä jos tulee syvempiä kuin 4. sisäkkäistä, että missä järjestyksessä edetään. Eli kaikki toimii kunnes tulee "Here's a slightly larger example:" ja sitten ei enää vastaukset ole samat kuin mallissa.
Itsellä on nyt mennyt 2:35 työaikaa, kun yleensä olen alle tunnin työllä saanut nämä tehtyä.
Voin siis kuvitella, että tuurilla menee heittämällä, mutta sitten jos ei arvaa oikein epämääräisesti annettuja tilanteita, niin debuggaus on todella hidasta.
Tajusin juuri, että tein tämän varmasti liian vaikeasti. Ei olisi pitänyt purkaa objekteiksi vaan tehdä vaan merkkijonomuunnoksilla.
VilleVal kirjoitti:
Minulla on ongelmana että en löydä ohjeistuksesta selkeää määritystä mitä pitää tehdä jos tulee syvempiä kuin 4. sisäkkäistä, että missä järjestyksessä edetään.
Kyllä se siinä lukee:
Jos jotain on syvemmällä kuin 4 (eli käytännössä 5, koska mistään operaatiosta ei tule enempää kuin 1 lisätaso kerralla), pitää tehdä explode, joka on kyllä ansiokkaan epäselvillä esimerkeillä neuvottu mutta siis tarkoittaa, että liian syvän parin tilalle tulee 0 ja sen vanhat luvut lisätään vasemmalla ja oikealla (mahdollisesti aivan eri syvyydellä) oleviin lukuihin.
Muuten, jos jokin luku on 10 tai suurempi, pitää tehdä split, jossa tällainen luku korvataan parilla. Ja tämän jälkeen palataan explode-vaiheeseen.
Ja jos ei kumpaakaan näistä toteudu, luku on valmis.
Käytännössä tuo tapahtuu siis perinteisellä while not done -silmukalla, jossa jokaisen muunnoksen jälkeen palataan silmukan alkuun, kunnes muunnoksia ei ole enää jäljellä.
VilleVal kirjoitti:
Tajusin juuri, että tein tämän varmasti liian vaikeasti. Ei olisi pitänyt purkaa objekteiksi vaan tehdä vaan merkkijonomuunnoksilla.
Ehdottomasti! Toteutusvinkkinä rot13-muodossa: Chh wn erxhefvb bing gheuna invxrvgn gäuäa grugäiääa. Urycbzzva zrarr lxfvhybggrvfran gnhyhxxban, wbffn ba unxnfhyxhwn, cvyxxhwn wn yhxhwn. Rkcybqrffn ynfxrgnna unxnfhyhvfgn flillggä, rafvzzävfra fbcvina yhiha xbuqnyyn cbvfgrgnna ivvfv xbugnn (fhyxh, yhxh, cvyxxh, yhxh, fhyxh), ynvgrgnna gvynyyr abyyn wn rgfvgääa fvyzhxbvyyn ivrervfrg infrzznygn wn bvxrnygn fhzznnzvfgn inegra. Fcyvgvffä xbeingnna lxfv yhxh ivvqryyä cnynyyn (fhyxh, rxnyhxh, cvyxxh, gbxnyhxh, fhyxh).
No niin, aloitin puhtaalta pöydältä tuossa 9:40 maissa ja nyt valmis.
Näköjään tein suunnilleen tuon rot13 vinkkisi mukaan. Joskin taulukon asemesta käytin merkkijonoa, josta korvailin pätkiä. Kuvaamasi menetelmän suoritusaika olisi varmana ollut parempi (itsellä noin sekunti kumpaankin vaiheeseen)
Luultavasti ensimmäisen viritykseni suurin vika oli, että se pilkkoi yli 10 luvut heti kun niitä ilmaantui, ja niinhän ei tietenkään olisi saanut tehdä. Tämä myös aiheutti sen, että lisätasoja pystyi tulemaan useampia kuin muuten.
Noudatan näissä näköjään perinnettä että teen joitain optimistisia oletuksia, jotka toteutuu kyllä harjoitusmateriaaleilla, mutta ei tuotantodatalla. :D
Ei voi mitään, nyt alkaa menemään niin hankalan tuntuisiksi, että enää en pysty (järkevässä ajassa) näitä ratkomaan. Just sain eilisen eka osion läpi, mutta aika ei nyt oikein riitä enempään. No onpa sitten jotain tekemistä, kun aika käy pitkäksi ... :)
Nämä koordinaatiston veivaukset aiheuttavat käsin tehtynä aina järjettömästi työtä, ja tässä tehtävässä piti vielä säätää aika monen sisäkkäisen silmukan kanssa (kaksi sensoria, uudesta jokin 24 eri kierrosta, molemmista jokin piste, sitten näiden mukaan kaikkien muiden pisteiden tarkistus, osuuko tarpeeksi moni yhteen). Itsellänikin oli ratkaisussa ensin bugi, jonka takia päädyin varmuuden vuoksi koodaamaan käsin ne 24 eri kiertoa (yksi per rivi, kun jokaisessa tarvitsee vain vaihtaa koordinaattien järjestystä ja etumerkkiä sopivasti), mikä olisi ollut luultavasti alunperinkin nopeampaa kuin kikkailu silmukoiden ja pyöritysfunktioiden kanssa. Tosin bugi ei lopulta liittynyt edes geometriaan vaan siihen, että eräässä tilanteessa lopetin sisäkkäisistä silmukoista yhden liikaa. JS-ratkaisuni vie reilut 10 sekuntia, mutta siinä luodaan vielä surutta uusia olioita jokaisen koordinaattilaskun yhteydessä, eli varmaan optimointiin olisi varaa.
Kuulostaa jotenkin tutulta tuo 24 kierron käsin koodaaminen varmuuden vuoksi.
Itselläni kosahti ensin siihen, että yhdistelin vaan sensoreiden dataa sitä mukaa, kun 12 luotaimen mätsi löytyi ja sitten näitä yhdistettyjä datapaketteja keskenään samalla 12 mätsin säännöllä. Tämä ilmeisesti antoi myös epätodellisia mätsejä ja lopputulos oli väärä. (Joskin oikea harjoitusaineistolla) Kun muutin koodin niin, että ensin käydään sensoreiden keskinäiset kohdistukset ja vasta lopuksi yhdistetään kaikki, niin homma pelasi.
Jos olettaisin että lähdedatan luotaimien sijainnit olisi generoitu satunnaisesti, niin tuo väärien yhdistymisten todennäköisyys tuntuu aika pieneltä. Eli joko kävi huono tuuri tai tuo oli tehtävän laatijalta tahallinen miina.
Ainakin tässä oppi sen, että jos tehtävä ei näytä sellaiselta 5 minuutissa heittämällä ratkaistavalta, niin kannattaa miettiä huolellisesti strategia ja miettiä eri vaihtoehtoisten toteutustapojen hyödyt ja haitat. Olisin säästänyt tunteja.
Kerrankin heräsin ajoissa ja molemmat osiot tehty ennen Metabolixia ;)
feenix kirjoitti:
Kerrankin heräsin ajoissa ja molemmat osiot tehty ennen Metabolixia ;)
Joo, onnistuin koodaamaan jonkin ylimääräisen elämäpelin nurkkiin. Tuloksettoman debuggailun jälkeen päädyin sitten selvempään ratkaisuun, jossa silmukat menevät reilusti reunan yli ja yksinkertaisesti kuvan luku ja kirjoitus tarkastavat reunan yli menevät indeksit, koodi lyheni taas puoleen ja alkoi toimia oikein. Kumma juttu, miksen tehnyt alusta asti näin.
Oikeassa syötteessä tyhjät osat vaihtavat tilaa joka kierroksella mutta esimerkissä tästä vain vihjaillaan lauseilla kuten ”careful to account for the infinite size”. Tämänhän näkee helposti syötteen ensimmäisestä merkistä ja siis tuli kyllä huomioiduksi alusta asti, mutta olipa taas vähän ylimääräistä vaivaa keksitty oikeaan syötteeseen. Se on vissiin tänä vuonna tehtävien henki.
Itsellä valitettavasti meni tunti ihan muuhun niin olen ihan tyytyväinen tuohon 39 minuutin nettosuoritusaikaan. Olen ilmeisesti oppinut jotain viime viikonlopusta, kun tarkistin tuon Metabolixin mainitseman hasardin jo ennen kuin aloin koodaamaan :D
Metabolix kirjoitti:
yksinkertaisesti kuvan luku ja kirjoitus tarkastavat reunan yli menevät indeksit
Itse käytin vastaavaa jossain aikaisemman päivän tehtävässä, mutta tänään tein vaihtelun vuoksi lukuvaiheessa 2 numeron levyisen ylimääräisen kehyksen kuvan ympärille ja joka kierroksella uuteen kuvaan 2 levyisen kehyksen "avaruuden" arvolla ja laskin vain sen sisäpuolisen alueen.
Itse asiassa jatkon kannalta täytynee laittaa työkalupakkiin "defaulting 2d array" joka hoitaa indeksien tarkistuksen ja sopivan arvon palauttamisen, niin ei tarvitse joka päivä koodata erikseen.. :|
Metabolix kirjoitti:
Oikeassa syötteessä tyhjät osat vaihtavat tilaa joka kierroksella mutta esimerkissä tästä vain vihjaillaan lauseilla kuten ”careful to account for the infinite size”.
Jep, meni hetki että tuon sai täysin oikein. Luulin ottaneeni huomioon, mutta sitten tajusin että enpäs tehnytkään kunnolla. Tein sitten yksinkertaisesti ja hieman tehottomasti, mutta toimiipahan ainakin.
Tehtävät ovat kyllä välillä vähän epäselviä ja vaikka läpäisee testimateriaalin voi saada aivan eri tuloksia sitten oikealla datalla. Esim. pikkumoka tuossa pakettien parsimisessa ei näkynyt heti kun yhdessä kohdassa alipaketit olivat 2 ja 2, joten kun luin vahingossa saman paketin kahdesti se meni nätisti läpi testistä, mutta oikea data...
Onnittelut Henrikille top10 sijoituksesta.
Tämänpäiväinen oli kiva, joskin kesti vähän aikaa hahmottaa mitä toi kakkosvaiheen noppa käytännössä tarkoitti. Yhtä hyvin oltaisiin voitu sanoa että pelataan kaikki mahdolliset pelikulut läpi eikä oltaisi puhuttu rinnakkaisuniversumeista.
VilleVal kirjoitti:
Tämänpäiväinen oli kiva, joskin kesti vähän aikaa hahmottaa mitä toi kakkosvaiheen noppa käytännössä tarkoitti.
Nopealla vilkaisulla sähkötukun kahvipöydässä näyttäisi tämän päiväinen tehtävä olevan kohtuullisen pieni töinen verrattuna viime aikaisiin tehtäviin ja peräti helppo.
Tänään minulla oli näköjään haasteena tulkita sääntöjä..
lainaus:
Once an amphipod stops moving in the hallway, it will stay in that spot until it can move into a room. (That is, once any amphipod starts moving, any other amphipods currently in the hallway are locked in place and will not move again until they can move fully into a room.)
Luin tuon painottaen tuota suluissa olevaa että käytävällä olevat on toisten tiellä, mutta toki tuossa sanottiin myös että käytävällä ei voi lainkaan siirtyä paikasta toiseen, vaikka ketään ei olisikaan edessä.
Tein päivän tehtävän paperilla, mutta tuli ensin virheitä ja en ehtinyt tehdä toista osaa aamulla. Näin tehtynä ensimmäinen osa oli jopa vaikeampi, koska siinä oli monta mahdollista tapaa, joista piti löytää paras. Toiseen osaan näen suoraan vain yhden mahdollisuuden, jonka kuitenkin laskin ensin jostain kohti väärin. Koodaaminen näyttää turhan isolta vaivalta.
Itse koodasin vaan pikkuisen ohjelman jolla pystyi manuaalisesti "pelaamaan" ja laskemaan pisteet.
Mielestäni tuossa oli hyvin intuitiivista löytää paras tapa, koska eri lajien väliset piste-erot oli niin isoja. Eli siis käytännössä olisi ollut kaukaa haettua että A:lla ei kannattaisi tehdä mutkaa jos se säästää pienenkin mutkan B:ltä, jne.
Itse koodasin amfipodit, ei ollut monimutkainen ja aika nopeasti laskee vastauksen. Ensin antoi vääriä vaikka esimerkkisyöte menikin läpi, mutta sitten huomasin että taulukoissa oli pari väärää numeroa ja esimerkki ei käyttänyt niitä. Korjaus ja sen jälkeen meni kiltisti läpi.
Tämänpäiväistä pitänee vähän miettiä enemmän kuin ehtii, muunsin jo koodin "oikeaksi" koodiksi sen sijaan että lukisi syötteestä koska muuten ihan järjetöntä, algoritmiin varmaan löytyisi muutamia jippoja joilla voi hypätä ohi tarpeettomista operaatioista jos jaksaisi katsoa. Näyttää top-100-listan mukaankin hieman hankalammalta kuin moni muu.
Hauska kuulla, miten joku koodaa ratkaisun tämänpäiväiseen. Itse hukkasin reilusti yli tunnin koodin tulkkaamiseen ja optimointiin ja kikkailuun. Kuvittelin, että säätämällä sopivia rivejä (kuten +0 tai *0) saisi koodin merkittävästi selvempään muotoon. Tästä ei ollut lopulta mitään apua. Oikea ratkaisu löytyi jälleen käsin. Käsittämättömästi vielä ajalla 1:53:07 tuli sijoitus 409, eli on joku muukin tainnut koodailla ihan turhia.
Piti vain oikeasti katsoa syötettä ajatuksella ja huomata siitä yksi aivan ilmeinen asia, jonka avulla sen sai muutettua järkevästi luettavaan muotoon. Siitä loppuun ratkaisu vaati enää perustietoa kokonaislukujen jakolaskun ja jakojäännöksen käytöstä. Laitan taas rot13-spoilerin: Wbxn ahzrebyyr gbvfghh fnzn cnevaxlzzrara eviva xbbqv, wbxn zhhggnn m-neibn lxfvaxregnvfra ruqba zhxnna. Xbbqv gvvivfgll lugrra ynhfrxxrrfrra cre ahzreb. Ynhfrxxrvgn byv xnugn ynwvn: wbxb m-neibn wngxrgnna hhqryyn ahzrebyyn gnv fra ybchfgn cbvfgrgnna ahzreb gvrgla ruqba gbgrhghrffn. Ynhfrxxrvfgn ibv xbbgn innqvghg ahzrebcnevra rebghxfrg, wbyybva ba uryccb zhbqbfgnn fhheva wn cvrava yhxh abvyyn ruqbvyyn.
Aihe on jo aika vanha, joten et voi enää vastata siihen.