chore: add xml comments

This commit is contained in:
Stevan Freeborn
2023-12-02 12:46:56 -06:00
parent ea65c5d830
commit f99414041c
5 changed files with 201 additions and 14 deletions
+52
View File
@@ -0,0 +1,52 @@
namespace CubeConundrum.Tests;
public class GameTests
{
[Theory, MemberData(nameof(TestData.Games), MemberType = typeof(TestData))]
public void PowerOfMinimumCubesNeeded_GivenAGame_ItShouldReturnTheSumOfTheMinimumCubesNeededForEachResult(Game game, int expected)
{
game.PowerOfMinimumCubesNeeded.Should().Be(expected);
}
public static class TestData
{
public static readonly IEnumerable<object[]> Games = new List<object[]>
{
new object[]
{
new Game
{
Id = 1,
Results =
{
new()
{
Cubes =
{
new() { Count = 3, Color = CubeColor.Blue },
new() { Count = 4, Color = CubeColor.Red }
}
},
new()
{
Cubes =
{
new() { Count = 1, Color = CubeColor.Red },
new() { Count = 2, Color = CubeColor.Green },
new() { Count = 6, Color = CubeColor.Blue }
}
},
new()
{
Cubes =
{
new() { Count = 2, Color = CubeColor.Green },
}
}
}
},
48
}
};
}
}
+7
View File
@@ -8,4 +8,11 @@ public class ProgramTests
var result = await Program.Main(["INPUT.txt"]); var result = await Program.Main(["INPUT.txt"]);
result.Should().Be(2879); result.Should().Be(2879);
} }
[Fact]
public async Task Main_GivenInputAndPart2_ItShouldReturnExpectedSum()
{
var result = await Program.Main(["INPUT.txt", "part2"]);
result.Should().Be(65122);
}
} }
@@ -1,8 +1,8 @@
namespace CubeConundrum.Tests; namespace CubeConundrum.Tests;
public class PartOnePuzzleSolverTests public class PuzzleSolverTests
{ {
private readonly PartOnePuzzleSolver _sut = new(); private readonly PuzzleSolver _sut = new();
[Theory, MemberData(nameof(TestData.Results), MemberType = typeof(TestData))] [Theory, MemberData(nameof(TestData.Results), MemberType = typeof(TestData))]
public void IsResultPossible_GivenAResult_ItShouldReturnExpectedOutcome(Result givenResult, bool expected) public void IsResultPossible_GivenAResult_ItShouldReturnExpectedOutcome(Result givenResult, bool expected)
+4 -4
View File
@@ -5,7 +5,7 @@ public class PuzzleParserTests
private readonly PuzzleParser _sut = new(); private readonly PuzzleParser _sut = new();
[Theory, MemberData(nameof(TestData.CubeStrings), MemberType = typeof(TestData))] [Theory, MemberData(nameof(TestData.CubeStrings), MemberType = typeof(TestData))]
public void ParseCube_GivenAStringThatRepresentsACube_ItShouldReturnTheEquivalentCubeModel(string input, Cube expected) public void ParseCube_GivenAStringThatRepresentsACube_ItShouldReturnTheEquivalentCubeModel(string input, CubeCollection expected)
{ {
var result = _sut.ParseCube(input); var result = _sut.ParseCube(input);
result.Should().BeEquivalentTo(expected); result.Should().BeEquivalentTo(expected);
@@ -29,9 +29,9 @@ public class PuzzleParserTests
{ {
public static readonly IEnumerable<object[]> CubeStrings = new List<object[]> public static readonly IEnumerable<object[]> CubeStrings = new List<object[]>
{ {
new object[] { "4 red", new Cube { Count = 4, Color = CubeColor.Red } }, new object[] { "4 red", new CubeCollection { Count = 4, Color = CubeColor.Red } },
new object[] { "1 green", new Cube { Count = 1, Color = CubeColor.Green } }, new object[] { "1 green", new CubeCollection { Count = 1, Color = CubeColor.Green } },
new object[] { "2 blue", new Cube { Count = 2, Color = CubeColor.Blue } } new object[] { "2 blue", new CubeCollection { Count = 2, Color = CubeColor.Blue } }
}; };
public static readonly IEnumerable<object[]> ResultStrings = new List<object[]> public static readonly IEnumerable<object[]> ResultStrings = new List<object[]>
+136 -8
View File
@@ -7,21 +7,24 @@ public class Program
if (args.Length is 0) if (args.Length is 0)
{ {
Console.WriteLine("Please provide a path to the input file."); Console.WriteLine("Please provide a path to the input file.");
return 1; return -1;
} }
if (File.Exists(args[0]) is false) if (File.Exists(args[0]) is false)
{ {
Console.WriteLine("The provided file does not exist."); Console.WriteLine("The provided file does not exist.");
return 2; return -2;
} }
var puzzleParser = new PuzzleParser(); var puzzleParser = new PuzzleParser();
var puzzleSolver = new PartOnePuzzleSolver(); var puzzleSolver = new PuzzleSolver();
var input = await File.ReadAllLinesAsync(args[0]); var input = await File.ReadAllLinesAsync(args[0]);
var games = input.Select(puzzleParser.ParseGame); var games = input.Select(puzzleParser.ParseGame);
var result = puzzleSolver.SumPossibleGameIds(games);
var result = args.Length > 1 && args[1] == "part2"
? puzzleSolver.SumGameMinimumPowers(games)
: puzzleSolver.SumPossibleGameIds(games);
Console.WriteLine($"The sum of all possible game ids is {result}."); Console.WriteLine($"The sum of all possible game ids is {result}.");
@@ -29,28 +32,78 @@ public class Program
} }
} }
public class PartOnePuzzleSolver /// <summary>
/// Puzzle solver.
/// </summary>
public class PuzzleSolver
{ {
/// <summary>
/// The maximum number of cubes that can be used in a game.
/// </summary>
private readonly int _maxCubeCount = 39; private readonly int _maxCubeCount = 39;
/// <summary>
/// The maximum number of red cubes that can be used in a game.
/// </summary>
private readonly int _maxRedCubeCount = 12; private readonly int _maxRedCubeCount = 12;
/// <summary>
/// The maximum number of green cubes that can be used in a game.
/// </summary>
private readonly int _maxGreenCubeCount = 13; private readonly int _maxGreenCubeCount = 13;
/// <summary>
/// The maximum number of blue cubes that can be used in a game.
/// </summary>
private readonly int _maxBlueCubeCount = 14; private readonly int _maxBlueCubeCount = 14;
/// <summary>
/// Determines whether a result is possible.
/// </summary>
/// <param name="result">The result to check.</param>
/// <returns>True if the result is possible, otherwise false.</returns>
public bool IsResultPossible(Result result) => result.TotalCubeCount <= _maxCubeCount public bool IsResultPossible(Result result) => result.TotalCubeCount <= _maxCubeCount
&& result.RedCubeCount <= _maxRedCubeCount && result.RedCubeCount <= _maxRedCubeCount
&& result.GreenCubeCount <= _maxGreenCubeCount && result.GreenCubeCount <= _maxGreenCubeCount
&& result.BlueCubeCount <= _maxBlueCubeCount; && result.BlueCubeCount <= _maxBlueCubeCount;
/// <summary>
/// Determines whether a game is possible.
/// </summary>
/// <param name="game">The game to check.</param>
/// <returns>True if the game is possible, otherwise false.</returns>
public bool IsGamePossible(Game game) => game.Results.All(IsResultPossible); public bool IsGamePossible(Game game) => game.Results.All(IsResultPossible);
/// <summary>
/// Sums all possible game ids.
/// </summary>
/// <param name="games">The games to sum.</param>
/// <returns>The sum of all possible game ids.</returns>
public int SumPossibleGameIds(IEnumerable<Game> games) => games public int SumPossibleGameIds(IEnumerable<Game> games) => games
.Where(IsGamePossible) .Where(IsGamePossible)
.Sum(g => g.Id); .Sum(g => g.Id);
/// <summary>
/// Sums the minimum powers of all games.
/// </summary>
/// <param name="games">The games to sum.</param>
/// <returns>The sum of the minimum powers of all games.</returns>
public int SumGameMinimumPowers(IEnumerable<Game> games) => games
.Select(g => g.PowerOfMinimumCubesNeeded)
.Sum();
} }
/// <summary>
/// Puzzle parser responsible for parsing puzzle input.
/// </summary>
public class PuzzleParser public class PuzzleParser
{ {
public Cube ParseCube(string cubeString) /// <summary>
/// Parses a cube from a string.
/// </summary>
/// <param name="cubeString">The string to parse.</param>
/// <returns>An instance of <see cref="CubeCollection"/>.</returns>
public CubeCollection ParseCube(string cubeString)
{ {
var parts = cubeString.Split(' '); var parts = cubeString.Split(' ');
var count = int.Parse(parts[0]); var count = int.Parse(parts[0]);
@@ -63,6 +116,11 @@ public class PuzzleParser
}; };
} }
/// <summary>
/// Parses a result from a string.
/// </summary>
/// <param name="resultString">The string to parse.</param>
/// <returns>An instance of <see cref="Result"/>.</returns>
public Result ParseResult(string resultString) public Result ParseResult(string resultString)
{ {
var cubes = resultString var cubes = resultString
@@ -77,6 +135,11 @@ public class PuzzleParser
}; };
} }
/// <summary>
/// Parses a game from a string.
/// </summary>
/// <param name="gameString">The string to parse.</param>
/// <returns>An instance of <see cref="Game"/>.</returns>
public Game ParseGame(string gameString) public Game ParseGame(string gameString)
{ {
var parts = gameString.Split(':'); var parts = gameString.Split(':');
@@ -95,30 +158,95 @@ public class PuzzleParser
} }
} }
/// <summary>
/// Represents a game.
/// </summary>
public class Game public class Game
{ {
/// <summary>
/// The id of the game.
/// </summary>
public int Id { get; set; } public int Id { get; set; }
/// <summary>
/// The results of the game.
/// </summary>
public List<Result> Results { get; set; } = []; public List<Result> Results { get; set; } = [];
private int MinimumRedCubesNeeded => Results.Max(r => r.RedCubeCount);
private int MinimumGreenCubesNeeded => Results.Max(r => r.GreenCubeCount);
private int MinimumBlueCubesNeeded => Results.Max(r => r.BlueCubeCount);
/// <summary>
/// The power of the minimum number of each cube type needed to play the game.
/// </summary>
public int PowerOfMinimumCubesNeeded => MinimumRedCubesNeeded * MinimumGreenCubesNeeded * MinimumBlueCubesNeeded;
} }
/// <summary>
/// Represents a result.
/// </summary>
public class Result public class Result
{ {
public List<Cube> Cubes { get; set; } = []; /// <summary>
/// The cubes in the result.
/// </summary>
public List<CubeCollection> Cubes { get; set; } = [];
/// <summary>
/// The total number of cubes in the result.
/// </summary>
public int TotalCubeCount => Cubes.Sum(c => c.Count); public int TotalCubeCount => Cubes.Sum(c => c.Count);
/// <summary>
/// The number of red cubes in the result.
/// </summary>
public int RedCubeCount => Cubes.Where(c => c.Color == CubeColor.Red).Sum(c => c.Count); public int RedCubeCount => Cubes.Where(c => c.Color == CubeColor.Red).Sum(c => c.Count);
/// <summary>
/// The number of green cubes in the result.
/// </summary>
public int GreenCubeCount => Cubes.Where(c => c.Color == CubeColor.Green).Sum(c => c.Count); public int GreenCubeCount => Cubes.Where(c => c.Color == CubeColor.Green).Sum(c => c.Count);
/// <summary>
/// The number of blue cubes in the result.
/// </summary>
public int BlueCubeCount => Cubes.Where(c => c.Color == CubeColor.Blue).Sum(c => c.Count); public int BlueCubeCount => Cubes.Where(c => c.Color == CubeColor.Blue).Sum(c => c.Count);
} }
public class Cube /// <summary>
/// Represents cubes of a given color.
/// </summary>
public class CubeCollection
{ {
/// <summary>
/// The number of cubes.
/// </summary>
public int Count { get; set; } public int Count { get; set; }
/// <summary>
/// The color of the cubes.
/// </summary>
public CubeColor Color { get; set; } public CubeColor Color { get; set; }
} }
/// <summary>
/// Represents a cube color.
/// </summary>
public enum CubeColor public enum CubeColor
{ {
/// <summary>
/// The red cube color.
/// </summary>
Red, Red,
/// <summary>
/// The green cube color.
/// </summary>
Green, Green,
/// <summary>
/// The blue cube color.
/// </summary>
Blue Blue
} }