Skip to content

Commit

Permalink
Merge pull request #16 from MartinZikmund/feature/aoc2024-day15
Browse files Browse the repository at this point in the history
AoC 2024 Day 15 Solutions
  • Loading branch information
MartinZikmund authored Dec 19, 2024
2 parents 5d7d206 + bf29a23 commit 72df7be
Show file tree
Hide file tree
Showing 3 changed files with 339 additions and 0 deletions.
121 changes: 121 additions & 0 deletions src/AdventOfCode.Puzzles/2024/15/Part1/Part1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Diagnostics;
using System.Text;
using AdventOfCode.Puzzles.Tools;

namespace AdventOfCode.Puzzles._2024._15.Part1;

public partial class Part1 : IPuzzleSolution
{
private int _width;
private int _height;
private char[,] _map;
private string _instructions;
private Point _robotPosition;

public async Task<string> SolveAsync(StreamReader inputReader)
{
var mapLines = new List<string>();
while (await inputReader.ReadLineAsync() is { } line && !string.IsNullOrWhiteSpace(line))
{
mapLines.Add(line);
}

_width = mapLines[0].Length;
_height = mapLines.Count;
_map = new char[_width, _height];

for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
_map[x, y] = mapLines[y][x];

if (_map[x, y] == '@')
{
_robotPosition = new Point(x, y);
}
}
}

StringBuilder instructions = new();
while (await inputReader.ReadLineAsync() is { } line)
{
instructions.Append(line);
}

_instructions = instructions.ToString();

foreach (var instruction in _instructions)
{
MoveRobot(instruction);
}

var total = 0;
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
if (_map[x, y] == 'O')
{
total += y * 100 + x;
}
}
}

return total.ToString();
}

private void MoveRobot(char instruction)
{
var direction = instruction switch
{
'^' => new Point(0, -1),
'>' => new Point(1, 0),
'v' => new Point(0, 1),
'<' => new Point(-1, 0),
_ => throw new InvalidOperationException()
};

if (CanMove(_robotPosition, direction))
{
Move(_robotPosition, direction);
_robotPosition += direction;
}
}

private bool CanMove(Point position, Point direction)
{
var newPosition = position + direction;

var newTile = _map[newPosition.X, newPosition.Y];
if (newTile == '#')
{
return false;
}
else if (newTile == 'O')
{
return CanMove(newPosition, direction);
}
else if (newTile == '.')
{
return true;
}
else
{
throw new InvalidOperationException();
}
}

private void Move(Point position, Point direction)
{
var newPosition = position + direction;
var newTile = _map[newPosition.X, newPosition.Y];
if (newTile != '.')
{
Move(newPosition, direction);
}

_map[newPosition.X, newPosition.Y] = _map[position.X, position.Y];
_map[position.X, position.Y] = '.';
}
}
197 changes: 197 additions & 0 deletions src/AdventOfCode.Puzzles/2024/15/Part2/Part2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
using System.Diagnostics;
using System.Text;
using AdventOfCode.Puzzles.Tools;

namespace AdventOfCode.Puzzles._2024._15.Part2;

public partial class Part2 : IPuzzleSolution
{
private int _width;
private int _height;
private char[,] _map;
private string _instructions;
private Point _robotPosition;

public async Task<string> SolveAsync(StreamReader inputReader)
{
var mapLines = new List<string>();
while (await inputReader.ReadLineAsync() is { } line && !string.IsNullOrWhiteSpace(line))
{
mapLines.Add(line);
}

_width = mapLines[0].Length * 2;
_height = mapLines.Count;
_map = new char[_width, _height];

for (int y = 0; y < _height; y++)
{
for (int x = 0; x < mapLines[0].Length; x++)
{
var character = mapLines[y][x];

if (character == '@')
{
_robotPosition = new Point(x * 2, y);
_map[x * 2, y] = '@';
_map[x * 2 + 1, y] = '.';
}
else if (character == '#')
{
_map[x * 2, y] = '#';
_map[x * 2 + 1, y] = '#';
}
else if (character == '.')
{
_map[x * 2, y] = '.';
_map[x * 2 + 1, y] = '.';
}
else if (character == 'O')
{
_map[x * 2, y] = '[';
_map[x * 2 + 1, y] = ']';
}
}
}

StringBuilder instructions = new();
while (await inputReader.ReadLineAsync() is { } line)
{
instructions.Append(line);
}

_instructions = instructions.ToString();

foreach (var instruction in _instructions)
{
MoveRobot(instruction);
}

var total = 0;
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
if (_map[x, y] == '[')
{
total += y * 100 + x;
}
}
}

return total.ToString();
}

private void OutputMap()
{
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
Debug.Write(_map[x, y]);
}
Debug.WriteLine("");
}
}

private void MoveRobot(char instruction)
{
var direction = instruction switch
{
'^' => new Point(0, -1),
'>' => new Point(1, 0),
'v' => new Point(0, 1),
'<' => new Point(-1, 0),
_ => throw new InvalidOperationException()
};

if (CanMove(_robotPosition, direction))
{
//OutputMap();
Move(_robotPosition, direction);
_robotPosition += direction;
}
}

private bool CanMove(Point position, Point direction)
{
var newPosition = position + direction;
var currentTile = _map[position.X, position.Y];

if (currentTile == '.')
{
return true;
}

if (currentTile == '#')
{
return false;
}

var newTile = _map[newPosition.X, newPosition.Y];

if (currentTile == '[' || currentTile == ']')
{
if ((currentTile == ']' && direction == (-1, 0)) ||
(currentTile == '[' && direction == (1, 0)))
{
return CanMove(newPosition, direction);
}

if (currentTile == ']' && (direction == (0, -1) || direction == (0, 1)))
{
return CanMove(newPosition, direction) && CanMove(newPosition + (-1, 0), direction);
}

if (currentTile == '[' && (direction == (0, -1) || direction == (0, 1)))
{
return CanMove(newPosition, direction) && CanMove(newPosition + (1, 0), direction);
}

return CanMove(newPosition, direction);
}

if (currentTile == '@')
{
return CanMove(newPosition, direction);
}

throw new InvalidOperationException();
}

private void Move(Point position, Point direction)
{
var newPosition = position + direction;

var currentTile = _map[position.X, position.Y];
var newTile = _map[newPosition.X, newPosition.Y];

if (direction == (-1, 0) || direction == (1, 0))
{
if (newTile != '.')
{
Move(newPosition, direction);
}
}
else
{
if (newTile == '[')
{
Move(newPosition + (1, 0), direction);
Move(newPosition, direction);
}
else if (newTile == ']')
{
Move(newPosition + (-1, 0), direction);
Move(newPosition, direction);
}
else if (newTile != '.')
{
Move(newPosition, direction);
}
}

_map[newPosition.X, newPosition.Y] = _map[position.X, position.Y];
_map[position.X, position.Y] = '.';
}
}
21 changes: 21 additions & 0 deletions src/AdventOfCode.Puzzles/2024/15/TestData.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#[email protected].#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########

<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^

0 comments on commit 72df7be

Please sign in to comment.