From 24c171c790728e5726e2d0a9f120361840b2e903 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:39:14 -0600 Subject: [PATCH] feat: solve part 1 --- 14/ParabolicReflectorDish.Tests/DishTests.cs | 96 ++++++++++++++++ 14/ParabolicReflectorDish.Tests/UnitTest1.cs | 10 -- 14/ParabolicReflectorDish/Program.cs | 109 ++++++++++++++++++- 3 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 14/ParabolicReflectorDish.Tests/DishTests.cs delete mode 100644 14/ParabolicReflectorDish.Tests/UnitTest1.cs diff --git a/14/ParabolicReflectorDish.Tests/DishTests.cs b/14/ParabolicReflectorDish.Tests/DishTests.cs new file mode 100644 index 0000000..db823bc --- /dev/null +++ b/14/ParabolicReflectorDish.Tests/DishTests.cs @@ -0,0 +1,96 @@ +namespace ParabolicReflectorDish.Tests; + +public class DishTests +{ + [Theory] + [MemberData(nameof(TestData.ParseTestData), MemberType = typeof(TestData))] + public void Parse_GivenInput_ItShouldReturnDishInstance(string[] input, Dish expected) + { + var result = Dish.Parse(input); + result.Should().BeEquivalentTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.CalculateTotalLoadTestData), MemberType = typeof(TestData))] + public void CalculateTotalLoad_WhenCalled_ItShouldReturnExpectedLoad(Dish dish, long expected) + { + var result = dish.CalculateTotalLoad(); + result.Should().Be(expected); + } + + public static class TestData + { + private static readonly Dish TestDish = new( + [ + ['O', 'O', 'O', 'O', '.', '#', '.', 'O', '.', '.'], + ['O', 'O', '.', '.', '#', '.', '.', '.', '.', '#'], + ['O', 'O', '.', '.', 'O', '#', '#', '.', '.', 'O'], + ['O', '.', '.', '#', '.', 'O', 'O', '.', '.', '.'], + ['.', '.', '.', '.', '.', '.', '.', '.', '#', '.'], + ['.', '.', '#', '.', '.', '.', '.', '#', '.', '#'], + ['.', '.', 'O', '.', '.', '#', '.', 'O', '.', 'O'], + ['.', '.', 'O', '.', '.', '.', '.', '.', '.', '.'], + ['#', '.', '.', '.', '.', '#', '#', '#', '.', '.'], + ['#', '.', '.', '.', '.', '#', '.', '.', '.', '.'], + ] + ); + + public static IEnumerable CalculateTotalLoadTestData => + new List + { + new object[] + { + new Dish( + [ + ['O', 'O', 'O', 'O', '.', '#', '.', 'O', '.', '.'], + ['O', 'O', '.', '.', '#', '.', '.', '.', '.', '#'], + ['O', 'O', '.', '.', 'O', '#', '#', '.', '.', 'O'], + ['O', '.', '.', '#', '.', 'O', 'O', '.', '.', '.'], + ['.', '.', '.', '.', '.', '.', '.', '.', '#', '.'], + ['.', '.', '#', '.', '.', '.', '.', '#', '.', '#'], + ['.', '.', 'O', '.', '.', '#', '.', 'O', '.', 'O'], + ['.', '.', 'O', '.', '.', '.', '.', '.', '.', '.'], + ['#', '.', '.', '.', '.', '#', '#', '#', '.', '.'], + ['#', '.', '.', '.', '.', '#', '.', '.', '.', '.'], + ] + ), + 136 + } + }; + + public static IEnumerable ParseTestData => + new List + { + new object[] + { + new string[] + { + "O....#....", + "O.OO#....#", + ".....##...", + "OO.#O....O", + ".O.....O#.", + "O.#..O.#.#", + "..O..#O..O", + ".......O..", + "#....###..", + "#OO..#....", + }, + new Dish( + [ + ['O', '.', '.', '.', '.', '#', '.', '.', '.', '.'], + ['O', '.', 'O', 'O', '#', '.', '.', '.', '.', '#'], + ['.', '.', '.', '.', '.', '#', '#', '.', '.', '.'], + ['O', 'O', '.', '#', 'O', '.', '.', '.', '.', 'O'], + ['.', 'O', '.', '.', '.', '.', '.', 'O', '#', '.'], + ['O', '.', '#', '.', '.', 'O', '.', '#', '.', '#'], + ['.', '.', 'O', '.', '.', '#', 'O', '.', '.', 'O'], + ['.', '.', '.', '.', '.', '.', '.', 'O', '.', '.'], + ['#', '.', '.', '.', '.', '#', '#', '#', '.', '.'], + ['#', 'O', 'O', '.', '.', '#', '.', '.', '.', '.'], + ] + ), + } + }; + } +} \ No newline at end of file diff --git a/14/ParabolicReflectorDish.Tests/UnitTest1.cs b/14/ParabolicReflectorDish.Tests/UnitTest1.cs deleted file mode 100644 index 0c4d24c..0000000 --- a/14/ParabolicReflectorDish.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ParabolicReflectorDish.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file diff --git a/14/ParabolicReflectorDish/Program.cs b/14/ParabolicReflectorDish/Program.cs index 3751555..25e4e47 100644 --- a/14/ParabolicReflectorDish/Program.cs +++ b/14/ParabolicReflectorDish/Program.cs @@ -1,2 +1,107 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +using System.Diagnostics; + +namespace ParabolicReflectorDish; + +public class Program +{ + public static async Task Main(string[] args) + { + if (args.Length is 0) + { + Console.WriteLine("Please provide a path to the input file."); + return -1; + } + + if (File.Exists(args[0]) is false) + { + Console.WriteLine("The provided file does not exist."); + return -2; + } + + var input = await File.ReadAllLinesAsync(args[0]); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var result = Dish + .Parse(input) + .CalculateTotalLoad(); + + stopwatch.Stop(); + + Console.WriteLine($"The total load is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + + return (int)result; + } +} + +public class Dish( + List> rows +) +{ + private const char RoundRockSymbol = 'O'; + private const char SquareRockSymbol = '#'; + private const char EmptySpaceSymbol = '.'; + + public List> Rows { get; init; } = rows; + + private List> TiltDishToNorth(List> rows) + { + var modifiedRows = rows.ToList(); + var numOfColumns = modifiedRows[0].Count; + var numOfRows = modifiedRows.Count; + + for (var currentColumnIndex = 0; currentColumnIndex < numOfColumns; currentColumnIndex++) + { + for (var currentRowIndex = 0; currentRowIndex < numOfRows; currentRowIndex++) + { + var current = modifiedRows[currentRowIndex][currentColumnIndex]; + + if (current is EmptySpaceSymbol) + { + for (var i = currentRowIndex + 1; i < numOfRows; i++) + { + var next = modifiedRows[i][currentColumnIndex]; + + if (next is SquareRockSymbol) + { + break; + } + + if (next is RoundRockSymbol) + { + modifiedRows[currentRowIndex][currentColumnIndex] = RoundRockSymbol; + modifiedRows[i][currentColumnIndex] = EmptySpaceSymbol; + break; + } + } + } + } + } + + return modifiedRows; + } + + public long CalculateTotalLoad() + { + var rows = TiltDishToNorth(Rows); + rows.Reverse(); + + return rows + .Select((r, index) => + { + var numOfRoundRocks = r.Where(c => c is RoundRockSymbol).Count(); + return (index + 1) * numOfRoundRocks; + }) + .Sum(); + } + + public static Dish Parse(string[] input) + { + var inputList = input + .Select(s => s.ToList()) + .ToList(); + + return new Dish(inputList); + } +} \ No newline at end of file