Advent of Code - the ugly truth

Squeeds Julkalender | 2023-12-04 | Lena Stridsberg
Det här inlägget är två år försenat och det finns en JÄTTEBRA anledning till det (såklart). För er som inte känner mig så behöver ni egentligen inte veta så mycket mer än att jag fullkomligt älskar när december drar igång så att jag kan gå upp riktigt, riktigt tidigt och bänka mig framför datorn innan arbetsdagen ens har börjat. Detta gör jag ju förstås eftersom Advent of Code släpper sitt första mysterium som behöver lösas och jag är tomtens främsta hjälpreda, I will rädda julen. Här kommer mina lösningar till dag 1 och 2.
christmas-2926962_640.jpg

Men just det, innan vi börjar, jag berättade ju att det fanns en jättebra anledning till varför det här inlägget är försenat och den anledningen finns -> här! <-

Vad som kommer hända nu är att jag tänker ta med er på en spännande resa kring mina två första dagar mot målet att rädda hela världens snöproduktion (tror jag?). Vilken ära för både er och mig!
Men här kommer twisten;
jag kommer att visa er den råa, ofiltrerade, orefaktorerade (ordet??), oraffinerade födseln av min kod.
Inget strössel på den här tårtan.
Inget presentpapper och glitter, inget smink - NI FATTAR.
Det här kommer antagligen bli lite pinsamt så plocka fram skämskudden. Nu kör vi.

Dag 1

Ska det vara såhär svårt första dagen?!Vad i hela friden händer här egentligen?
Dag 1 brukar alltid vara mysig; en dag där vi får känna oss smarta och leva i illusionen av att vi kommer flyga igenom de kommande 25 dagarna. Men i år. I år tänkte jag att jag måste ha backat rent utvecklingsmässigt och gått tillbaka 6 år i tiden eller något. Vilken ovanligt knivig start! 
Är det bara jag eller kände ni så också?
Här är länken till dag 1 -> DAG 1 <-

Lösning till del 1

LÄTT SOM EN PLÄTT tänkte jag vid första anblick. Nu var det inte plättlätt. Det var faktiskt ganska svårt.
Om vi börjar här......... 
Ni kanske noterar hur otroligt dåligt namngivet allting så redan nu vill jag ursäkta mig själv genom att säga att JAG VILLE LÖSA DETTA SNABBT och personligen skiter jag alltid i vad sakerna heter initialt. En int skulle kunna heta rand lika gärna, jag vill bara få igenom mina tester först - sen städar vi.
Då har jag fått ursäkta mig lite, nu fortsätter vi.

Så vi har alltså en rad som skulle kunna se ut som det här: 1abc2
Jag ville från den plocka ut första och sista siffran, så jag gjorde en liten steg-för-steg i mitt huvud och den såg ut såhär:

1. Ta bort allting som inte är siffror
Därav min String clean som var det första sättet jag kom på att rensa bort alla icke-siffror.

2. Hitta den första siffran
Inga konstigheter här, jag har ju städat bort alla icke-siffror från clean så här borde det första tecknet vara första siffran.
Jag hyser enorm tilltro till mitt regex här för felhantering är ingenting som bara flyger in vid födseln såattsäga.

3. Hitta den sista siffran
Detta gick undan också, jag körde en gammal modulus och rent teoretiskt så är entalet som blir kvar den sista siffran.
Den teorin översattes snyggt i praktiken också så vips hade jag sista siffran i handen såattsäga.

4. Gör dem till en ny siffra
Nu tar vi fram skämskudden allihopa, för det här är ju inte vackert. Men det fungerar. 
Jag gråter när jag ser det här och jag inser att jag sitter och riskerar mitt yrke för vissa saker jag kommer visa här.
Men vi släpper den här raden en stund och bara tackar och tar emot för DET FUNKAR.

5. Addera ihop
Vilket lyckligt slut allting fick hörrni, del 1 gick som smort. 

Lösning till del 2

Jaha. And the hell begins. Eller inte hell kanske, men en ljummen bastu? Detta är ju för tusan dag ETT.
Tillbaka till ritbordet och här blev min nya checklista:

1. Fixa ett Enum som håller siffrorna 1-9 både i siffer- och text-form
Ingen avancerad logik med det; alla siffrorna i mitt enum Numbers såg ut såhär;
ONE ("one", 1) etc etc etc.

2. Översätt varje rad till siffror
cleanString är ett namn på raden som nu har tolkats och översatts till ENBART siffror.
Metoden som fixar det ser ut såhär:

För att försöka översätta så börjar jag med att kika på om det första tecknet (som alltså antingen är en siffra eller en bokstav) är en siffra och om så är fallet så lägger jag till den i strängen jag bygger upp.
Om tecknet jag står på inte är en siffra så kommer jag jämföra med mitt egna enum för att se om strängen (med start på index i) matchar med någon av dem. Låt säga att vi har en rad som ser ut såhär: 1abcone2
Första varvet lägger vi en 1:a.
Andra varvet lägger vi inte till någonting eftersom inget av mina enum börjar på abcone2.
Tredje varvet lägger vi inte till någonting eftersom inget av mina enum börjar på bcone2.
Fjärde varvet lägger vi inte till någonting eftersom inget av mina enum börjar på cone2.
Femte varvet lägger vi till en 1:a eftersom mitt enum ONE matchar på one2.
Sjätte varvet lägger vi inte till någonting eftersom inget av mina enum börjar på ne2.
Sjunde varvet lägger vi inte till någonting eftersom inget av mina enum börjar på e2.
Åttonde varvet lägger vi till en 2:a.
Efter detta returnerar metoden strängen 112.

3. Hitta första siffran
Samma princip som första delen!

4. Hitta sista siffran
Samma princip som första delen!

5. Addera ihop
Tjohoo det gick ju!
Men det var inte smärtfritt.
Jag fastnade ett bra tag på att exempelvis "oneight" skulle returnera 18 och "eightwo" skull returnera 82.

Summering av dag 1

Jag är lite smått chockad fortfarande över att första dagen var såpass klurig, men jag hade kul!
Det är inte snyggt men för mig börjar det roliga nu när allting fungerar; städningen!
När jag har röjt upp så kommer jag slänga upp koden på github så om ni är intresserade av den transformationen får ni helt enkelt söka upp mig.

Dag 2

Detta har jag, nemas problemas!Famous last words.
Här är länken till dag 2: -> dag 2 <-
Jag kan inte med ord beskriva hur extremt lättad jag var när jag läste igenom den här uppgiften. TACK gode någon att det inte stack iväg i svårighetsgrad på en gång. Den här dagen var i mina ögon lättare, men den åsikten är säkert delad.

Lösning till del 1

Såhär ser min huvudmetod ut:

Nu när ni själva har läst beskrivningen till uppgiften så behöver jag ju inte beskriva hela problematiken och eftersom ni känner mig lite bättre såhär långt ner i inlägget så har ni ju såklart förstått att jag börjar med checklistorna direkt. Så var även fallet nu:

1. Skapa ett record GameData som håller information om antal av varje färg
Såhär: GameData(int knownRed, int knownBlue, int knownGreen){}
Jag döpte fälten till known[färg] för att värdet kommer vara maxvärdet av just den färgen för varje rad. 
Det kommer alltså vara så många jag VET finns i varje färg efter mina uträkningar.

2. Mappa varje rad till en Map<Integer, GameData> där nyckeln är radens id
En rad kunde se ut såhär: Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
I den raden så är 1:an radens id och det första jag gör i min loop är alltså att extrahera ut id:t.

I while-loopen i den här metoden så fångar jag den första gruppen från mitt regex; i det här fallet det innanför "()" som alltså plockar ut siffran som kommer efter "Game " och innan ":". Fungerade hur bra som helst om än lite slarvigt skrivet och med en hög dos av tilltro.... YOLO.

3. Skapa GameData-records för varje rad så att jag har all info jag behöver
Nu tycker jag att det var alldeles för längesedan skämskudden var framme. HÄMTA DEN! 

Den där sista raden som IntelliJ så snällt påpekar att jag inte har skrivit så jättebra beror på att jag gör en .get() på en Optional utan att göra en present check. Men vem har tid. Nu har jag lovat slarvig kod så här är den.
Men om vi bortser från den så kan jag förklara vad som händer här.

1. Jag vill få tag i den högsta siffran av varje färg för raden jag är på så jag skapar en metod för själva extraheringen.
2. I den skickar jag in färgen jag vill ha samt raden som jag nämnde tidigare.
3. Jag körde vidare med Pattern och letar alltså efter siffran som kommer före " [färg]". Det ger tillbaka en int.
4. Varje match jag får lägger jag till i en lista, så jag har en lista med antal av den färg jag är intresserad av.
5. returnen googlade jag fram och den plockar ut det högsta värdet....... Jag vill inte prata mer om det. Det fungerade.

4. Summera alla id:n som tillhör varje accepterat GameRecord
Den här metoden är väl ändå helt okej även om jag har sett så många smutta lösningar på den här övningar.
Lösningar på en rad. Jag hyser sån extrem respekt för människor som bara ser den snygga lösningen direkt och skriver ner den. Som att ni spelar schack och tänker 5 drag i förväg medan jag håller mig till max 2. Det är det jag klarar av, sen får jag sakta och stegvis närma mig den där snygga koden men det är inte sällan jag stannar halvvägs ärligt talat.
Nu är jag inte en enradare, jag skriver ut vad jag tänker ungefär.


Men jag loopar igenom min map och sen kollar jag om varje entry innehåller lika många eller mindre än [färg]Available och om så är fallet så ska id:t adderas på i summan.
KLAR!

Lösning till del 2

Nu blir det pinsamt igen. Jag har återigen fått IntelliJs klagomål och för er som var uppmärksamma såg ni det i en tidigare bild också...

Duplicated code fragment (9 lines long)

Såatteh.
9 rader duplicerad kod.
Det är hela metoden förutom returnen.
Det är inte snyggt.
Vi tittar på getSumOfMinimumNumbersOfEachColour istället.

Här har jag förstått att jag gjorde någonting bra i steg 1, för jag håller i ALL information jag behöver redan.
Den är liksom redan sparad ner i min gameDataMap. Toppen!
I steg 2 av uppgiften skulle jag multiplicera min röda, gröna och blåa known i varje rad med varandra och därefter skulle jag addera de talen med varandra för att få det slutgiltiga resultatet.
Det gick. Jag var nöjd. Jag stängde ner datorn och fixade frukost till barnen.

Summering av dag 2

Herregud vad skönt. Jag kände att jag hade ett stabilt flow under hela övningen.
Kände tillochmed den där känslan av att vara BRA. Jag kände mig såattsäga... Värdig mitt yrke?

Vad ville jag med detta egentligen då?

Jag vet inte om jag är ensam med det här, men jag hoppas verkligen inte det..
Ibland kan jag sitta med en uppgift på jobbet - som oftast innebär att jag ändrar andra personers kod - och få sån extrem dusch av imposter syndrome att jag vill krypa under skrivbordet. Människor runt omkring mig är så duktiga, så talangfulla.
Var lagrar de all information för att kunna skriva så bra kod?
Varför gör inte jag det? Varför skriver jag min kod i etapper?
Steg 1. Skräp.
Steg 2. Mindre skräpigt.
Steg 3. Nu börjar det likna något.
Steg 4. Okej du är värdig.
Steg 5. Sällan jag hamnar här ärligt talat.

Jag vill egentligen inte göra mer än att bara kasta upp min första kod så att någon där ute som också skriver många rader inte känner sig så ensam. Eller så gjorde jag det för att SNÄLLA be er som gör såhär att pinga mig så att jag slipper känna mig så ensam.
Så gör en god gärning nu inför jul och bota min imposter syndrome för all framtid?

Skämt åsido, jag ville bara skriva av mig lite. God jul och gott nytt år!