Inlägg

Inlägg som Xenofonus har skrivit i forumet
Av Xenofonus

Fick jobb på min LIA-plats (2-årigt YH-program). Där blev jag kvar ca 2 år och kunde lätt byta jobb sen.

Av Xenofonus

Dag: 4
Språk: C#

public static void Run() { var scratchies = FileReader.ReadLines("Day4.txt") .Select(x => { var idAndGameDetails = x.Split(":", StringSplitOptions.RemoveEmptyEntries); var id = int.Parse(idAndGameDetails[0].Split(" ", StringSplitOptions.RemoveEmptyEntries)[1]); var numbers = idAndGameDetails[1].Split("|", StringSplitOptions.TrimEntries); var winningNumbers = numbers[0].Split(" ", StringSplitOptions.RemoveEmptyEntries).Select(x => int.Parse(x)).ToList(); var scratchyNumbers = numbers[1].Split(" ", StringSplitOptions.RemoveEmptyEntries).Select(x => int.Parse(x)).ToList(); return new Scratchy(id, winningNumbers, scratchyNumbers); }).ToList(); var part1Res = scratchies.Select(x => { var numOfIntersection = x.WinningNumbers.Intersect(x.ScratchysNumbers).Count(); return numOfIntersection > 1 ? Math.Floor(Math.Pow(2, numOfIntersection-1)) : numOfIntersection; }).Sum(); Console.WriteLine(part1Res); for (int i = 0; i < scratchies.Count; i++) { var scratchy = scratchies[i]; for (int j = 0; j < scratchy.Instances; j++) { var numOfIntersection = scratchy.WinningNumbers.Intersect(scratchy.ScratchysNumbers).Count(); var lastIndex = numOfIntersection <= scratchies.Count - 1 ? numOfIntersection + i + 1 : scratchies.Count - 1; for (int k = i + 1; k < lastIndex; k++) { var scratchyCopy = scratchies[k] with { Instances = scratchies[k].Instances + 1 }; scratchies[k] = scratchyCopy; } } } Console.WriteLine(scratchies.Sum(x => x.Instances)); } internal record Scratchy(int Id, IReadOnlyList<int> WinningNumbers, IReadOnlyList<int> ScratchysNumbers, int Instances = 1);

Dold text
Av Xenofonus

Dag: 1
Språk: C#
Kommentar: Not great, not terrible

var day1Res = FileReader.ReadLines("Day1.txt") .Select(x => { var first = x.ToCharArray().First(possibleNum => char.IsNumber(possibleNum)); var last = x.ToCharArray().Last(possibleNum => char.IsNumber(possibleNum)); return char.GetNumericValue(first) * 10 + char.GetNumericValue(last); }).Sum(); Console.WriteLine(day1Res); var day1Res2 = FileReader.ReadLines("Day1.txt") .Select(x => { var firstIndex = int.MaxValue; var firstValue = 0; var secondIndex = int.MinValue; var secondValue = 0; foreach (var item in numToInt) { var indexOfFirstKey = x.IndexOf(item.Key); if (indexOfFirstKey >= 0 && indexOfFirstKey < firstIndex) { firstIndex = indexOfFirstKey; firstValue = item.Value; } var indexOfSecondKey = x.LastIndexOf(item.Key); if (indexOfSecondKey >= 0 && indexOfSecondKey > secondIndex) { secondIndex = indexOfSecondKey; secondValue = item.Value; } } return firstValue*10 + secondValue; }).Sum(); Console.WriteLine(day1Res2); }

Dold text

Dag: 2
Språk: C#
Kommentar: Nöjd med denna

public static void Run() { var games = FileReader.ReadLines("Day2.txt") .Select(GameMaker) .ToList(); var day1Res = games.Where(x => x.Possible).Select(x => x.Id).Sum(); Console.WriteLine(day1Res); var day2Res = games.Select(x => x.Blue * x.Red * x.Green).Sum(); Console.WriteLine(day2Res); } private static Game GameMaker(string input) { var idAndCubesSeparation = input.Split(":", StringSplitOptions.RemoveEmptyEntries); string id = idAndCubesSeparation[0].Split(" ")[1]; var game = new Game(int.Parse(id)); var gameSections = idAndCubesSeparation[1].Split(";", StringSplitOptions.RemoveEmptyEntries); foreach (var section in gameSections) { var sectionColorParts = section.Split(",", StringSplitOptions.RemoveEmptyEntries); foreach (var colorPart in sectionColorParts) { var numCubesAndColor = colorPart.Split(" ", StringSplitOptions.RemoveEmptyEntries); var num = int.Parse(numCubesAndColor[0]); var color = numCubesAndColor[1]; //if Possible has been set to false, it will stay false, otherwise do the value check game = (color) switch { "blue" => game with { Possible = !game.Possible ? game.Possible : num <= Game.BLUE_LIMIT, Blue = int.Max(game.Blue, num) }, "red" => game with { Possible = !game.Possible ? game.Possible : num <= Game.RED_LIMIT, Red = int.Max(game.Red, num) }, "green" => game with { Possible = !game.Possible ? game.Possible : num <= Game.GREEN_LIMIT, Green = int.Max(game.Green, num) }, _ => game }; } } return game; } private record Game(int Id, int Blue = 0, int Red = 0, int Green = 0, bool Possible = true) { internal const int BLUE_LIMIT = 14; internal const int RED_LIMIT = 12; internal const int GREEN_LIMIT = 13; }

Dold text

Dag: 3
Språk: C#
Kommentar: Fy fan jag borde sluta koda och bli jordgubbsförsäljare var känslan jag fick

public static void Run() { var lines = FileReader.ReadLines("Day3.txt"); var lineDetails = lines .Select((line, index) => { List<Gear> gears = []; List<LineNumber> lineNumbers = []; string currNumber = ""; for (int i = 0; i < line.Length; i++) { var currChar = line[i]; if (currChar == '*') { gears.Add(new Gear(i, [])); } if (!char.IsNumber(currChar)) { if (currNumber != "") { lineNumbers.Add(new LineNumber(int.Parse(currNumber), i - currNumber.Length, i)); currNumber = ""; } } else { currNumber += currChar; } } if (currNumber != "") { lineNumbers.Add(new LineNumber(int.Parse(currNumber), line.Length - currNumber.Length, line.Length)); } return new LineDetails(line, index, index == 0, index == lines.Length - 1, lineNumbers, gears); }) .ToList(); lineDetails.ForEach(ld => ld.Numbers.ForEach(ln => ln.CheckSurrounding(ld, lineDetails))); var part1Res = lineDetails.SelectMany(ld => { return ld.Numbers.Where(ldn => ldn.SymbolSurrounded); }).Sum(x => x.Number); var part2Res = lineDetails .SelectMany(ld => ld.Gears) .Where(x => x.Numbers.Count == 2) .Select(x => x.Numbers.Aggregate((a, b) => a * b)) .Sum(); Console.WriteLine(part1Res); Console.WriteLine(part2Res); } internal record LineDetails(string Line, int Index, bool IsTop, bool IsBottom, List<LineNumber> Numbers, List<Gear> Gears); internal class LineNumber() { public int Number { get; init; } public int StartIndex { get; init; } public int EndIndex { get; init; } public bool SymbolSurrounded { get; set; } readonly Func<char, bool> _isSymbol = (char c) => (!char.IsNumber(c) && c != '.'); readonly Func<char, bool> _isGear = (char c) => (c == '*'); public LineNumber(int number, int startIndex, int endIndex, bool symbolSurrounded = false) : this() { Number = number; StartIndex = startIndex; EndIndex = endIndex; SymbolSurrounded = symbolSurrounded; } public void CheckSurrounding(LineDetails ld, List<LineDetails> allLines) { bool addedTopAlready = false; bool addedBottomAlready = false; for (int i = StartIndex; i < EndIndex; i++) { if (!ld.IsTop) { var lineDescriptionAbove = allLines[ld.Index - 1]; var upperleftIndex = i > 0 ? i - 1 : -1; var upperRightIndex = i < ld.Line.Length - 1 ? i + 1 : -1; if (upperleftIndex > 0) { if (_isGear(lineDescriptionAbove.Line[upperleftIndex]) && !addedTopAlready) { lineDescriptionAbove.Gears.First(x => x.Index == upperleftIndex).Numbers.Add(Number); addedTopAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionAbove.Line[upperleftIndex])) this.SymbolSurrounded = true; } if (_isGear(lineDescriptionAbove.Line[i]) && !addedTopAlready) { lineDescriptionAbove.Gears.First(x => x.Index == i).Numbers.Add(Number); addedTopAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionAbove.Line[i])) this.SymbolSurrounded = true; if (upperRightIndex > 0) { if (_isGear(lineDescriptionAbove.Line[upperRightIndex]) && !addedTopAlready) { lineDescriptionAbove.Gears.First(x => x.Index == upperRightIndex).Numbers.Add(Number); addedTopAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionAbove.Line[upperRightIndex])) this.SymbolSurrounded = true; } } if (!ld.IsBottom) { var lineDescriptionBelow = allLines[ld.Index + 1]; var lowerleftIndex = i > 0 ? i - 1 : -1; var lowerRightIndex = i < ld.Line.Length - 1 ? i + 1 : -1; if (lowerleftIndex > 0) { if (_isGear(lineDescriptionBelow.Line[lowerleftIndex]) && !addedBottomAlready) { lineDescriptionBelow.Gears.First(x => x.Index == lowerleftIndex).Numbers.Add(Number); addedBottomAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionBelow.Line[lowerleftIndex])) this.SymbolSurrounded = true; } if (_isGear(lineDescriptionBelow.Line[i]) && !addedBottomAlready) { lineDescriptionBelow.Gears.First(x => x.Index == i).Numbers.Add(Number); addedBottomAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionBelow.Line[i])) this.SymbolSurrounded = true; if (lowerRightIndex > 0) { if (_isGear(lineDescriptionBelow.Line[lowerRightIndex]) && !addedBottomAlready) { lineDescriptionBelow.Gears.First(x => x.Index == lowerRightIndex).Numbers.Add(Number); addedBottomAlready = true; } if (!SymbolSurrounded && _isSymbol(lineDescriptionBelow.Line[lowerRightIndex])) this.SymbolSurrounded = true; } } if (i > 0) { if (_isGear(ld.Line[i - 1])) ld.Gears.First(x => x.Index == i - 1).Numbers.Add(Number); if (!SymbolSurrounded && _isSymbol(ld.Line[i-1])) this.SymbolSurrounded = true; } if (i < ld.Line.Length - 1) { if (_isGear(ld.Line[i + 1])) ld.Gears.First(x => x.Index == i+1).Numbers.Add(Number); if (!SymbolSurrounded && _isSymbol(ld.Line[i + 1])) this.SymbolSurrounded = true; } } } } internal record Gear(int Index, List<int> Numbers);

Dold text
Av Xenofonus

Inte svaret du söker men det viktigaste är definitivt du själv och att du redan nu börjar plugga mer om du har intresset. Se skolan mer som en vägledning.

Av Xenofonus

Provade massa olika pushnotistjänster för RN ungefär 2 år sedan och då tyckte jag expo push notification var lättast. Kan ju ha hänt en del på den tiden så klart men ta en titt.

Av Xenofonus

Här är kursen som fick mig att bli så intresserad att jag tillslut bytte karriär till utvecklare.

udemykurs

Börjar från noll och slutar med att bygga en fullstackapp, du kommer inte att kunna gå och jobba efter kursen men du har kommit en bra bit på vägen.

Av Xenofonus
Skrivet av heretic16:

Det blev lite grötigt med att använda enums när man behöver dom i strängar.

Så jag gjorde om koden och använde bara strängar helt enkelt.

Och istället använde jag mallar.

template <typename T, std::size_t N> int Tools_Software_Algorithms_findIndexOf(const T(&arr)[N], const T& value) { for (std::size_t i = 0; i < N; i++) { if (arr[i] == value) { return i; } } return -1; // Not found } template <typename T, std::size_t N> constexpr std::size_t Tools_Software_Algorithms_getArraySize(const T(&)[N]) { return N; }

Jag hoppas att detta ska fungera bättre.

Jag kan inte C++ så bra men har sett dig skriva i andra trådar att prestanda är väldigt viktigt för dig. Den här lösningen verkar ha en annan filosofi om vi säger så, åtminstone jämfört med lösningarna ovan?

Av Xenofonus
Skrivet av heretic16:

Nu när tråden är varm, då tänkte jag ställa en liten fråga som berör struktur.

Jag jobbar inte som mjukvarutuvecklare, men jag håller på programmera mycket på fritiden och även inom jobbet.
När jag programmerar så har jag en tendens att strukturera om mina filer hela tiden i mappar. Jag har liksom många mappar där bara enskilda filer ligger.

Detta tar dock en tid, men när jag hittar min struktur så blir projektet allt lättare att modifiera vid behov.
Känner ni igen er också att varje projekt tar sin tid att få sin struktur och när strukturen är klar, ja då är det 10X lättare att programmera?

Jag försöker undvika till varje pris att få spagettikod. Jag skriver aldrig sådant dock, så jag är mycket noga på att från vissa t.ex. .cpp filer så skall man ej kunna anropa vissa funktioner.

Jag kör inte OOP, om inte behovet finns tydligt.

Oftast så följer man nog en etablerad standard, åtminstone på jobbet. Databasfiler ligger där, controllers ligger där, e t c.

Av Xenofonus

De som säger att språk Y kommer att döda/byta ut språk X är väl mest click baiters, det förstår nog de flesta. Det är samma sak som när det kommer nya JS-ramverk eller exempelvis Microsoft Blazor, de har lärt sig av sina föregångare och kanske har coola features som löser vanliga problem från sina föregångare men det finns nog ingen som tror att alla kommer sluta rakt av med de äldre sakerna då för mycket tid har investerats, både i arbetstid och kompetensmässigt.

Så om det sker en förändring är den nog mer långsam, över ett decennium eller mer.

Av Xenofonus

Tror du kan behöva visa mer kod för att se vad som händer på andra ställen.

Av Xenofonus

Rekommenderar Visual Studio 2022 istället för 2019, åtminstone i C# så känns den mycket smartare än 2019.

Av Xenofonus
Skrivet av Yoshman:

Vad som är värt att veta här är att kompilatorn ofta har svårare att göra något riktigt optimalt med det sista.

Testar man dina två exempel så är är "foreach" versionen ungefär 2x så snabb som den deklarativa versionen.

Vidare kanske nedan är mer vad man rimligen borde ha skrivit om man siktade på en imperativ version, den är 6x snabbare än den deklarativa versionen (bench:at med BenchmarkDotNet) och .NET 7.0.

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; double sumDoubledEvenNumbers = 0; int numEvenNumbers = 0; foreach (var number in ints) { if (number % 2 == 0) { sumDoubledEvenNumbers += number * 2; numEvenNumbers++; } } double average = sumDoubledEvenNumbers / numEvenNumbers;

Prestanda är definitivt inte allt och helt klart kan den deklarativa varianten vara betydligt enklare att förstå i vissa lägen. Men den stilen är inte helt icke-kontroversiell, det är fullt möjligt att skriva kod på det sättet i Golang (finns bibliotek som gör det möjligt) men där är det i stort sätt konsensus att "for-loop" är lättare för andra att förstå och därför att föredra.

Men finns lägen där den deklarativa versionen kan ge prestandafördelar. Java parallel streams, Rust Rayon, standard C++ par/par_unseq execution policies och liknande kan med rätt typ av problem ge en rätt fin prestandaboost som ofta är betydlig svårare att få till med imperativ stil.

Så som det mesta inom programmeringsvärlden, vad som är "bäst" är långt ifrån entydigt...

Ja just i C#-LINQ är implementationen att först görs din collection om till en IEnumerable, och att varenda metod du sedan kedjar på blir en loop som skapar upp en ny IEnumerable med förändringen (eller aggregerar ihop den som med t ex Average, Sum och så klart Aggregate). Så inge vidare om det är högsta möjliga prestanda man jagar.

Av Xenofonus
Skrivet av heretic16:

Ja. Vad betyder det där liksom.

Jag förstår idén med att skriva allt på en enda rad, men det blir grötigt.

Jag ogillar C++ auto som finns överallt. Är detta något sätt för att komma bort från int, float, long, double, short, uint16_t osv?

Nu kan jag inte just den där syntaxen men det är väl som fluid interfaces i alla språk, om man inte läsa det så ser det fruktansvärt komplicerat ut men när man kan det så blir det mycket mer läsligt. Påhittat krysstat exempel i C#:

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var evenDoubledInts = new List<int>(); foreach(var number in ints) { if(number % 2 == 0) { evenDoubledInts.Add(number*2); } } int totalSum = 0; foreach(var number in evenDoubledInts) { totalSum += number; } double average = totalSum / evenDoubledInts.Count;

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; double average = ints .Where(x => x % 2 == 0) .Select(x => x*2) .Average();

Vi beskriver för kompilatorn deklarativt vad vi vill göra och låter den oroa sig för detaljerna, jag vill bara ha de jämna talen, jag vill att de dubbleras och till sist vill jag veta medelvärdet. Hur du gör bryr jag mig inte om.

Av Xenofonus
Skrivet av WebbkodsLärlingen:

Så där försöker den skriva ut "bleh" innan fetch-anropet hinner slutföras? Rent förenklat talat, hur bör man då kombinera det med await så det blir som önskat? Typ något i stil med:

let bleh; const getBleh = fetchBs().then( (asd) =>{ //asynkront anrop bleh = asd; }) console.log(await getBleh);

Nu har jag inte börjat lära mig ES6 ännu men det jag tänker är att nyckelordet "await" används för att förhindra kod direkt under koden som innehåller "await" från att köras? Samtidigt så verkar det inte gå att skriva await varsomhelst i kod? Så då verkar det nästan som om allt måste vara async-funktioner för att man ska ha koll på exekveringsflödet?

För det vi vill se till är att console.log() inte får köras förrän async-anropet är färdigt och hur gör man det om inte console.log själv är inuti samma async-anrop för att "await" ska få användas?

För att använda await i js måste man vara i ett asyncblock vilket kan bli awkward ibland. Lättaste i det där fallet vore att skapa en ny . then-kedja eller antagligen ännu bättre göra allt innanför den första .thenfunktionen

Av Xenofonus

Som nybörjare kommer de verka som samma språk nästan. När man börjar komma igång med mer avancerade grejer skulle jag säga att C# definitivt har lite roligare funktioner som object initializersyntaxen, LINQ slår Java streams lätt, anonyma objekt i LINQ, string interpolation och async/await syntaxen.

Men mina Javakunskaper är några år nu så det kanske har kommit ikapp/förbi på de områdena eller andra.

Av Xenofonus

Är nog lättast om du hittar en youtubevideo där du kan se exakt vad de klickar på och vad som ändras, auto layout är jäkligt klurig och drar du sedan i komponenten så försvinner auto layouten... massa bök.

Av Xenofonus

Bygga på "traditionellt" sätt, betyder det t ex bygga SPA-applikationer eller menar du bokstavligen old school HTML/CSS/sprinkla lite JS?

Av Xenofonus
Skrivet av heretic16:

Men problemet är att när jag skapar min release-applikation, alltså mappen. Så hamnar alla mina .dll och .exe filer där, men ingen "minFil.txt" finns där.

Menar du att de kommer med när du bygger din debug? I såna fall har du inte ändrat konfigureringen för ditt releaseprojekt utan bara debug.

Av Xenofonus

Ska man inte klicka på filen och ändra "copy to output directory" i file properties? Eller funkar inte det i för C++-solutions?

Av Xenofonus

Dag 7 Kotlin

class Day7 { fun run() { val input = java.io.File("src/input/day7.txt").readLines(); val fileStructure = addChildren(input) var root = fileStructure while (root?.parentDirectory != null) { root = root?.parentDirectory } val part1Answer = root!!.part1() val part2Answer = root!!.part2(30000000).minByOrNull { it.totalSize }!! println(part1Answer) println(part2Answer.totalSize) println(root!!.part1test()) } private tailrec fun addChildren(instructions: List<String>, currentDirectory: Directory? = null): Directory? { if (instructions.isEmpty()) { return currentDirectory } val instruction = instructions.first() when { instruction.startsWith("dir ") -> { val directoryName = instruction.split(" ")[1] val newDirectory = Directory(currentDirectory, mutableListOf(), mutableListOf(), directoryName) currentDirectory?.subDirectories?.add(newDirectory) return addChildren(instructions.drop(1), currentDirectory) } instruction.split(" ")[0].all { it.isDigit() } -> { val fileParts = instruction.split(" ") val newFile = File(currentDirectory!!, fileParts[1], fileParts[0].toInt()) currentDirectory?.files?.add(newFile) return addChildren(instructions.drop(1), currentDirectory) } instruction == "$ ls" -> return addChildren(instructions.drop(1), currentDirectory) instruction.startsWith("$ cd") -> { val targetDirectory = instruction.split(" ")[2] if (targetDirectory == "/") { return addChildren( instructions.drop(1), Directory(null, mutableListOf(), mutableListOf(), targetDirectory) ) } if (targetDirectory == "..") { return addChildren(instructions.drop(1), currentDirectory?.parentDirectory) } return addChildren( instructions.drop(1), currentDirectory?.subDirectories?.find { it.name == targetDirectory }) } } throw IllegalArgumentException("nu blev det tokigt igen") } class Directory( val parentDirectory: Directory?, val subDirectories: MutableList<Directory>, val files: MutableList<File>, val name: String ) { val totalSize: Int by lazy { files.sumOf { it.size } + this.subDirectories.sumOf { it.totalSize } } fun part1(): Int { val size = if (totalSize < 100000) totalSize else 0 return size + this.subDirectories.sumOf { it.part1() } } fun part1test(): Int { println(this.name + ": " + this.totalSize) return totalSize + this.subDirectories.sumOf { it.part1test() } } fun part2( targetFreeSpace: Int, currentFreeSpace: Int = 70000000 - this.totalSize, directoriesForDelete: MutableList<Directory> = mutableListOf() ): List<Directory> { if (currentFreeSpace + this.totalSize >= targetFreeSpace) { directoriesForDelete.add(this) } for (childDirectory in this.subDirectories) { childDirectory.part2(targetFreeSpace, currentFreeSpace, directoriesForDelete) } return directoriesForDelete } } class File(val parentDirectory: Directory, val name: String, val size: Int) }

Dold text

Dag 8 Koltin

class Day8 { fun run(){ //val input = "30373\n25512\n65332\n33549\n35390".split("\n") val input = File("src/input/day8.txt").readLines(); val allTrees: List<List<Tree>> = input.mapIndexed { y, treeLine -> val trees = treeLine.split("").subList(1, treeLine.length+1) trees.mapIndexed { x, tree -> Tree(x, y, tree.toInt()) } } val forest = Forest(allTrees) println(forest.treesVisibleFromAnywhere) println(forest.highestScenicValue) } } class Forest(val trees: List<List<Tree>>) { val treesVisibleFromAnywhere: Int by lazy { var visibleTrees = 0 for (y in trees.indices) { for(x in trees[0].indices) { val currentTree = trees[y][x] val treeLineHorizontal = trees[y] val treeLineVertical = getVerticalTreeLine(x) val hasAnyHeigherLeft = treeLineHorizontal.filter { it != currentTree && it.x < currentTree.x }.all { it.height < currentTree.height } val hasAnyHeigheRight = treeLineHorizontal.filter { it != currentTree && it.x > currentTree.x }.all { it.height < currentTree.height } val hasAnyHeigherAbove = treeLineVertical.filter { it != currentTree && it.y < currentTree.y }.all { it.height < currentTree.height } val hasAnyHeigherBelow = treeLineVertical.filter { it != currentTree && it.y > currentTree.y }.all { it.height < currentTree.height } visibleTrees += when{ y == 0 || y == trees.size-1 -> 1 x == 0 || x == trees[0].size-1 -> 1 hasAnyHeigherLeft || hasAnyHeigheRight -> 1 hasAnyHeigherAbove || hasAnyHeigherBelow -> 1 else -> 0 } } } visibleTrees } val highestScenicValue: Int get(){ var highestScore = 0 val treeCounter = {treesToCount: List<Tree>, treeCountDirection: TreeCountDirection, currentTree: Tree -> val treesOnSpecifiedSide = when(treeCountDirection){ TreeCountDirection.LEFT -> treesToCount.filter { it != currentTree && it.x < currentTree.x}.reversed() TreeCountDirection.RIGHT -> treesToCount.filter { it != currentTree && it.x > currentTree.x } TreeCountDirection.UP -> treesToCount.filter { it != currentTree && it.y < currentTree.y }.reversed() TreeCountDirection.DOWN -> treesToCount.filter { it != currentTree && it.y > currentTree.y } }.takeWhile { it.height < currentTree.height } treesOnSpecifiedSide.count() + when(treeCountDirection){ TreeCountDirection.LEFT -> if (treesOnSpecifiedSide.lastOrNull()?.x != 0) 1 else 0 TreeCountDirection.RIGHT -> if (treesOnSpecifiedSide.lastOrNull()?.x != treesToCount.size-1) 1 else 0 TreeCountDirection.UP -> if (treesOnSpecifiedSide.lastOrNull()?.y != 0) 1 else 0 TreeCountDirection.DOWN -> if (treesOnSpecifiedSide.lastOrNull()?.y != trees.size-1) 1 else 0 } } for (y in 1 .. trees.size - 2) { for(x in 1 .. trees[0].size - 2) { val currentTree = trees[y][x] val treeLineHorizontal = trees[y] val treeLineVertical = getVerticalTreeLine(x) val scoreLeft = treeCounter(treeLineHorizontal, TreeCountDirection.LEFT, currentTree) val scoreRight = treeCounter(treeLineHorizontal, TreeCountDirection.RIGHT, currentTree) val scoreAbove = treeCounter(treeLineVertical, TreeCountDirection.UP, currentTree) val scoreBelow = treeCounter(treeLineVertical, TreeCountDirection.DOWN, currentTree) val score = scoreLeft*scoreRight*scoreAbove*scoreBelow if(score > highestScore) { highestScore = score } } } return highestScore } private fun getVerticalTreeLine(x: Int): List<Tree> { var verticalTrees: MutableList<Tree> = mutableListOf() for(treeLine in trees) { verticalTrees.add(treeLine[x]) } return verticalTrees.toList() } } data class Tree(val x: Int, val y: Int, val height: Int) enum class TreeCountDirection{ LEFT, RIGHT, UP, DOWN }

Dold text

Dag 9 Koltin

class Day9 { fun run() { val input = File("src/input/day9.txt").readLines() val moves = input.map { val moveParts = it.trim().split(" ") val moveDirection = when (moveParts[0]) { "U" -> MoveCommand.Direction.UP "D" -> MoveCommand.Direction.DOWN "L" -> MoveCommand.Direction.LEFT "R" -> MoveCommand.Direction.RIGHT else -> throw IllegalArgumentException() } MoveCommand(moveDirection, moveParts[1].toInt()) } println(Knots(2).moveAround(moves)) println(Knots(10).moveAround(moves)) } } class MoveCommand(val direction: Direction, val totalSteps: Int) { val isVertical: Boolean by lazy { direction == Direction.UP || direction == Direction.DOWN } enum class Direction(val step: Int) { UP(1), DOWN(-1), LEFT(-1), RIGHT(1) } } data class Knot(var current: Point, val isHead: Boolean = false) class Knots(numberOfKnots: Int){ private val allKnots: LinkedList<Knot> = LinkedList() init { val head = Knot(Point(0, 0), true) allKnots.addFirst(head) IntRange(1, numberOfKnots-1).forEach { _ -> allKnots.add(Knot(Point(0,0))) } } fun moveAround(commands: List<MoveCommand>): Int { val uniqueLocations: MutableSet<Pair<Int, Int>> = mutableSetOf(Pair(0, 0)) commands.forEach {command -> for (step in 0 until command.totalSteps) { allKnots.forEachIndexed{knotIndex, knot -> if(knot.isHead) { moveHead(knot, command) } else { val lastKnot = allKnots[knotIndex-1] moveTailPart(knot, lastKnot) } } val tailCurrentLocation = Pair(allKnots.last.current.x, allKnots.last.current.y) uniqueLocations.add(tailCurrentLocation) } } return uniqueLocations.size } companion object { private fun moveHead(head: Knot, command: MoveCommand) = if (command.isVertical) head.current.move(head.current.x, head.current.y + command.direction.step) else head.current.move(head.current.x + command.direction.step, head.current.y) private fun moveTailPart(tailPart: Knot, lastPart: Knot){ val currentPoint = tailPart.current val lastPoint = lastPart.current if(currentPoint.distance(lastPoint) == 2.0) { val newX = (lastPoint.x + currentPoint.x) / 2 val newY = (lastPoint.y + currentPoint.y) / 2 currentPoint.move(newX, newY) } else if (currentPoint.distance(lastPoint) > 2.0) { val newX = when{ lastPoint.x > currentPoint.x -> currentPoint.x+1 lastPoint.x < currentPoint.x -> currentPoint.x-1 else -> currentPoint.x } val newY = when{ lastPoint.y > currentPoint.y -> currentPoint.y+1 lastPoint.y < currentPoint.y -> currentPoint.y-1 else -> currentPoint.y } currentPoint.move(newX, newY) } } } }

Dold text

Dag 10 Koltin

class Day10 { fun run() { val input = File("src/input/day10.txt").readLines() val display = Display(input) println(display.runInstructions()) println(display.part2Sb.toString()) } } class Display(private val instructions: List<String>){ private var x: Int = 1 val part2Sb: StringBuilder = java.lang.StringBuilder() private var cycleNumber: Int by Delegates.observable(0){prop, oldValue, newValue -> if(newValue % 20 == 0 && newValue % 40 != 0) { signalStrengths.add(x*newValue) } val currentPositionOnRow = (newValue - 1) % 40 val spriteIsInView = currentPositionOnRow == x-1 || currentPositionOnRow == x || currentPositionOnRow == x+1 if (spriteIsInView) part2Sb.append("#") else part2Sb.append(".") if(currentPositionOnRow == 39) { part2Sb.append("\n") } } private val signalStrengths: MutableList<Int> = mutableListOf() fun runInstructions(): Int { for ( instruction in instructions) { when{ instruction == "noop" -> cycleNumber++ instruction.startsWith("addx") -> { val value = instruction.split(" ")[1].toInt() repeat(2){cycleNumber++} x += value } } } return signalStrengths.sum() } }

Dold text

Jag har inte lekt med Kotlin innan det här så om någon ser något uppenbart jättekonstigt jag gör så vill jag gärna veta Tyckte om observablen i del 10 i a f. Trevligt språk!