feat: solve part 1 of puzzle 3

This commit is contained in:
Stevan Freeborn
2023-12-04 10:32:14 -06:00
parent d50b7c75ca
commit 9f2ccdf17f
6 changed files with 250 additions and 13 deletions
+105
View File
@@ -0,0 +1,105 @@
namespace Scratchcards.Tests;
public class CardTests
{
[Theory]
[MemberData(nameof(TestData.ParseCardData), MemberType = typeof(TestData))]
public void Parse_GivenInput_ItShouldReturnExpectedCard(string input, Card expected)
{
var result = Card.Parse(input);
result.Should().BeEquivalentTo(expected);
}
[Theory]
[MemberData(nameof(TestData.GetCardValueData), MemberType = typeof(TestData))]
public void GetCardValue_GivenCard_ItShouldReturnExpectedValue(Card card, int expected)
{
var result = card.GetCardValue();
result.Should().Be(expected);
}
public static class TestData
{
private static readonly Dictionary<string, Card> TestCards =
new()
{
{
"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53",
new Card(
1,
[41, 48, 83, 86, 17],
[83, 86, 6, 31, 17, 9, 48, 53]
)
},
{
"Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19",
new Card(
2,
[13, 32, 20, 16, 61],
[61, 30, 68, 82, 17, 32, 24, 19]
)
},
{
"Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1",
new Card(
3,
[1, 21, 53, 59, 44],
[69, 82, 63, 72, 16, 21, 14, 1]
)
},
{
"Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83",
new Card(
4,
[41, 92, 73, 84, 69],
[59, 84, 76, 51, 58, 5, 54, 83]
)
},
{
"Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36",
new Card(
5,
[87, 83, 26, 28, 32],
[88, 30, 70, 12, 93, 22, 82, 36]
)
},
{
"Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11",
new Card(
6,
[31, 18, 13, 56, 72],
[74, 77, 10, 23, 35, 67, 36, 11]
)
},
};
public static IEnumerable<object[]> ParseCardData =>
TestCards
.Select(kvp => new object[] { kvp.Key, kvp.Value })
.ToList();
public static IEnumerable<object[]> GetCardValueData()
{
for (var i = 0; i < TestCards.Count; i++)
{
var currentCard = TestCards.ElementAt(i);
var expectedValue = i switch
{
0 => 8,
1 => 2,
2 => 2,
3 => 1,
4 => 0,
5 => 0,
_ => throw new Exception("Unexpected card index"),
};
yield return new object[]
{
currentCard.Value,
expectedValue
};
}
}
}
}
+2 -1
View File
@@ -1 +1,2 @@
global using Xunit;
global using Xunit;
global using FluentAssertions;
@@ -0,0 +1,42 @@
namespace Scratchcards.Tests;
public class PuzzleSolverTests
{
private readonly PuzzleSolver _sut = new();
[Theory]
[MemberData(nameof(TestData.SumCardValuesData), MemberType = typeof(TestData))]
public void SumCardValues_GivenCards_ItShouldReturnExpectedValue(string[] cards, int expected)
{
var result = _sut.SumCardValues(cards);
result.Should().Be(expected);
}
public static class TestData
{
private static string[] Input => File.ReadAllLines("INPUT.txt");
public static IEnumerable<object[]> SumCardValuesData =>
new List<object[]>
{
new object[]
{
new[]
{
"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53",
"Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19",
"Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1",
"Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83",
"Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36",
"Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11",
},
13,
},
new object[]
{
Input,
23235,
},
};
}
}
@@ -27,4 +27,10 @@
<ProjectReference Include="..\Scratchcards\Scratchcards.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="..\INPUT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
-10
View File
@@ -1,10 +0,0 @@
namespace Scratchcards.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
+95 -2
View File
@@ -1,2 +1,95 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
namespace Scratchcards;
public class Program
{
public static async Task<int> 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 puzzleSolver = new PuzzleSolver();
var input = await File.ReadAllLinesAsync(args[0]);
var result = puzzleSolver.SumCardValues(input);
Console.WriteLine($"The sum of all card values is {result}.");
return result;
}
}
public class PuzzleSolver
{
public int SumCardValues(string[] cards) => cards
.Select(Card.Parse)
.Sum(c => c.GetCardValue());
}
public class Card(
int id,
List<int> winningNumbers,
List<int> numbers
)
{
public int Id { get; init; } = id;
public List<int> WinningNumbers { get; init; } = winningNumbers;
public List<int> Numbers { get; init; } = numbers;
public int GetCardValue()
{
var commonNumbers = WinningNumbers.Intersect(Numbers).ToList();
return commonNumbers.Count is 1
? 1
: (int)Math.Pow(2, commonNumbers.Count - 1);
}
public static Card Parse(string input)
{
var parts = input.Split(':');
var cardId = int.Parse(
parts[0].Split(
' ',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries
)[1]
);
var numberStrings = parts[1].Trim();
var numberParts = numberStrings
.Split('|')
.Select(s => s.Trim())
.ToArray();
var winningNumbersString = numberParts[0];
var numbersString = numberParts[1];
var winningNumbers = winningNumbersString
.Split(
' ',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries
)
.Select(s => s.Trim())
.Select(int.Parse)
.ToList();
var numbers = numbersString
.Split(
' ',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries
)
.Select(s => s.Trim())
.Select(int.Parse)
.ToList();
return new Card(cardId, winningNumbers, numbers);
}
}