feat: solved day 8 part 1 and part 2
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
namespace ResonantCollinearity.Tests;
|
||||||
|
|
||||||
|
public class LineTests
|
||||||
|
{
|
||||||
|
private readonly string[] _exampleInput = [
|
||||||
|
"............",
|
||||||
|
"........0...",
|
||||||
|
".....0......",
|
||||||
|
".......0....",
|
||||||
|
"....0.......",
|
||||||
|
"......A.....",
|
||||||
|
"............",
|
||||||
|
"............",
|
||||||
|
"........A...",
|
||||||
|
".........A..",
|
||||||
|
"............",
|
||||||
|
"............",
|
||||||
|
];
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Slope_WhenCalled_ItShouldReturnExpectedValue()
|
||||||
|
{
|
||||||
|
var line = new Line(new(3, 4), new(5, 5), _exampleInput);
|
||||||
|
|
||||||
|
var result = line.GetAntinodes();
|
||||||
|
|
||||||
|
await Assert.That(result).IsEquivalentTo(new List<Point>()
|
||||||
|
{
|
||||||
|
new(1, 3),
|
||||||
|
new(7, 6),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
namespace ResonantCollinearity.Tests;
|
||||||
|
|
||||||
|
public class PuzzleParserTests
|
||||||
|
{
|
||||||
|
private readonly PuzzleParser _parser = new();
|
||||||
|
private readonly string[] _exampleInput = [
|
||||||
|
"............",
|
||||||
|
"........0...",
|
||||||
|
".....0......",
|
||||||
|
".......0....",
|
||||||
|
"....0.......",
|
||||||
|
"......A.....",
|
||||||
|
"............",
|
||||||
|
"............",
|
||||||
|
"........A...",
|
||||||
|
".........A..",
|
||||||
|
"............",
|
||||||
|
"............",
|
||||||
|
];
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Parse_WhenGivenExampleInput_ItShouldReturnExpectedListOfFrequencies()
|
||||||
|
{
|
||||||
|
var antenna = new List<Antenna>()
|
||||||
|
{
|
||||||
|
new(1, 8, '0'),
|
||||||
|
new(2, 5, '0'),
|
||||||
|
new(3, 7, '0'),
|
||||||
|
new(4, 4, '0'),
|
||||||
|
new(5, 6, 'A'),
|
||||||
|
new(8, 8, 'A'),
|
||||||
|
new(9, 9, 'A'),
|
||||||
|
};
|
||||||
|
|
||||||
|
var expectedGroupings = antenna.GroupBy(c => c.Frequency).ToList();
|
||||||
|
|
||||||
|
var result = _parser.Parse(_exampleInput);
|
||||||
|
|
||||||
|
await Assert.That(result).IsEquivalentTo(expectedGroupings);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SolutionPartOne_WhenGivenExampleInput_ItShouldReturnExpectedAntinodes()
|
||||||
|
{
|
||||||
|
var expectedAntinodes = new List<Point>()
|
||||||
|
{
|
||||||
|
new(0, 11),
|
||||||
|
new(3, 2),
|
||||||
|
new(5, 6),
|
||||||
|
new(7, 0),
|
||||||
|
new(1, 3),
|
||||||
|
new(4, 9),
|
||||||
|
new(0, 6),
|
||||||
|
new(6, 3),
|
||||||
|
new(2, 10),
|
||||||
|
new(5, 1),
|
||||||
|
new(2, 4),
|
||||||
|
new(11, 10),
|
||||||
|
new(7, 7),
|
||||||
|
new(10, 10),
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _parser.Parse(_exampleInput).GetAntinodes(_exampleInput);
|
||||||
|
|
||||||
|
await Assert.That(result).IsEquivalentTo(expectedAntinodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SolutionPartTwo_WhenGivenExampleInput_ItShouldReturnExpectedAntinodes()
|
||||||
|
{
|
||||||
|
// var expectedAntinodes = new List<Point>()
|
||||||
|
// {
|
||||||
|
// new(0, 11),
|
||||||
|
// new(3, 2),
|
||||||
|
// new(5, 6),
|
||||||
|
// new(7, 0),
|
||||||
|
// new(1, 3),
|
||||||
|
// new(4, 9),
|
||||||
|
// new(0, 6),
|
||||||
|
// new(6, 3),
|
||||||
|
// new(2, 10),
|
||||||
|
// new(5, 1),
|
||||||
|
// new(2, 4),
|
||||||
|
// new(11, 10),
|
||||||
|
// new(7, 7),
|
||||||
|
// new(10, 10),
|
||||||
|
// };
|
||||||
|
|
||||||
|
var result = _parser.Parse(_exampleInput).GetAntinodes(_exampleInput, isPart2: true);
|
||||||
|
|
||||||
|
await Assert.That(result.Count).IsEquivalentTo(34);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,130 @@ var input = await File.ReadAllLinesAsync(args[0]);
|
|||||||
var stopwatch = new Stopwatch();
|
var stopwatch = new Stopwatch();
|
||||||
stopwatch.Start();
|
stopwatch.Start();
|
||||||
|
|
||||||
// TODO: Implement solution
|
var result = new PuzzleParser().Parse(input).GetAntinodes(input, isPart2).Count;
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Console.WriteLine($". ({stopwatch.ElapsedMilliseconds}ms)");
|
Console.WriteLine($"The number of antinode locations is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||||
|
|
||||||
|
// TODO: Make this better...it is ugly
|
||||||
|
static class AntennaGroupingsExtensions
|
||||||
|
{
|
||||||
|
public static List<Point> GetAntinodes(this List<IGrouping<char,Antenna>> groupings, string[] input, bool isPart2 = false)
|
||||||
|
{
|
||||||
|
var antinodeLocations = new HashSet<Point>();
|
||||||
|
|
||||||
|
foreach (var group in groupings)
|
||||||
|
{
|
||||||
|
var antennas = group.ToList();
|
||||||
|
|
||||||
|
foreach (var a1 in antennas)
|
||||||
|
{
|
||||||
|
foreach (var a2 in antennas)
|
||||||
|
{
|
||||||
|
if (a1 == a2)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pointOne = a1.ToPoint();
|
||||||
|
var pointTwo = a2.ToPoint();
|
||||||
|
var line = new Line(pointOne, pointTwo, input);
|
||||||
|
var antinodes = isPart2
|
||||||
|
? line.GetPart2Antinodes()
|
||||||
|
: line.GetAntinodes();
|
||||||
|
antinodes.ForEach(a => antinodeLocations.Add(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return antinodeLocations.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PuzzleParser
|
||||||
|
{
|
||||||
|
public List<IGrouping<char,Antenna>> Parse(string[] input)
|
||||||
|
{
|
||||||
|
var antennas = new List<Antenna>();
|
||||||
|
|
||||||
|
foreach (var (line, rowIndex) in input.Select((line, index) => (line, index)))
|
||||||
|
{
|
||||||
|
foreach (var (character, colIndex) in line.Select((character, index) => (character, index)))
|
||||||
|
{
|
||||||
|
if (char.IsDigit(character) || char.IsLetter(character))
|
||||||
|
{
|
||||||
|
antennas.Add(new(rowIndex, colIndex, character));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var antennaGroupedByFrequency = antennas.GroupBy(a => a.Frequency).ToList();
|
||||||
|
|
||||||
|
return antennaGroupedByFrequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Antenna(int RowIndex, int ColIndex, char Frequency)
|
||||||
|
{
|
||||||
|
public Point ToPoint()
|
||||||
|
{
|
||||||
|
return new(RowIndex, ColIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Point(int RowIndex, int ColIndex)
|
||||||
|
{
|
||||||
|
public bool IsOnMap(string[] map)
|
||||||
|
{
|
||||||
|
return RowIndex > -1 &&
|
||||||
|
RowIndex < map.Length &&
|
||||||
|
ColIndex > -1 &&
|
||||||
|
ColIndex < map[0].Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Slope(int Rise, int Run);
|
||||||
|
|
||||||
|
class Line(Point start, Point end, string[] Map)
|
||||||
|
{
|
||||||
|
private readonly Slope _slope = new(end.RowIndex - start.RowIndex, end.ColIndex - start.ColIndex);
|
||||||
|
|
||||||
|
public List<Point> GetAntinodes()
|
||||||
|
{
|
||||||
|
var doubledRun = _slope.Run * 2;
|
||||||
|
var doubledRise = _slope.Rise * 2;
|
||||||
|
|
||||||
|
return new List<Point>()
|
||||||
|
{
|
||||||
|
new(end.RowIndex - doubledRise, end.ColIndex - doubledRun),
|
||||||
|
new(start.RowIndex + doubledRise, start.ColIndex + doubledRun),
|
||||||
|
}.Where(p => p.IsOnMap(Map)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Point> GetPart2Antinodes()
|
||||||
|
{
|
||||||
|
var antinodes = new List<Point>();
|
||||||
|
|
||||||
|
// we are finding antinodes from
|
||||||
|
// start antenna back
|
||||||
|
var currentPoint = start;
|
||||||
|
|
||||||
|
while (currentPoint.IsOnMap(Map))
|
||||||
|
{
|
||||||
|
antinodes.Add(currentPoint);
|
||||||
|
currentPoint = new(currentPoint.RowIndex - _slope.Rise, currentPoint.ColIndex - _slope.Run);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are finding antinodes from
|
||||||
|
// end antenna out
|
||||||
|
currentPoint = end;
|
||||||
|
|
||||||
|
while (currentPoint.IsOnMap(Map))
|
||||||
|
{
|
||||||
|
antinodes.Add(currentPoint);
|
||||||
|
currentPoint = new(currentPoint.RowIndex + _slope.Rise, currentPoint.ColIndex + _slope.Run);
|
||||||
|
}
|
||||||
|
|
||||||
|
return antinodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ dotnet build
|
|||||||
## Challenges
|
## Challenges
|
||||||
|
|
||||||
| Day | Problem | Solution | Notes |
|
| Day | Problem | Solution | Notes |
|
||||||
|-----|----------------------------|-------------------------------------|----------------------------------------------------------------------------------------------|
|
|-----|----------------------------|----------------------------------------|--------------------------------------------------------------------------------------------------------|
|
||||||
| 01 | [Problem](./01/PROBLEM.md) | [Solution](./01/HistorianHysteria/) | A great way to start! |
|
| 01 | [Problem](./01/PROBLEM.md) | [Solution](./01/HistorianHysteria/) | A great way to start! |
|
||||||
| 02 | [Problem](./02/PROBLEM.md) | [Solution](./02/RedNosedReports/) | Damn their was an edge case that really bit me...direction change after first pair of levels |
|
| 02 | [Problem](./02/PROBLEM.md) | [Solution](./02/RedNosedReports/) | Damn their was an edge case that really bit me...direction change after first pair of levels |
|
||||||
| 03 | [Problem](./03/PROBLEM.md) | [Solution](./03/MullItOver/) | Thank goodness this wasn't a repeat of day 2. |
|
| 03 | [Problem](./03/PROBLEM.md) | [Solution](./03/MullItOver/) | Thank goodness this wasn't a repeat of day 2. |
|
||||||
@@ -51,3 +51,4 @@ dotnet build
|
|||||||
| 05 | [Problem](./05/PROBLEM.md) | [Solution](./05/PrintQueue/) | A graph to the rescue! |
|
| 05 | [Problem](./05/PROBLEM.md) | [Solution](./05/PrintQueue/) | A graph to the rescue! |
|
||||||
| 06 | [Problem](./06/PROBLEM.md) | [Solution](./06/GuardGallivant/) | I kind of brute forced part two... |
|
| 06 | [Problem](./06/PROBLEM.md) | [Solution](./06/GuardGallivant/) | I kind of brute forced part two... |
|
||||||
| 07 | [Problem](./07/PROBLEM.md) | [Solution](./07/BridgeRepair/) | Not perfect or pretty, but good enough |
|
| 07 | [Problem](./07/PROBLEM.md) | [Solution](./07/BridgeRepair/) | Not perfect or pretty, but good enough |
|
||||||
|
| 08 | [Problem](./08/PROBLEM.md) | [Solution](./08/ResonantCollinearity/) | Without some help from chat I don't know where I'd be...to be fair the description kind of mislead me. |
|
||||||
|
|||||||
Reference in New Issue
Block a user