feat: solve part 1

This commit is contained in:
Stevan Freeborn
2023-12-18 22:51:12 -06:00
parent e37fbc977c
commit 92e3e32d0b
4 changed files with 384 additions and 12 deletions
+160
View File
@@ -0,0 +1,160 @@
namespace PointOfIncidence.Tests;
public class PatternTests
{
[Theory]
[MemberData(nameof(TestData.ParseTestData), MemberType = typeof(TestData))]
public void Parse_GivenAPattern_ItShouldReturnPatternInstance(string[] input, Pattern expected)
{
var result = Pattern.Parse(input);
result.Should().BeEquivalentTo(expected);
}
[Theory]
[MemberData(nameof(TestData.FindPointOfReflectionTestData), MemberType = typeof(TestData))]
public void FindPointOfReflection_GivenAPattern_ItShouldReturnPointOfReflection(string[] input, PointOfReflection expected)
{
var pattern = Pattern.Parse(input);
var result = pattern.FindPointOfReflection();
result.Should().BeEquivalentTo(expected);
}
[Fact]
public void SummarizePatternNotes_GivenExampleInput_ItShouldReturnExpectedValue()
{
var input = File
.ReadAllText("EXAMPLE.txt")
.ReplaceLineEndings();
var patterns = input
.Split(Environment.NewLine + Environment.NewLine)
.Select(p => p.Split(Environment.NewLine));
var result = patterns
.Select(Pattern.Parse)
.Sum(p => p.SummarizePatternNotes());
result.Should().Be(405);
}
[Fact]
public void SummarizePatternNotes_GivenInput_ItShouldReturnExpectedValue()
{
var input = File
.ReadAllText("INPUT.txt")
.ReplaceLineEndings();
var patterns = input
.Split(Environment.NewLine + Environment.NewLine)
.Select(p => p.Split(Environment.NewLine));
var result = patterns
.Select(Pattern.Parse)
.Select(p => p.SummarizePatternNotes())
.Sum();
result.Should().Be(33728);
}
public static class TestData
{
public static IEnumerable<object[]> ParseTestData =>
new List<object[]>
{
new object[]
{
new string[]
{
"#.##..##.",
"..#.##.#.",
},
new Pattern(
[
['#', '.', '#', '#', '.', '.', '#', '#', '.'],
['.', '.', '#', '.', '#', '#', '.', '#', '.'],
],
[
['#', '.'],
['.', '.'],
['#', '#'],
['#', '.'],
['.', '#'],
['.', '#'],
['#', '.'],
['#', '#'],
['.', '.'],
]
),
}
};
public static IEnumerable<object[]> FindPointOfReflectionTestData =>
new List<object[]>
{
new object[]
{
new string[]
{
"#...##..#",
"#....#..#",
"..##..###",
"#####.##.",
"#####.##.",
"..##..###",
"#....#..#",
},
new PointOfReflection
{
Type = ReflectionType.Horizontal,
StartIndex = 3,
EndIndex = 4,
},
},
new object[]
{
new string[]
{
"#.##..##.",
"..#.##.#.",
"##......#",
"##......#",
"..#.##.#.",
"..##..##.",
"#.#.##.#.",
},
new PointOfReflection
{
Type = ReflectionType.Vertical,
StartIndex = 4,
EndIndex = 5,
}
},
new object[]
{
new string[]
{
"...##..##.#.#",
".##.#####.###",
"##.#....####.",
"#.#....#.#..#",
".#..#.#...#.#",
".#..#.#...#.#",
"#.#....#.#..#",
"##.#....####.",
".########.###",
"...##..##.#.#",
"#.#.###.....#",
"#.#.###.....#",
"...##..##.#.#",
},
new PointOfReflection
{
Type = ReflectionType.Horizontal,
StartIndex = 10,
EndIndex = 11,
},
},
};
}
}
@@ -27,4 +27,16 @@
<ProjectReference Include="..\PointOfIncidence\PointOfIncidence.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="..\INPUT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include=".\EXAMPLE.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
-10
View File
@@ -1,10 +0,0 @@
namespace PointOfIncidence.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
+212 -2
View File
@@ -1,2 +1,212 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
using System.Diagnostics;
namespace PointOfIncidence;
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 input = await File.ReadAllTextAsync(args[0]);
var patterns = input
.ReplaceLineEndings()
.Split(Environment.NewLine + Environment.NewLine)
.Select(p => p.Split(Environment.NewLine));
var stopwatch = new Stopwatch();
stopwatch.Start();
var result = patterns
.Select(Pattern.Parse)
.Sum(p => p.SummarizePatternNotes());
stopwatch.Stop();
Console.WriteLine($"The total of all pattern note summaries is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
return (int)result;
}
}
public class Pattern(
List<List<char>> rows,
List<List<char>> columns
)
{
public List<List<char>> Rows { get; init; } = rows;
public List<List<char>> Columns { get; init; } = columns;
public PointOfReflection FindPointOfReflection()
{
var pointOfReflection = new PointOfReflection();
var startRowIndex = 0;
var endRowIndex = 1;
while (endRowIndex < Rows.Count)
{
var startRow = Rows[startRowIndex];
var endRow = Rows[endRowIndex];
if (startRow.SequenceEqual(endRow))
{
var isHorizontalReflection = true;
var possibleReflectionPoint = new PointOfReflection
{
StartIndex = startRowIndex,
EndIndex = endRowIndex,
Type = ReflectionType.Horizontal,
};
while (startRowIndex > 0 && endRowIndex < Rows.Count - 1)
{
var previousRow = Rows[startRowIndex - 1];
var nextRow = Rows[endRowIndex + 1];
if (previousRow.SequenceEqual(nextRow) is false)
{
isHorizontalReflection = false;
startRowIndex = possibleReflectionPoint.StartIndex;
endRowIndex = possibleReflectionPoint.EndIndex;
break;
}
startRowIndex--;
endRowIndex++;
}
if (isHorizontalReflection)
{
pointOfReflection = possibleReflectionPoint;
break;
}
}
startRowIndex++;
endRowIndex++;
}
if (pointOfReflection.Type == ReflectionType.None)
{
var startColumnIndex = 0;
var endColumnIndex = 1;
while (endColumnIndex < Columns.Count)
{
var startColumn = Columns[startColumnIndex];
var endColumn = Columns[endColumnIndex];
if (startColumn.SequenceEqual(endColumn))
{
var isVerticalReflection = true;
var possibleReflectionPoint = new PointOfReflection
{
StartIndex = startColumnIndex,
EndIndex = endColumnIndex,
Type = ReflectionType.Vertical,
};
while (startColumnIndex > 0 && endColumnIndex < Columns.Count - 1)
{
var previousColumn = Columns[startColumnIndex - 1];
var nextColumn = Columns[endColumnIndex + 1];
if (previousColumn.SequenceEqual(nextColumn) is false)
{
isVerticalReflection = false;
startColumnIndex = possibleReflectionPoint.StartIndex;
endColumnIndex = possibleReflectionPoint.EndIndex;
break;
}
startColumnIndex--;
endColumnIndex++;
}
if (isVerticalReflection)
{
pointOfReflection = possibleReflectionPoint;
break;
}
}
startColumnIndex++;
endColumnIndex++;
}
}
return pointOfReflection;
}
public long SummarizePatternNotes()
{
var pointOfReflection = FindPointOfReflection();
if (pointOfReflection.Type is ReflectionType.None)
{
return 0;
}
if (pointOfReflection.Type is ReflectionType.Vertical)
{
return pointOfReflection.StartIndex + 1;
}
return (pointOfReflection.StartIndex + 1) * 100;
}
public static Pattern Parse(string[] input)
{
var columns = new List<List<char>>();
var height = input.Length;
var width = input[0].Length;
for (var i = 0; i < width; i++)
{
var column = new List<char>();
for (var j = 0; j < height; j++)
{
column.Add(input[j][i]);
}
columns.Add(column);
}
var rows = input
.Select(
row => row
.ToCharArray()
.ToList()
)
.ToList();
return new Pattern(rows, columns);
}
}
public class PointOfReflection
{
public ReflectionType Type = ReflectionType.None;
public int StartIndex { get; set; } = -1;
public int EndIndex { get; set; } = -1;
}
public enum ReflectionType
{
Horizontal,
Vertical,
None,
}