diff --git a/AdventOfCode/AdventOfCode.csproj b/AdventOfCode/AdventOfCode.csproj index 72b5faa..0ff1ded 100644 --- a/AdventOfCode/AdventOfCode.csproj +++ b/AdventOfCode/AdventOfCode.csproj @@ -13,7 +13,6 @@ - diff --git a/AdventOfCode/Common/AOCExtensions.cs b/AdventOfCode/Common/AOCExtensions.cs index 489d462..526074c 100644 --- a/AdventOfCode/Common/AOCExtensions.cs +++ b/AdventOfCode/Common/AOCExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; namespace AOC2021.Helper { @@ -8,5 +10,14 @@ namespace AOC2021.Helper { return Convert.ToInt32(str); } + + public static IEnumerable> Chunk(this IEnumerable source, int chunksize) + { + while (source.Any()) + { + yield return source.Take(chunksize); + source = source.Skip(chunksize); + } + } } } diff --git a/AdventOfCode/Models/AOCDay.cs b/AdventOfCode/Models/AOCDay.cs index 1a4a096..43d70f8 100644 --- a/AdventOfCode/Models/AOCDay.cs +++ b/AdventOfCode/Models/AOCDay.cs @@ -55,8 +55,10 @@ namespace AdventOfCode.Models protected abstract AOCResponse ExecutePartA(); protected abstract AOCResponse ExecutePartB(); - protected string[] GetSplitInput() + protected string[] GetSplitInput(bool noTrim = false) { + if (noTrim) + return this._request.Input.Replace("\r", "").Split("\n"); return this._request.Input.Trim().Replace("\r", "").Split("\n"); } diff --git a/AdventOfCode/Properties/launchSettings.json b/AdventOfCode/Properties/launchSettings.json index 028a864..c26a05f 100644 --- a/AdventOfCode/Properties/launchSettings.json +++ b/AdventOfCode/Properties/launchSettings.json @@ -1,5 +1,4 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", +{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, @@ -8,10 +7,10 @@ "sslPort": 44329 } }, + "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "IIS Express": { "commandName": "IISExpress", - "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -19,13 +18,12 @@ }, "AdventOfCode": { "commandName": "Project", - "dotnetRunMessages": "true", - "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": "true", + "applicationUrl": "https://localhost:5001;http://localhost:5000" } } -} +} \ No newline at end of file diff --git a/AdventOfCode/_2022/Day3.cs b/AdventOfCode/_2022/Day3.cs index 555d1da..7b823e7 100644 --- a/AdventOfCode/_2022/Day3.cs +++ b/AdventOfCode/_2022/Day3.cs @@ -1,5 +1,6 @@ using AdventOfCode.Common; using AdventOfCode.Models; +using AOC2021.Helper; using System; using System.Collections.Generic; using System.Linq; @@ -27,26 +28,18 @@ namespace AdventOfCode._2022 protected override AOCResponse ExecutePartB() { var rows = GetSplitInput(); - var elves = new List(); - int elfSet = 0; - for (int i = 0; i < rows.Length; i++) - { - if (string.IsNullOrWhiteSpace(rows[i])) - { - elves.Add(rows.Skip(elfSet).Take(i - elfSet).ToArray()); - elfSet = i + 1; - } - if (i == rows.Length - 1) - { - elves.Add(rows.Skip(elfSet).ToArray()); - } - } - var highestCalories = new List(); - foreach (var elf in elves) + int total = 0; + foreach (var group in rows.Chunk(3)) { - highestCalories.Add(elf.Select(x => int.Parse(x)).Sum()); + var elf1 = group.ToArray()[0].ToCharArray(); + var elf2 = group.ToArray()[1].ToCharArray(); + var elf3 = group.ToArray()[2].ToCharArray(); + var inter = elf1.Intersect(elf2).Intersect(elf3).First(); + Log("Intersection char is " + inter); + total += GetPriority(inter); } - _response.Answer = highestCalories.OrderByDescending(x => x).Take(3).Sum(); + + _response.Answer = total; return _response; } diff --git a/AdventOfCode/_2022/Day4.cs b/AdventOfCode/_2022/Day4.cs new file mode 100644 index 0000000..add6b7c --- /dev/null +++ b/AdventOfCode/_2022/Day4.cs @@ -0,0 +1,40 @@ +using AdventOfCode._2022.Models; +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 4)] + public class Day4 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var input = GetSplitInput(); + var overlappingPairs = 0; + foreach (var cleaningTasks in input) + { + var cleaningTask = new CleaningSectionTask(cleaningTasks); + if (cleaningTask.IsOneSectionFullyOverlapped()) overlappingPairs++; + } + _response.Answer = overlappingPairs; + return _response; + } + + protected override AOCResponse ExecutePartB() + { + var input = GetSplitInput(); + var overlappingPairs = 0; + foreach (var cleaningTasks in input) + { + var cleaningTask = new CleaningSectionTask(cleaningTasks); + if (cleaningTask.IsAnySectionOverlapped()) overlappingPairs++; + } + _response.Answer = overlappingPairs; + return _response; + } + } +} diff --git a/AdventOfCode/_2022/Day5.cs b/AdventOfCode/_2022/Day5.cs new file mode 100644 index 0000000..681ce04 --- /dev/null +++ b/AdventOfCode/_2022/Day5.cs @@ -0,0 +1,30 @@ +using AdventOfCode._2022.Models; +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 5)] + public class Day5 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var input = GetSplitInput(noTrim: true); + var crates = input.Take(Array.FindIndex(input, x => string.IsNullOrEmpty(x))); + var moves = input.Skip(crates.Count() + 1); + var crateBoard = new CargoCrateBoard(_request.Version, crates.ToArray(), moves.ToArray()); + _response.Answer = string.Join(" ", crateBoard.GetResults()); + return _response; + } + + protected override AOCResponse ExecutePartB() + { + //Version specific is handled in CargoCrateBoard object + return ExecutePartA(); + } + } +} diff --git a/AdventOfCode/_2022/Day6.cs b/AdventOfCode/_2022/Day6.cs new file mode 100644 index 0000000..a0b113b --- /dev/null +++ b/AdventOfCode/_2022/Day6.cs @@ -0,0 +1,57 @@ +using AdventOfCode._2022.Models; +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 6)] + public class Day6 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var input = GetSplitInput().First(); + + var datastream = input.ToCharArray(); + for (int i = 4; i < datastream.Length; i++) + { + var prevChars = datastream.Skip(i - 4).Take(4); + if (!HasDuplicates(prevChars)) + { + _response.Answer = i; + break; + } + } + + return _response; + } + + protected override AOCResponse ExecutePartB() + { + var input = GetSplitInput().First(); + + var datastream = input.ToCharArray(); + for (int i = 14; i < datastream.Length; i++) + { + var prevChars = datastream.Skip(i - 14).Take(14); + if (!HasDuplicates(prevChars)) + { + _response.Answer = i; + break; + } + } + + return _response; + } + + private bool HasDuplicates(IEnumerable chars) + { + if (chars.Count() == chars.Distinct().Count()) + return false; + return true; + } + } +} diff --git a/AdventOfCode/_2022/Models/CargoCrateBoard.cs b/AdventOfCode/_2022/Models/CargoCrateBoard.cs new file mode 100644 index 0000000..562a08f --- /dev/null +++ b/AdventOfCode/_2022/Models/CargoCrateBoard.cs @@ -0,0 +1,114 @@ +using AdventOfCode.Models; +using AOC2021.Helper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace AdventOfCode._2022.Models +{ + public class CargoCrateBoard + { + private readonly CrateBoard _board; + public CargoCrateBoard(AOCVersion version, string[] crates, string[] craneMoves) + { + _board = new CrateBoard(crates); + ProcessMoves(version, craneMoves); + } + + public IEnumerable GetResults() + { + return _board.GetResults(); + } + + private void ProcessMoves(AOCVersion version, string[] moves) + { + foreach (var move in moves) + { + string numbersOnly = Regex.Replace(move, "[^0-9.]", " "); + var pendingMoves = Regex.Replace(numbersOnly, @"\s+", " ").Trim().Split(" "); + _board.Move(version, pendingMoves[0].ToInt(), pendingMoves[1].ToInt(), pendingMoves[2].ToInt()); + } + } + } + + class CrateBoard + { + private List> _crates; + public CrateBoard(string[] crates) + { + _crates = new List>(); + var boardSize = Regex.Replace(crates.Last(), @"\s+", " ").Trim().Split(" ").Count(); + for (int i = 0; i < boardSize; i++) + { + _crates.Add(new Stack()); + } + + //Fix input to handle spaces by replacing with empty crates + for (int i = (crates.Length - 2); i >=0; i--) + { + var crateRow = crates[i]; + crateRow = crateRow.Replace("] ", "] [-]"); + crateRow = crateRow.Replace(" [", "[-] ["); + crateRow = crateRow.Replace(" ", " [-] "); + + var cratesPerRow = crateRow.Split(" "); + if (cratesPerRow.Length != boardSize) throw new ArgumentException("Crates don't match board size"); + + for (int x = 0; x < cratesPerRow.Length; x++) + { + if (!cratesPerRow[x].Equals("[-]")) + _crates[x].Push(new Crate(cratesPerRow[x])); + } + + } + } + + public void Move(AOCVersion version, int amount, int sourceStackId, int destinationStackId) + { + var sourceStack = _crates[(sourceStackId - 1)]; + var destStack = _crates[(destinationStackId - 1)]; + + if (version == AOCVersion.A) + { + for (int i = 0; i < amount; i++) + { + destStack.Push(sourceStack.Pop()); + } + } + else + { + var temp = new Stack(); + for (int i = 0; i < amount; i++) + { + temp.Push(sourceStack.Pop()); + } + for (int i = 0; i < amount; i++) + { + destStack.Push(temp.Pop()); + } + } + + } + + public IEnumerable GetResults() + { + var list = new List(); + for (int i = 0; i < _crates.Count(); i++) + { + list.Add(_crates[i].Peek().Name); + } + return list; + } + } + + class Crate + { + public string Name { get; set; } + public Crate(string crateName) + { + this.Name = crateName; + } + } +} diff --git a/AdventOfCode/_2022/Models/CleaningSection.cs b/AdventOfCode/_2022/Models/CleaningSection.cs new file mode 100644 index 0000000..ded7331 --- /dev/null +++ b/AdventOfCode/_2022/Models/CleaningSection.cs @@ -0,0 +1,51 @@ +using AOC2021.Helper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode._2022.Models +{ + public class CleaningSection + { + public int Starting { get; set; } + public int Ending { get; set; } + public CleaningSection(string section) + { + var split = section.Split("-"); + Starting = split[0].ToInt(); + Ending = split[1].ToInt(); + } + } + + public class CleaningSectionTask + { + private readonly CleaningSection firstSection; + private readonly CleaningSection secondSection; + public CleaningSectionTask(string taskList) + { + var cleaningSections = taskList.Split(","); + firstSection = new CleaningSection(cleaningSections[0]); + secondSection = new CleaningSection(cleaningSections[1]); + } + + public bool IsOneSectionFullyOverlapped() + { + if (firstSection.Starting >= secondSection.Starting && firstSection.Ending <= secondSection.Ending) + return true; + if (secondSection.Starting >= firstSection.Starting && secondSection.Ending <= firstSection.Ending) + return true; + return false; + } + + public bool IsAnySectionOverlapped() + { + if (firstSection.Starting >= secondSection.Starting && firstSection.Starting <= secondSection.Ending) return true; + if (firstSection.Ending >= secondSection.Starting && firstSection.Ending <= secondSection.Ending) return true; + + if (secondSection.Starting >= firstSection.Starting && secondSection.Starting <= firstSection.Ending) return true; + if (secondSection.Ending >= firstSection.Starting && secondSection.Ending <= firstSection.Ending) return true; + return false; + } + } +}