143 lines
6.5 KiB
C#
143 lines
6.5 KiB
C#
using AdventOfCode.Core.Shared.IO;
|
|
|
|
namespace AdventOfCode.Solutions._2023
|
|
{
|
|
public class Day16 : IChallange
|
|
{
|
|
public int Year => 2023;
|
|
public int Day => 16;
|
|
|
|
private readonly IInputReader _inputReader;
|
|
|
|
public Day16(IInputReader inputReader)
|
|
{
|
|
_inputReader = inputReader;
|
|
_inputReader.SetInput(this);
|
|
}
|
|
|
|
public async Task<string> GetSolutionPart1()
|
|
{
|
|
Grid<Point> grid = await _inputReader.ReadToGrid<Point>();
|
|
Point? point = grid.TryGetNode(0, 0);
|
|
ISet<Point> set = Move(grid, new HashSet<Point>(), new HashSet<Point>(), point, Direction.Right);
|
|
return set.Count.ToString();
|
|
}
|
|
|
|
public async Task<string> GetSolutionPart2()
|
|
{
|
|
Grid<Point> grid = await _inputReader.ReadToGrid<Point>();
|
|
int columnMax = grid.GetColumn(0).Select(p => Move(grid, new HashSet<Point>(), new HashSet<Point>(), p, Direction.Down).Count).Max();
|
|
int rowMax = grid.GetRow(0).Select(p => Move(grid, new HashSet<Point>(), new HashSet<Point>(), p, Direction.Right).Count).Max();
|
|
return Math.Max(columnMax, rowMax).ToString();
|
|
}
|
|
|
|
private static ISet<Point> Move(Grid<Point> grid, ISet<Point> energized, ISet<Point> splittersHit, Point? currentLocation, Direction direction)
|
|
{
|
|
if (currentLocation == null)
|
|
return energized;
|
|
|
|
if ((currentLocation.Value == '-' || currentLocation.Value == '|') && !splittersHit.Add(currentLocation))
|
|
return energized;
|
|
|
|
energized.Add(currentLocation);
|
|
|
|
|
|
(long X, long Y, Direction NewDirection) newPosition = (currentLocation.X, currentLocation.Y, direction);
|
|
switch (currentLocation.Value)
|
|
{
|
|
case '.':
|
|
newPosition = MoveStraight(currentLocation, direction);
|
|
Point? newPoint = grid.TryGetNode(newPosition.X, newPosition.Y);
|
|
while(newPoint != null && newPoint.Value == '.')
|
|
{
|
|
energized.Add(newPoint);
|
|
newPosition = MoveStraight(newPoint, direction);
|
|
newPoint = grid.TryGetNode(newPosition.X, newPosition.Y);
|
|
}
|
|
return Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
case '\\':
|
|
if (direction == Direction.Down || direction == Direction.Up)
|
|
newPosition = MoveLeft(currentLocation, direction);
|
|
else if (direction == Direction.Right ||direction == Direction.Left)
|
|
newPosition = MoveRight(currentLocation, direction);
|
|
return Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
|
|
case '/':
|
|
if (direction == Direction.Down || direction == Direction.Up)
|
|
newPosition = MoveRight(currentLocation, direction);
|
|
else if (direction == Direction.Right || direction == Direction.Left)
|
|
newPosition = MoveLeft(currentLocation, direction);
|
|
|
|
return Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
case '|':
|
|
if (direction == Direction.Up || direction == Direction.Down)
|
|
newPosition = MoveStraight(currentLocation, direction);
|
|
else
|
|
{
|
|
newPosition = MoveLeft(currentLocation, direction);
|
|
energized = Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
newPosition = MoveRight(currentLocation, direction);
|
|
}
|
|
return Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
case '-':
|
|
|
|
if (direction == Direction.Right || direction == Direction.Left)
|
|
newPosition = MoveStraight(currentLocation, direction);
|
|
else
|
|
{
|
|
newPosition = MoveLeft(currentLocation, direction);
|
|
energized = Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
newPosition = MoveRight(currentLocation, direction);
|
|
}
|
|
return Move(grid, energized, splittersHit, grid.TryGetNode(newPosition.X, newPosition.Y), newPosition.NewDirection);
|
|
}
|
|
|
|
|
|
return energized;
|
|
}
|
|
|
|
private enum Direction
|
|
{
|
|
Up,
|
|
Down,
|
|
Left,
|
|
Right
|
|
}
|
|
|
|
private static (long X, long Y, Direction NewDirection) MoveStraight(Point from, Direction direction)
|
|
{
|
|
return direction switch
|
|
{
|
|
Direction.Up => (from.X, from.Y - 1, direction),
|
|
Direction.Down => (from.X, from.Y + 1, direction),
|
|
Direction.Left => (from.X - 1, from.Y, direction),
|
|
Direction.Right => (from.X + 1, from.Y, direction),
|
|
_ => (from.X, from.Y, direction),
|
|
};
|
|
}
|
|
|
|
private static (long X, long Y, Direction NewDirection) MoveLeft(Point from, Direction direction)
|
|
{
|
|
return direction switch
|
|
{
|
|
Direction.Up => (from.X - 1, from.Y, Direction.Left),
|
|
Direction.Down => (from.X + 1, from.Y, Direction.Right),
|
|
Direction.Left => (from.X, from.Y + 1, Direction.Down),
|
|
Direction.Right => (from.X, from.Y - 1, Direction.Up),
|
|
_ => (from.X, from.Y, direction),
|
|
};
|
|
}
|
|
|
|
private static (long X, long Y, Direction NewDirection) MoveRight(Point from, Direction direction)
|
|
{
|
|
return direction switch
|
|
{
|
|
Direction.Up => (from.X + 1, from.Y, Direction.Right),
|
|
Direction.Down => (from.X - 1, from.Y, Direction.Left),
|
|
Direction.Left => (from.X, from.Y - 1, Direction.Up),
|
|
Direction.Right => (from.X, from.Y + 1, Direction.Down),
|
|
_ => (from.X, from.Y, direction),
|
|
};
|
|
}
|
|
}
|
|
} |