Files
advent-of-code/AdventOfCode/AOC.Tests/Y2023/Day01.cs
T
2024-11-28 22:56:28 +00:00

157 lines
4.9 KiB
C#

using System.Diagnostics;
using System.Reflection;
using System.Text.RegularExpressions;
namespace AOC.Tests.Y2023
{
[TestFixture, Parallelizable(ParallelScope.All)]
public class Day01
{
protected string GetThisClassName() { return this.GetType().Name; }
private string[] realData;
[SetUp]
public void Setup()
{
realData = File.ReadAllLines(Path.Combine(TestContext.CurrentContext.TestDirectory, "Y2023", "Data", $"{GetThisClassName()}.dat"));
}
[TestCase(@"1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet", 142)]
[TestCase(null, 53080)] // The actual answer
public void Part1(string? input, int? expected)
{
string[] lines = input != null ? input.Split("\n") : realData;
int result = 0;
foreach (string line in lines)
{
// Get all characters that are digits
string digits = new(line.Where(char.IsDigit).ToArray());
if (digits.Length == 1)
{
digits += digits;
}
else if (digits.Length > 2)
{
digits = $"{digits[0]}{digits[digits.Length - 1]}";
}
result += int.Parse(digits);
}
if (expected != null)
{
Assert.That(result, Is.EqualTo(expected.Value));
}
Console.WriteLine($"Part 1: {result}");
}
[TestCase(@"two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen", 281)]
[TestCase("three2six8two5", 35)]
[TestCase("eightjzqzhrllg1oneightfck", 88)]
[TestCase(null, 53268)] // The actual answer
public void Part2(string? input, int? expected)
{
string[] lines = input != null ? input.Split("\n") : realData;
int result = 0;
foreach (string line in lines)
{
result += GetNumber(line);
}
if (expected != null)
{
Assert.That(result, Is.EqualTo(expected.Value));
}
Console.WriteLine($"Part 2: {result}");
}
private record FoundMatch
{
public string Number { get; set; }
public List<int> Indexes { get; set; }
};
private int GetNumber(string input)
{
// Find every instance of a match for these strings, along with the index of their first character
List<string> stringsToMatch = new()
{
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "1", "2", "3", "4", "5", "6", "7", "8", "9"
};
List<FoundMatch> foundMatches = new();
foreach (string number in stringsToMatch)
{
if (!input.Contains(number))
{
continue;
}
FoundMatch foundMatch = new()
{
Number = number,
Indexes = new(),
};
// Find each instance of the string within the string, and record the index of the first character for each
int index = input.IndexOf(number, StringComparison.Ordinal);
while (index != -1)
{
foundMatch.Indexes.Add(index);
index = input.IndexOf(number, index + 1, StringComparison.Ordinal);
}
foundMatches.Add(foundMatch);
}
// Get the first occuring number in foundMatches, and the last occurring
FoundMatch firstMatch = foundMatches.OrderBy(x => x.Indexes[0]).First();
FoundMatch lastMatch = foundMatches.OrderBy(x => x.Indexes[^1]).Last();
Dictionary<string, string> numbersToConvert = new()
{
{"one", "1"},
{"two", "2"},
{"three", "3"},
{"four", "4"},
{"five", "5"},
{"six", "6"},
{"seven", "7"},
{"eight", "8"},
{"nine", "9"},
};
// Get the firstDigit and lastDigit as ints, converting any words using the numbersToConvert dictionary
string firstDigit = firstMatch.Number;
if (numbersToConvert.ContainsKey(firstMatch.Number))
{
firstDigit = numbersToConvert[firstMatch.Number];
}
string lastDigit = lastMatch.Number;
if (numbersToConvert.ContainsKey(lastMatch.Number))
{
lastDigit = numbersToConvert[lastMatch.Number];
}
int finalNumber = int.Parse($"{firstDigit}{lastDigit}");
Console.WriteLine(finalNumber);
return finalNumber;
}
}
}