It's back to easier problems with this one.
My solution was to create a dictionary of rooms and their doors. This is easily done in C# with a flags enum:
[Flags]
private enum RoomDoors
{
None = 0,
North = 1,
South = 2,
East = 4,
West = 8
}
This allows to create rooms with multiple doors by combining them as such: RoomDoors.North | RoomDoors.South | RoomDoors.East
(this room would have a door on the north side, south side and east side, but no door on the west side). The only "constraint" of flags enum in C# is that your values should be powers of two: think of it as being bits lighting up in a byte. This also allows boolean arithmetic like adding a door to a room: doors |= RoomDoors.North
and easy checking of doors in a room using doors.HasFlag(RoomDoors.North)
.
I created a RegexParser class to parse the input using a stack of the current positions. The basic directions pop the stack, add a door depending on the direction and push the new position on the stack. The opening parentheses copy the top position of the stack, the closing parentheses remove the top position and the vertical bar removes the top and copies the second (now top), effectively going back to the previous position and copying it.
This class was used to drive a MapBuilder class that contained the doors for each room in a dictionary and a method to add a new door beside a door considering the direction.
Once the map was created, I created a DistanceCalculator class that takes the dictionary of rooms with their doors and created dictionary of rooms with their distance from the starting position. To calculate the distance I looped through each room and checked the smallest distance between it's four possible adjacent rooms, increasing it by 1 and saving it to the new room.
With this distance map, the first part of the problem is solved by finding the largest distance in the map and the second part is solved by counting the number of distances more than 1000.