Skip to content

Commit

Permalink
Day 11 (#48)
Browse files Browse the repository at this point in the history
* Added day 11 with part one solved

* Add part two solution

* Reorder for readability

* Finalize day project

* Fix formatting
  • Loading branch information
mMosiur authored May 9, 2024
1 parent a5033cb commit 79957e0
Show file tree
Hide file tree
Showing 17 changed files with 416 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .run/Day11 example.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Day11 example" type="DotNetProject" factoryName=".NET Project"
folderName="Day11">
<option name="EXE_PATH" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/bin/Debug/net8.0/Day11.exe"/>
<option name="PROGRAM_PARAMETERS" value="example.txt"/>
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/bin/Debug/net8.0"/>
<option name="PASS_PARENT_ENVS" value="1"/>
<option name="USE_EXTERNAL_CONSOLE" value="0"/>
<option name="USE_MONO" value="0"/>
<option name="RUNTIME_ARGUMENTS" value=""/>
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/Day11.csproj"/>
<option name="PROJECT_EXE_PATH_TRACKING" value="1"/>
<option name="PROJECT_ARGUMENTS_TRACKING" value="1"/>
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1"/>
<option name="PROJECT_KIND" value="DotNetCore"/>
<option name="PROJECT_TFM" value="net8.0"/>
<method v="2">
<option name="Build"/>
</method>
</configuration>
</component>
20 changes: 20 additions & 0 deletions .run/Day11.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Day11" type="DotNetProject" factoryName=".NET Project" folderName="Day11">
<option name="EXE_PATH" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/bin/Debug/net8.0/Day11.exe"/>
<option name="PROGRAM_PARAMETERS" value=""/>
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/bin/Debug/net8.0"/>
<option name="PASS_PARENT_ENVS" value="1"/>
<option name="USE_EXTERNAL_CONSOLE" value="0"/>
<option name="USE_MONO" value="0"/>
<option name="RUNTIME_ARGUMENTS" value=""/>
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Day11 - Cosmic Expansion/Day11.csproj"/>
<option name="PROJECT_EXE_PATH_TRACKING" value="1"/>
<option name="PROJECT_ARGUMENTS_TRACKING" value="1"/>
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1"/>
<option name="PROJECT_KIND" value="DotNetCore"/>
<option name="PROJECT_TFM" value="net8.0"/>
<method v="2">
<option name="Build"/>
</method>
</configuration>
</component>
7 changes: 7 additions & 0 deletions AdventOfCode2023.sln
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Day09", "Day09 - Mirage Mai
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Day10", "Day10 - Pipe Maze\Day10.csproj", "{D237B79E-9D78-4F99-B9BA-43B52609AAAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Day11", "Day11 - Cosmic Expansion\Day11.csproj", "{28DC51A6-39A7-4180-B890-D5B5D0AF71EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -92,6 +94,10 @@ Global
{D237B79E-9D78-4F99-B9BA-43B52609AAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D237B79E-9D78-4F99-B9BA-43B52609AAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D237B79E-9D78-4F99-B9BA-43B52609AAAE}.Release|Any CPU.Build.0 = Release|Any CPU
{28DC51A6-39A7-4180-B890-D5B5D0AF71EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28DC51A6-39A7-4180-B890-D5B5D0AF71EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28DC51A6-39A7-4180-B890-D5B5D0AF71EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28DC51A6-39A7-4180-B890-D5B5D0AF71EC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CE8086B8-A3E4-40E0-859F-607F95D25514} = {F6C05A63-6269-425F-B877-9E9F0BC1FC26}
Expand All @@ -104,5 +110,6 @@ Global
{78787B01-0E1E-472E-8B58-4FFD864FC1F6} = {F6C05A63-6269-425F-B877-9E9F0BC1FC26}
{1E0917F9-35B3-4474-B335-E72C6BDFE667} = {F6C05A63-6269-425F-B877-9E9F0BC1FC26}
{D237B79E-9D78-4F99-B9BA-43B52609AAAE} = {F6C05A63-6269-425F-B877-9E9F0BC1FC26}
{28DC51A6-39A7-4180-B890-D5B5D0AF71EC} = {F6C05A63-6269-425F-B877-9E9F0BC1FC26}
EndGlobalSection
EndGlobal
18 changes: 18 additions & 0 deletions Day11 - Cosmic Expansion/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch (my input)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/Day11.dll",
"args": [
"input.txt"
],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
}
]
}
21 changes: 21 additions & 0 deletions Day11 - Cosmic Expansion/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"group": {
"kind": "build",
"isDefault": true
},
"args": [
"build",
"${workspaceFolder}/Day11.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
22 changes: 22 additions & 0 deletions Day11 - Cosmic Expansion/Day11.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>AdventOfCode.Year2023.Day11</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="mMosiur.AdventOfCode.Abstractions" Version="4.4.1"/>
<PackageReference Include="mMosiur.AdventOfCode.Common" Version="0.1.3"/>
</ItemGroup>

<ItemGroup>
<None Update="*.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
63 changes: 63 additions & 0 deletions Day11 - Cosmic Expansion/Day11Solver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using AdventOfCode.Abstractions;
using AdventOfCode.Common.Geometry;
using AdventOfCode.Year2023.Day11.Puzzle;

namespace AdventOfCode.Year2023.Day11;

public sealed class Day11Solver : DaySolver
{
public override int Year => 2023;
public override int Day => 11;
public override string Title => "Cosmic Expansion";

private readonly IReadOnlyCollection<Point> _initialPositions;
private readonly Day11SolverOptions _options;

public Day11Solver(Day11SolverOptions options) : base(options)
{
_options = options;
var inputReader = new InputReader(options.GalaxyChar);
_initialPositions = inputReader.ReadGalaxyPositions(Input);
}

public Day11Solver(Action<Day11SolverOptions> configure)
: this(DaySolverOptions.FromConfigureAction(configure))
{
}

public Day11Solver() : this(new Day11SolverOptions())
{
}

public override string SolvePart1()
{
var galaxyMap = new GalaxyMap(_initialPositions);
galaxyMap.Expand(_options.PartOneExpansionMagnitude);
long sum = SumDistancesBetweenGalaxies(galaxyMap);
return sum.ToString();
}

public override string SolvePart2()
{
var galaxyMap = new GalaxyMap(_initialPositions);
galaxyMap.Expand(_options.PartTwoExpansionMagnitude);
long sum = SumDistancesBetweenGalaxies(galaxyMap);
return sum.ToString();
}

private static long SumDistancesBetweenGalaxies(GalaxyMap galaxyMap)
{
long sum = 0;
for (int i = 0; i < galaxyMap.Galaxies.Count; i++)
{
var g1 = galaxyMap.Galaxies[i];
for (int j = i + 1; j < galaxyMap.Galaxies.Count; j++)
{
var g2 = galaxyMap.Galaxies[j];
sum += MathG.ManhattanDistance(g1.Position, g2.Position);
}
}

return sum;
}
}
11 changes: 11 additions & 0 deletions Day11 - Cosmic Expansion/Day11SolverOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using AdventOfCode.Abstractions;

namespace AdventOfCode.Year2023.Day11;

public sealed class Day11SolverOptions : DaySolverOptions
{
public char GalaxyChar { get; set; } = '#';

public int PartOneExpansionMagnitude { get; set; } = 2;
public int PartTwoExpansionMagnitude { get; set; } = 1_000_000;
}
1 change: 1 addition & 0 deletions Day11 - Cosmic Expansion/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Point = AdventOfCode.Common.Geometry.Point2D<long>;
42 changes: 42 additions & 0 deletions Day11 - Cosmic Expansion/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Diagnostics;
using AdventOfCode;
using AdventOfCode.Year2023.Day11;

try
{
string? filepath = args.Length switch
{
0 => null,
1 => args[0],
_ => throw new CommandLineException(
$"Program was called with too many arguments. Proper usage: \"dotnet run [<input filepath>]\"."
)
};

Day11Solver solver = new(options => { options.InputFilepath = filepath ?? options.InputFilepath; });

Console.WriteLine($"--- Day {solver.Day}: {solver.Title} ---");

Console.Write("Part one: ");
string part1 = solver.SolvePart1();
Console.WriteLine(part1);

Console.Write("Part two: ");
string part2 = solver.SolvePart2();
Console.WriteLine(part2);
}
catch (AdventOfCodeException e)
{
string errorPrefix = e switch
{
CommandLineException => "Command line error",
InputException => "Input error",
DaySolverException => "Day solver error",
_ => throw new UnreachableException($"Unknown exception type \"{e.GetType()}\".")
};

Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($"{errorPrefix}: {e.Message}");
Console.ResetColor();
Environment.Exit(1);
}
11 changes: 11 additions & 0 deletions Day11 - Cosmic Expansion/Puzzle/Galaxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace AdventOfCode.Year2023.Day11.Puzzle;

internal interface IGalaxy
{
Point Position { get; }
}

internal sealed class Galaxy(Point position) : IGalaxy
{
public Point Position { get; set; } = position;
}
95 changes: 95 additions & 0 deletions Day11 - Cosmic Expansion/Puzzle/GalaxyMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
namespace AdventOfCode.Year2023.Day11.Puzzle;

internal sealed class GalaxyMap
{
private const int ExpandListInitialCapacity = 10;

private readonly List<Galaxy> _galaxies;
private long _maxColumn;
private long _maxRow;

public GalaxyMap(IEnumerable<Point> galaxyPositions)
{
_galaxies = galaxyPositions.Select(p => new Galaxy(p)).ToList();
_maxRow = _galaxies.Max(g => g.Position.X);
_maxColumn = _galaxies.Max(g => g.Position.Y);
}

public IReadOnlyList<IGalaxy> Galaxies => _galaxies;

public void Expand(int expansionMagnitude)
{
ExpandRows(expansionMagnitude);
ExpandColumns(expansionMagnitude);
}

private void ExpandRows(int expansionMagnitude)
{
var galaxiesPerRow = new List<Galaxy>?[_maxRow + 1];
foreach (var galaxy in _galaxies)
{
long row = galaxy.Position.X;
var rowList = galaxiesPerRow[row];
if (rowList is null)
{
rowList = new List<Galaxy>(ExpandListInitialCapacity);
galaxiesPerRow[row] = rowList;
}

rowList.Add(galaxy);
}

int rowOffset = 0;
for (int row = 0; row <= _maxRow; row++)
{
var rowList = galaxiesPerRow[row];
if (rowList is null)
{
rowOffset = rowOffset + expansionMagnitude - 1;
continue;
}

foreach (var galaxy in rowList)
{
galaxy.Position = new(row + rowOffset, galaxy.Position.Y);
}
}

_maxRow += rowOffset;
}

private void ExpandColumns(int expansionMagnitude)
{
var galaxiesPerColumn = new List<Galaxy>?[_maxColumn + 1];
foreach (var galaxy in _galaxies)
{
long column = galaxy.Position.Y;
var columnList = galaxiesPerColumn[column];
if (columnList is null)
{
columnList = new List<Galaxy>(ExpandListInitialCapacity);
galaxiesPerColumn[column] = columnList;
}

columnList.Add(galaxy);
}

int columnOffset = 0;
for (int column = 0; column <= _maxColumn; column++)
{
var columnList = galaxiesPerColumn[column];
if (columnList is null)
{
columnOffset = columnOffset + expansionMagnitude - 1;
continue;
}

foreach (var galaxy in columnList)
{
galaxy.Position = new(galaxy.Position.X, column + columnOffset);
}
}

_maxColumn += columnOffset;
}
}
35 changes: 35 additions & 0 deletions Day11 - Cosmic Expansion/Puzzle/InputReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace AdventOfCode.Year2023.Day11.Puzzle;

internal sealed class InputReader
{
private const int InitialGalaxyListSize = 500;
private readonly char _galaxyChar;

public InputReader(char galaxyChar)
{
_galaxyChar = galaxyChar;
}

public IReadOnlyCollection<Point> ReadGalaxyPositions(string input)
{
var list = new List<Point>(InitialGalaxyListSize);
int row = 0;
foreach (var lineSpan in input.AsSpan().EnumerateLines())
{
int column = 0;
foreach (char c in lineSpan)
{
if (c == _galaxyChar)
{
list.Add(new(row, column));
}

column++;
}

row++;
}

return list;
}
}
Loading

0 comments on commit 79957e0

Please sign in to comment.