Completed day 14
This commit is contained in:
parent
50810d6e06
commit
3c8a45f6e6
@ -7,9 +7,9 @@ InputReader inputReader = new()
|
|||||||
//IsDebug = true
|
//IsDebug = true
|
||||||
};
|
};
|
||||||
|
|
||||||
//inputReader.SetInputByChallange(3);
|
inputReader.SetInputByChallange(14);
|
||||||
|
|
||||||
IChallange challange = new Day15(inputReader);
|
IChallange challange = new Day14(inputReader);
|
||||||
|
|
||||||
Console.WriteLine($"Part 1: {await challange.GetSolutionPart1()}");
|
Console.WriteLine($"Part 1: {await challange.GetSolutionPart1()}");
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
using AdventOfCode.Core;
|
using AdventOfCode.Core;
|
||||||
using AdventOfCode.Core.Shared.Grid;
|
using AdventOfCode.Core.Shared.Grid;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks.Dataflow;
|
|
||||||
|
|
||||||
namespace AdventOfCode.Solutions._2023
|
namespace AdventOfCode.Solutions._2023
|
||||||
{
|
{
|
||||||
@ -19,104 +16,57 @@ namespace AdventOfCode.Solutions._2023
|
|||||||
|
|
||||||
bolders = MoveUp(bolders, cubes);
|
bolders = MoveUp(bolders, cubes);
|
||||||
|
|
||||||
return bolders.Sum(bolder => grid.Rows - bolder.Y).ToString();
|
return CalculateLoad(CreateStringMap(bolders, cubes, grid.Rows, grid.Columns).Split(':'), grid.Rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetSolutionPart2()
|
public async Task<string> GetSolutionPart2()
|
||||||
{
|
{
|
||||||
int maxCycles = 1_000_000_000;
|
int maxCycles = 1_000_000_000;
|
||||||
Dictionary<string, int> mapStates = [];
|
Dictionary<string, int> mapStates = [];
|
||||||
bool foundLoop = false;
|
|
||||||
|
|
||||||
Grid<Point> grid = await _inputReader.ReadToGrid<Point>();
|
Grid<Point> grid = await _inputReader.ReadToGrid<Point>();
|
||||||
HashSet<Point> bolders = grid.FindWithValue('O').Select(p => new Point(p.X, p.Y)).ToHashSet();
|
HashSet<Point> bolders = grid.FindWithValue('O').Select(p => new Point(p.X, p.Y)).ToHashSet();
|
||||||
HashSet<Point> cubes = grid.FindWithValue('#').Select(p => new Point(p.X, p.Y)).ToHashSet();
|
HashSet<Point> cubes = grid.FindWithValue('#').Select(p => new Point(p.X, p.Y)).ToHashSet();
|
||||||
|
|
||||||
int totalBolders = bolders.Count;
|
for (int currentCycle = 1; currentCycle <= maxCycles; currentCycle++)
|
||||||
|
|
||||||
for (int currentCycle = 0; currentCycle < maxCycles; currentCycle++)
|
|
||||||
{
|
{
|
||||||
// ensure the state is saved
|
|
||||||
mapStates.TryAdd(CreateStringMap(bolders, cubes, grid.Rows, grid.Columns), currentCycle);
|
|
||||||
// add a test to see when we hit the right cycle for the test data
|
|
||||||
|
|
||||||
// move the boulders
|
// move the boulders
|
||||||
bolders = MoveUp(bolders, cubes);
|
bolders = MoveUp(bolders, cubes);
|
||||||
if (bolders.Count != totalBolders)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"lost boulders MoveUp at {currentCycle}, from {totalBolders} to {bolders.Count}");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
bolders = MoveLeft(bolders, cubes);
|
bolders = MoveLeft(bolders, cubes);
|
||||||
if (bolders.Count != totalBolders)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"lost boulders MoveLeft at {currentCycle}, from {totalBolders} to {bolders.Count}");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
bolders = MoveDown(bolders, cubes, grid.Rows);
|
bolders = MoveDown(bolders, cubes, grid.Rows);
|
||||||
if (bolders.Count != totalBolders)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"lost boulders MoveDown at {currentCycle}, from {totalBolders} to {bolders.Count}");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
bolders = MoveRight(bolders, cubes, grid.Columns);
|
bolders = MoveRight(bolders, cubes, grid.Columns);
|
||||||
|
|
||||||
if (bolders.Count != totalBolders)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"lost boulders MoveRight at {currentCycle}, from {totalBolders} to {bolders.Count}");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we found the loop, if so we continue untill the end
|
|
||||||
if (foundLoop) continue;
|
|
||||||
|
|
||||||
// see if the current layout of the platform already exists
|
// see if the current layout of the platform already exists
|
||||||
// if so we are repeating our selfs so wel can calculate the remaining steps to get to the end.
|
|
||||||
// we might even yoink the map from the dic and use that
|
|
||||||
if (mapStates.TryGetValue(CreateStringMap(bolders, cubes, grid.Rows, grid.Columns), out int prevCycle))
|
if (mapStates.TryGetValue(CreateStringMap(bolders, cubes, grid.Rows, grid.Columns), out int prevCycle))
|
||||||
{
|
{
|
||||||
// calculate remaining cycles to the first exit point
|
long cyclesWithoutStartCycles = maxCycles - prevCycle;
|
||||||
int remainingCycles = maxCycles % (currentCycle + 1);
|
long cycleLength = currentCycle - prevCycle;
|
||||||
// set the total the first exit point
|
|
||||||
int exitMap = remainingCycles + currentCycle;
|
|
||||||
|
|
||||||
string[] lines = mapStates.First(kvp => kvp.Value == prevCycle - 1).Key.Split(':', StringSplitOptions.RemoveEmptyEntries);
|
long remainingCycles = cyclesWithoutStartCycles % cycleLength;
|
||||||
int totalWeight = 0;
|
long exitMap = remainingCycles + prevCycle;
|
||||||
for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
|
string[] lines = mapStates.First(kvp => kvp.Value == exitMap).Key.Split(':');
|
||||||
{
|
return CalculateLoad(lines, grid.Rows);
|
||||||
int weight = lines[lineIndex].Length, lineWeight = 0;
|
|
||||||
for (int charIndex = 0; charIndex < lines[lineIndex].Length; charIndex++)
|
|
||||||
{
|
|
||||||
if (lines[lineIndex][charIndex] is '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (lines[lineIndex][charIndex] is '#')
|
|
||||||
{
|
|
||||||
weight = lines[lineIndex].Length - charIndex - 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lines[lineIndex][charIndex] is 'O')
|
|
||||||
{
|
|
||||||
lineWeight += weight;
|
|
||||||
weight--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
totalWeight += lineWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalWeight.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure the state is saved
|
||||||
|
mapStates.TryAdd(CreateStringMap(bolders, cubes, grid.Rows, grid.Columns), currentCycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return bolders.Sum(bolder => grid.Rows - bolder.Y).ToString();
|
return bolders.Sum(bolder => grid.Rows - bolder.Y).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string CalculateLoad(string[] lines, long totalRows)
|
||||||
|
{
|
||||||
|
long totalWeight = 0;
|
||||||
|
for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
|
||||||
|
{
|
||||||
|
int bolders = lines[lineIndex].Where(c => c == 'O').Count();
|
||||||
|
totalWeight += bolders * (totalRows - lineIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalWeight.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private HashSet<Point> MoveUp(HashSet<Point> bolders, HashSet<Point> cubes)
|
private HashSet<Point> MoveUp(HashSet<Point> bolders, HashSet<Point> cubes)
|
||||||
{
|
{
|
||||||
HashSet<Point> boldersMoved = [];
|
HashSet<Point> boldersMoved = [];
|
||||||
@ -143,16 +93,14 @@ namespace AdventOfCode.Solutions._2023
|
|||||||
HashSet<Point> boldersMoved = [];
|
HashSet<Point> boldersMoved = [];
|
||||||
foreach (Point bolder in bolders.OrderByDescending(bolder => bolder.Y))
|
foreach (Point bolder in bolders.OrderByDescending(bolder => bolder.Y))
|
||||||
{
|
{
|
||||||
// current location
|
|
||||||
long ySearch = bolder.Y;
|
long ySearch = bolder.Y;
|
||||||
while (ySearch + 1 < ySize // ensure in map
|
while (ySearch + 1 < ySize
|
||||||
&& !boldersMoved.Contains(new(bolder.X, ySearch + 1)) // check that the next tile does not have a bolder
|
&& !boldersMoved.Contains(new(bolder.X, ySearch + 1))
|
||||||
&& !cubes.Contains(new(bolder.X, ySearch + 1))) // check that the next tile has not cube
|
&& !cubes.Contains(new(bolder.X, ySearch + 1)))
|
||||||
{
|
{
|
||||||
ySearch++; // move to next
|
ySearch++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// something found on next location so place bolder here
|
|
||||||
boldersMoved.Add(new(bolder.X, ySearch));
|
boldersMoved.Add(new(bolder.X, ySearch));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,16 +112,14 @@ namespace AdventOfCode.Solutions._2023
|
|||||||
HashSet<Point> boldersMoved = [];
|
HashSet<Point> boldersMoved = [];
|
||||||
foreach (Point bolder in bolders.OrderBy(bolder => bolder.X))
|
foreach (Point bolder in bolders.OrderBy(bolder => bolder.X))
|
||||||
{
|
{
|
||||||
// current location
|
|
||||||
long xSearch = bolder.X;
|
long xSearch = bolder.X;
|
||||||
while (xSearch - 1 >= 0 // ensure in map
|
while (xSearch - 1 >= 0
|
||||||
&& !boldersMoved.Contains(new(xSearch - 1, bolder.Y)) // check that the next tile does not have a bolder
|
&& !boldersMoved.Contains(new(xSearch - 1, bolder.Y))
|
||||||
&& !cubes.Contains(new(xSearch - 1, bolder.Y))) // check that the next tile has not cube
|
&& !cubes.Contains(new(xSearch - 1, bolder.Y)))
|
||||||
{
|
{
|
||||||
xSearch--; // move to next
|
xSearch--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// something found on next location so place bolder here
|
|
||||||
boldersMoved.Add(new(xSearch, bolder.Y));
|
boldersMoved.Add(new(xSearch, bolder.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,16 +131,14 @@ namespace AdventOfCode.Solutions._2023
|
|||||||
HashSet<Point> boldersMoved = [];
|
HashSet<Point> boldersMoved = [];
|
||||||
foreach (Point bolder in bolders.OrderByDescending(bolder => bolder.X))
|
foreach (Point bolder in bolders.OrderByDescending(bolder => bolder.X))
|
||||||
{
|
{
|
||||||
// current location
|
|
||||||
long xSearch = bolder.X;
|
long xSearch = bolder.X;
|
||||||
while (xSearch + 1 < xSize // ensure in map
|
while (xSearch + 1 < xSize
|
||||||
&& !boldersMoved.Contains(new(xSearch + 1, bolder.Y)) // check that the next tile does not have a bolder
|
&& !boldersMoved.Contains(new(xSearch + 1, bolder.Y))
|
||||||
&& !cubes.Contains(new(xSearch + 1, bolder.Y))) // check that the next tile has not cube
|
&& !cubes.Contains(new(xSearch + 1, bolder.Y)))
|
||||||
{
|
{
|
||||||
xSearch++; // move to next
|
xSearch++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// something found on next location so place bolder here
|
|
||||||
boldersMoved.Add(new(xSearch, bolder.Y));
|
boldersMoved.Add(new(xSearch, bolder.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user