feat: solve part 1 and part 2
This commit is contained in:
@@ -27,4 +27,10 @@
|
||||
<ProjectReference Include="..\CosmicExpansion\CosmicExpansion.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\INPUT.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace CosmicExpansion.Tests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
namespace CosmicExpansion.Tests;
|
||||
|
||||
public class UniverseTests
|
||||
{
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.ParseTestData), MemberType = typeof(TestData))]
|
||||
public void Parse_WhenGivenUniverseWithGalaxies_ItShouldReturnListOfGalaxies(string[] givenInput, Universe expectedUniverse)
|
||||
{
|
||||
var result = Universe.Parse(givenInput);
|
||||
result.Should().BeEquivalentTo(expectedUniverse);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.GetShortestPathsBetweenGalaxiesTestData), MemberType = typeof(TestData))]
|
||||
public void GetShortestPathsBetweenGalaxies_WhenGivenUniverseWithGalaxies_ItShouldReturnShortestPathsBetweenGalaxies(Universe givenUniverse, int expectedNumberOrPaths)
|
||||
{
|
||||
var result = givenUniverse.GetShortestPathsBetweenGalaxies();
|
||||
result.Count.Should().Be(expectedNumberOrPaths);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.SumOfShortestPathsBetweenGalaxiesTestData), MemberType = typeof(TestData))]
|
||||
public void SumOfShortestPathsBetweenGalaxies_WhenGivenUniverseWithGalaxies_ItShouldReturnSumOfShortestPathsBetweenGalaxies(Universe givenUniverse, int expectedSumOfShortestPaths)
|
||||
{
|
||||
givenUniverse.SumOfShortestPathsBetweenGalaxies.Should().Be(expectedSumOfShortestPaths);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.CalculateDistanceBetweenGalaxiesTestData), MemberType = typeof(TestData))]
|
||||
public void CalculateDistanceBetweenGalaxies_WhenGivenTwoGalaxies_ItShouldReturnDistanceBetweenGalaxies(Galaxy startGalaxy, Galaxy endGalaxy, int expectedDistance)
|
||||
{
|
||||
var result = Universe.CalculateDistanceBetweenGalaxies(startGalaxy, endGalaxy);
|
||||
result.Should().Be(expectedDistance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumOfShortestPathsBetweenGalaxies_WhenGivenInput_ItShouldReturnSumOfShortestPathsBetweenGalaxies()
|
||||
{
|
||||
var input = File.ReadAllLines("INPUT.txt");
|
||||
var universe = Universe.Parse(input);
|
||||
universe.SumOfShortestPathsBetweenGalaxies.Should().Be(10292708);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumOfShortestPathsBetweenGalaxies_WhenGivenInputAndIsPart2_ItShouldReturnSumOfShortestPathsBetweenGalaxies()
|
||||
{
|
||||
var input = File.ReadAllLines("INPUT.txt");
|
||||
var universe = Universe.Parse(input, 1_000_000);
|
||||
universe.SumOfShortestPathsBetweenGalaxies.Should().Be(790194712336);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class TestData
|
||||
{
|
||||
private static readonly Universe TestUniverse = new(
|
||||
12,
|
||||
13,
|
||||
[
|
||||
new(0, 4),
|
||||
new(1, 9),
|
||||
new(2, 0),
|
||||
new(5, 8),
|
||||
new(6, 1),
|
||||
new(7, 12),
|
||||
new(10, 9),
|
||||
new(11, 0),
|
||||
new(11, 5),
|
||||
]
|
||||
);
|
||||
|
||||
public static IEnumerable<object[]> ParseTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
new string[]
|
||||
{
|
||||
"...#......",
|
||||
".......#..",
|
||||
"#.........",
|
||||
"..........",
|
||||
"......#...",
|
||||
".#........",
|
||||
".........#",
|
||||
"..........",
|
||||
".......#..",
|
||||
"#...#.....",
|
||||
},
|
||||
TestUniverse,
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> GetShortestPathsBetweenGalaxiesTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
TestUniverse,
|
||||
36,
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> SumOfShortestPathsBetweenGalaxiesTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
TestUniverse,
|
||||
374,
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> CalculateDistanceBetweenGalaxiesTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
TestUniverse.Galaxies[4],
|
||||
TestUniverse.Galaxies[8],
|
||||
9,
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
TestUniverse.Galaxies[0],
|
||||
TestUniverse.Galaxies[6],
|
||||
15,
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
TestUniverse.Galaxies[2],
|
||||
TestUniverse.Galaxies[5],
|
||||
17,
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
TestUniverse.Galaxies[7],
|
||||
TestUniverse.Galaxies[8],
|
||||
5,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,171 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
Console.WriteLine("Hello, World!");
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace CosmicExpansion;
|
||||
|
||||
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 isPart2 = args.Length > 1 && args[1] == "part2";
|
||||
var input = await File.ReadAllLinesAsync(args[0]);
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
var universe = isPart2
|
||||
? Universe.Parse(input, 1_000_000)
|
||||
: Universe.Parse(input);
|
||||
|
||||
var result = universe.SumOfShortestPathsBetweenGalaxies;
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine($"The sum of the shortest paths between galaxies is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
}
|
||||
|
||||
public class Universe(
|
||||
int height,
|
||||
int width,
|
||||
List<Galaxy> galaxies
|
||||
)
|
||||
{
|
||||
private const char GalaxySymbol = '#';
|
||||
public int Height { get; init; } = height;
|
||||
public int Width { get; init; } = width;
|
||||
public List<Galaxy> Galaxies { get; init; } = galaxies;
|
||||
public long SumOfShortestPathsBetweenGalaxies =>
|
||||
GetShortestPathsBetweenGalaxies()
|
||||
.Values
|
||||
.Sum();
|
||||
|
||||
public Dictionary<(int galaxyOneIndex, int galaxyTwoIndex), long> GetShortestPathsBetweenGalaxies()
|
||||
{
|
||||
var shortestPaths = new Dictionary<(int galaxyOneIndex, int galaxyTwoIndex), long>();
|
||||
|
||||
for (int i = 0; i < Galaxies.Count; i++)
|
||||
{
|
||||
var galaxyOne = Galaxies[i];
|
||||
|
||||
for (int j = i + 1; j < Galaxies.Count; j++)
|
||||
{
|
||||
var galaxyTwo = Galaxies[j];
|
||||
|
||||
if (shortestPaths.ContainsKey((i, j)) || shortestPaths.ContainsKey((j, i)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var shortestPath = CalculateDistanceBetweenGalaxies(galaxyOne, galaxyTwo);
|
||||
shortestPaths.Add((i, j), shortestPath);
|
||||
}
|
||||
}
|
||||
|
||||
return shortestPaths;
|
||||
}
|
||||
|
||||
public static long CalculateDistanceBetweenGalaxies(Galaxy galaxyOne, Galaxy galaxyTwo) =>
|
||||
Math.Abs(galaxyTwo.Row - galaxyOne.Row) + Math.Abs(galaxyTwo.Column - galaxyOne.Column);
|
||||
|
||||
public static Universe Parse(string[] input, int expandFactor = 2)
|
||||
{
|
||||
var emptyRows = new List<int>();
|
||||
var emptyColumns = new List<int>();
|
||||
var galaxies = new List<Galaxy>();
|
||||
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
var currentRow = input[i];
|
||||
|
||||
if (currentRow.Contains(GalaxySymbol) is false)
|
||||
{
|
||||
emptyRows.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < input[0].Length; i++)
|
||||
{
|
||||
var galaxyInColumn = false;
|
||||
|
||||
for (int j = 0; j < input.Length; j++)
|
||||
{
|
||||
var currentPosition = input[j][i];
|
||||
|
||||
if (currentPosition == GalaxySymbol)
|
||||
{
|
||||
galaxyInColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (galaxyInColumn is false)
|
||||
{
|
||||
emptyColumns.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
var currentRow = input[i];
|
||||
|
||||
for (int j = 0; j < currentRow.Length; j++)
|
||||
{
|
||||
var currentPosition = currentRow[j];
|
||||
|
||||
if (currentPosition == GalaxySymbol)
|
||||
{
|
||||
var numOfEmptyRowsBefore = emptyRows.Where(row => row < i).Count();
|
||||
var rowOffset = numOfEmptyRowsBefore is 0
|
||||
? 0
|
||||
: (numOfEmptyRowsBefore * expandFactor) - numOfEmptyRowsBefore;
|
||||
|
||||
var numOfEmptyColumnsBefore = emptyColumns.Where(column => column < j).Count();
|
||||
var columnOffset = numOfEmptyColumnsBefore is 0
|
||||
? 0
|
||||
: (numOfEmptyColumnsBefore * expandFactor) - numOfEmptyColumnsBefore;
|
||||
|
||||
galaxies.Add(new Galaxy(i + rowOffset, j + columnOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var heightOffset = emptyRows.Count is 0
|
||||
? 0
|
||||
: (emptyRows.Count * expandFactor) - emptyRows.Count;
|
||||
var widthOffset = emptyColumns.Count is 0
|
||||
? 0
|
||||
: (emptyColumns.Count * expandFactor) - emptyColumns.Count;
|
||||
|
||||
var height = input.Length + heightOffset;
|
||||
var width = input[0].Length + widthOffset;
|
||||
|
||||
return new Universe(
|
||||
height,
|
||||
width,
|
||||
galaxies
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class Galaxy(
|
||||
long row,
|
||||
long column
|
||||
)
|
||||
{
|
||||
public long Row { get; init; } = row;
|
||||
public long Column { get; init; } = column;
|
||||
}
|
||||
Reference in New Issue
Block a user