using System.Collections.Generic;
public static void Main()
Map map = new Map(Input.INPUT2);
List<char> keys = new List<char>();
map.FindKeyOrder(out pathLength, keys);
Console.WriteLine("Keys: " + string.Join(",", keys));
Console.WriteLine("Distance: " + pathLength);
public struct Vec2 : IEquatable<Vec2> {
public Vec2(int x, int y) {
public static Vec2 operator+(Vec2 a, Vec2 b) {
return new Vec2() { x = a.x + b.x, y = a.y + b.y };
public static Vec2 operator+(Vec2 v, Direction dir) {
public Direction GetDirection(Vec2 other) {
if (other.x == x && other.y == y)
if (Math.Abs(other.x - x) > Math.Abs(other.y - y)) {
public int GetManhattan(Vec2 other) {
return Math.Abs(x - other.x) + Math.Abs(y - other.y);
public static bool operator==(Vec2 a, Vec2 b) {
return a.x == b.x && a.y == b.y;
public static bool operator!=(Vec2 a, Vec2 b) {
return a.x != b.x || a.y != b.y;
public override string ToString() {
return "(" + x + ", " + y + ")";
public override int GetHashCode()
return x.GetHashCode() ^ (y.GetHashCode() << 2);
public override bool Equals(object o) {
return other.x == x && other.y == y;
public bool Equals(Vec2 other) {
return other.x == x && other.y == y;
public const char UNKNOWN = (char)0;
public const char EMPTY = '.';
public const char WALL = '#';
private List<Vec2> robotPositions = new List<Vec2>();
private Dictionary<char, Vec2> keys = new Dictionary<char, Vec2>();
private Dictionary<char, Vec2> doors = new Dictionary<char, Vec2>();
result.robotPositions.AddRange(robotPositions);
result.tiles = new char[tiles.Length];
Array.Copy(tiles, result.tiles, tiles.Length);
result.keys = new Dictionary<char, Vec2>(keys);
result.doors = new Dictionary<char, Vec2>(doors);
Vec2 pos = new Vec2(0, 0);
for (int i = 0; i < input.Length; ++i) {
public void SetRobotPosition(int index, Vec2 position) {
robotPositions[index] = position;
public void SetTile(Vec2 position, char tile) {
tiles[position.x - offset.x + (position.y - offset.y) * size.x] = tile;
public char GetTile(Vec2 position) {
if (position.x < 0 || position.y < 0)
if (position.x >= size.x || position.y >= size.y)
return tiles[position.x + position.y * size.x];
public Vec2 GetPosition(char c) {
if (doors.ContainsKey(c))
throw new Exception(c + " not found in map");
private void AddPosition(Vec2 newPosition) {
int newOffsetX = Math.Min(newPosition.x, offset.x);
int newOffsetY = Math.Min(newPosition.y, offset.y);
int newWidth = Math.Max(newPosition.x - newOffsetX + 1, size.x - newOffsetX + offset.x);
int newHeight = Math.Max(newPosition.y - newOffsetY + 1, size.y - newOffsetY + offset.y);
if (size.x >= newWidth && size.y >= newHeight && newOffsetX >= offset.x && newOffsetY >= offset.y)
char[] newTiles = new char[newWidth * newHeight];
for (int y = 0; y < size.y; ++y) {
for (int x = 0; x < size.x; ++x) {
newTiles[x + offset.x - newOffsetX + (y + offset.y - newOffsetY) * newWidth] = tiles[x + y * size.x];
for (int y = 0; y < size.y; ++y) {
for (int x = 0; x < size.x; ++x)
foreach (Vec2 robotPosition in robotPositions)
if ((robotPosition.x - offset.x) == x && (robotPosition.y - offset.y) == y) {
char c = tiles[x + y * size.x];
public void TakeKey(char c) {
throw new Exception(c + " is not a key");
char door = char.ToUpper(c);
public bool Exists(char c) {
return keys.ContainsKey(c) || doors.ContainsKey(c);
public void OpenDoor(char c) {
throw new Exception(c + " is not a key");
private static Dictionary<string, (int, List<char>)> keysToPath
= new Dictionary<string, (int, List<char>)>();
private static int level = 0;
public void FindKeyOrder(out int bestPathLength, List<char> path) {
var reachable = FindReachable(robotPositions, IsKey);
bestPathLength = int.MaxValue;
foreach (var kvp in reachable)
Console.WriteLine("Starting with key " + kvp.Key);
Vec2 position = GetPosition(kvp.Key);
int toKeyPath = GetPathLength(robotPositions[kvp.Value], position);
HashSet<char> keysLeft = new HashSet<char>(keys.Keys);
keysLeft.Remove(kvp.Key);
Vec2 tempRP = robotPositions[kvp.Value];
robotPositions[kvp.Value] = position;
string fingerprint = robotPositions.Join() + "-" + keysLeft.OrderBy(k => k).Join("");
robotPositions[kvp.Value] = tempRP;
(int, List<char>) lengthAndPath;
if (!keysToPath.TryGetValue(fingerprint, out lengthAndPath))
copy.SetRobotPosition(kvp.Value, position);
List<char> temp = new List<char>();
copy.FindKeyOrder(out int tempLength, temp);
lengthAndPath = (tempLength, temp);
keysToPath[fingerprint] = lengthAndPath;
int pathLength = lengthAndPath.Item1 + toKeyPath;
if (pathLength < bestPathLength) {
path.AddRange(lengthAndPath.Item2);
bestPathLength = pathLength;
private bool IsDoor(char c)
return c >= 'A' && c <= 'Z';
private bool IsKey(char c)
return c >= 'a' && c <= 'z';
private Dictionary<char, int> FindReachable(IList<Vec2> source, Func<char, bool> criteria)
Dictionary<char, int> result = new Dictionary<char, int>();
for (int i = 0; i < source.Count; i++)
Dictionary<char, int> reachable = FindReachable(s, criteria);
foreach (var kvp in reachable)
private Dictionary<char, int> FindReachable(Vec2 source, Func<char, bool> criteria) {
HashSet<Vec2> visited = new HashSet<Vec2>();
HashSet<Vec2> openSet = new HashSet<Vec2>();
HashSet<Vec2> newOpenSet = new HashSet<Vec2>();
Dictionary<char, int> result = new Dictionary<char, int>();
while (openSet.Count > 0) {
foreach (Vec2 v in openSet) {
if (!result.ContainsKey(c))
for (int i = 0; i < 4; ++i) {
Vec2 candidate = v + (Direction)i;
if (visited.Contains(candidate))
newOpenSet.Add(candidate);
openSet.UnionWith(newOpenSet);
private bool CanWalkOn(char c) {
if (c >= 'a' && c <= 'z')
public int GetPathLength(Vec2 source, Vec2 target) {
List<Vec2> path = new List<Vec2>();
if (!FindPath(source, target, path)) {
public int GetPathLength(Vec2 source, IEnumerable<Vec2> targets) {
List<Vec2> path = new List<Vec2>();
foreach (Vec2 target in targets) {
if (!FindPath(source, target, path)) {
public bool FindPath(Vec2 source, Vec2 target, List<Vec2> path) {
Dictionary<Vec2, Vec2> cameFrom = new Dictionary<Vec2, Vec2>();
Dictionary<Vec2, int> gScore = new Dictionary<Vec2, int>();
Dictionary<Vec2, int> fScore = new Dictionary<Vec2, int>();
HashSet<Vec2> openSet = new HashSet<Vec2>();
fScore[source] = source.GetManhattan(target);
if (gScore.TryGetValue(v, out int s)) {
while (openSet.Count > 0) {
int lScore = int.MaxValue;
foreach (Vec2 v in openSet) {
if (v.GetManhattan(target) < lScore) {
lScore = v.GetManhattan(target);
current = cameFrom[current];
int gScoreCurrent = GetGScore(current);
for (int i = 0; i < 4; ++i) {
Direction d = (Direction)i;
Vec2 neighbour = current + d;
if (!CanWalkOn(GetTile(neighbour)) && neighbour != target)
int tScore = gScoreCurrent + 1;
if (tScore < GetGScore(neighbour)) {
cameFrom[neighbour] = current;
gScore[neighbour] = tScore;
fScore[neighbour] = tScore + neighbour.GetManhattan(target);
public static class Extensions {
public static void Swap<T>(this IList<T> l, int indexA, int indexB) {
public static string Join<T>(this IEnumerable<T> input, string separator = ", ") {
return string.Join(separator, input);
public static List<List<T>> GetPermutations<T>(this IEnumerable<T> input) {
List<T> A = new List<T>(input);
List<List<T>> result = new List<List<T>>();
public static string EXAMPLE1 = @"#########
public static string EXAMPLE2 = @"########################
########################";
public static string EXAMPLE3 = @"#############
public static string EXAMPLE5 = @"########################
########################";
public static string INPUT1 = @"#################################################################################
#.......#.A...........#.........#.......#.#.........#.............#...#..r......#
#.###.###.#####.#####.#.#######.#.#######.#.#.#####.#.#.#.#######.###.#.###.###.#
#...#.#...#.....#.#...#...#.....#.......#...#.#...#o#.#.#.#...#.#...#.#...#.#...#
#####.#.###.#####.#.###.#W###.#########.#####.#.#.###.#.#.#.#.#.###.#K###.#.#####
#.....#.#.#...#...#...#.#...#...........#...#...#.....#.#.#.#.#.#...#...#.#.....#
#M###.#.#.###.#.#####.#####.###########.#.#.###.#######.###.#.#.#.#####.#.#####.#
#.#...#...#...#.#...#.....#...#..z....#.#.#...#...#.....#...#.#.#.#...#.......#.#
#.###.###.#.###.#.#.#####.###.#.###.#.#.#.###.#####.#.###.###.#.#.#.#.#####.###.#
#...#...#.#.#....y#.....#.....#.#.#.#.#.#...#.#...#.#.#...#...#.#...#.#...#.#m..#
#.#.#####.#.###########.#######.#.#.#.#.###.#.#.#X#.#.#.###.###.#####.#.#.###.###
#.#.#...#.#s..#.......#.......#...#.#.#.#...#...#.#.#.#.#.#.#.......#...#...#...#
###.#.#.#.###.#.#####.###.###.#####.#.#.#.#######.#.###.#.#.#.#####.#######.###.#
#...#.#...#.#...#...#.#...#.......#.#.#.#.#.......#.....#.#.#.#.....#.....#.....#
#.###.#####.#####.#.#C#.###.#####.#.#.#.#.#####.###.#####.#.###.#####.#.#.#####.#
#.....#.....#.....#.#.#.#...#...#...#.#.#.#.F.#...#...#...#...#.#...#.#.#.....#.#
#.#######.#.###.###.#.#.#####.#.#######.#.#.#.###.###.###.###.#.#.#.#.#.#######.#
#.#.......#...#.#...#.#...#...#.#.......#...#.#.#...#.......#.#.#.#.#.#.........#
#.#.#########.#.#####.###N#.###.#.###########.#.###.#########.#.#.#.#.###########
#...#...#.......#.....#...#.#.#.#.......#...#.#...............#...#.#.#....q....#
#####.###.#######.#####.###.#.#.#######.#.#.#.#############.#####.#.#.#.#.#####.#
#g..#.....#.....#...#.#...#...#.......#.#.#.#..l..........#.#...#.#.#.#.#...#...#
###.#.#####.###.###.#T#.#.###.###.#####.###.#############.#####B#.#.#.#.###.#####
#...#.#...#...#.....#.#.#...#.#.#.#...#.#.......#.......#...#...#.#...#...#.....#
#.###.###.###.#####.#.###.###.#.#.#.#.#.#.#####.#.###.#####.#.###.#####.#######.#
#...#...#...#.#.#...#...#.I...#.#...#...#.....#.#...#.#...#...#.#...#.#.#.......#
###.###.#.###.#.#.#####.#####.#.#############.#####.#.#.#.#####.###.#.#.#.#######
#.....#.#...#.#.......#.#...#...........#.....#.....#...#.......#.#.#.#.#.......#
#.#####.###.#.#######.#.#.#.#####.#######.###.#.###########.###.#.#.#.#.#######.#
#...........#.#e....#.#...#...#...#.....#.#...#...#.........#.....#.#...#.......#
#.###########.#.###.#########.#####.###.#.#######.#.#####.#######.#.#####.#####.#
#.....#.#.....#.#.#.........#.......#...#.#.......#.#.....#.....#.#...#...#.#...#
#####.#.#.#####.#.#####.#.###########.###.#.#######.#####.#.###.#.###.#.###.#.###
#...#.#.#.......#.#.....#.#.........#.#.#...#.#.....#...#.#.#...#...#.#...#...#.#
#.###.#.#########.#.#####.#V#.#####.#.#.#.###.#.###.#.#.###.#.#######.###.#.###.#
#.#...#.....#.....#.#.....#.#...#...#.#.#.#...#.#.#.#.#.....#.........#...#.#...#
#.#.###.###.#.#####.#######.###.#.###.#.#.###.#.#.#.#.#################.###.#.#.#
#.#.....#.#.#.....#.......#.#.#.#...#.#.#.#...#.#...#.#.........#.......#.S.#.#.#
#.#######.#.#####.#######.#.#.#.#####.#.#.#.#.#.#####.#####.###.#.#######.###.#.#
#.......................#.....#.............#.#.............#.....#...........#.#
#######################################.@.#######################################
#...............#.....#.....#.............#.........................D.......#..u#
#.#############.#####.#.#.###.###.#####.#.#.#.#####.#######.###############.#.###
#.....#.....#...#...#...#.....#.#.#.....#...#....v#.#.....#.#.......#.....#.#.E.#
#####.#.#####.###.#.#.#########.#.#######.#######.###.###.###.#####.#.#####.#.#.#
#.....#.....#.....#.#.#...#.....#.......#.#.......#.....#.#...#...#.#....j#t#.#.#
#.#########.#######.#.#.#.#.###########.#.#.#######.#####.#.###.###.#####.#.#.#.#
#.......#...#...#...#...#...#.......#...#.#.#.....#.#.....#.#.....#.#...#.#.#.#.#
#######.#.#.###.#.#######.###.#####.#.#####.#.###.#.#.#####.#####.#.#.#.#.#.###.#
#.....#.#.#.....#...#.....#...#.....#...#...#.#.#...#.....#.......#...#.#.#.#...#
###.###.#.#####.###.#####.#.###.#####.#.#.#.#.#.#########.#######.#####.#.#.#.#.#
#...#...#...#...#.#.....#.#.#.#.#.....#.#.#d#.#.....#.......#.....#.....#.#...#.#
#.###.#####.#.###.#####.#.#.#.#.#######.#.###.###.#.#.#######.#####.#####.#####.#
#.....#...#.#.....#.....#.#.#.#...#.....#.....#...#.#.....#.....#...#...#.....#.#
#.#####.#.#.#.#####.#####.#.#.###.#.###.#######.#.#######.#.#####.#####.#.#.#.#.#
#.#.....#.#.#.#.....#.....#.#...#.#.#...#.......#.#.....#...#.#...#.....#.#.#.#.#
#.###.#.#.#.#.#.###########.###.#.#.#.###.#########.#.#######.#.#####.###.#.###.#
#.H.#.#.#.#.#.#.....#.....#.#...#...#...#.#.....#...#.........#.#.....#...#.....#
###.###.#.#.#.#####.#.###.#.#.#########.#.#.###.#.#######.#####.#.#.#.#.#########
#.#.#...#...#...#.#...#...#.#...#.......#...#.#...#.....#...#...#.#.#.#.........#
#.#.#.#.#######.#.#####.###.#.#.#.#######.###.#########.###.#.#####.#.#########.#
#...#.#.#...#.#.#...#...#...#.#.#...#...#...#...#.....#...#.#.#.....#.#.......#.#
#.###.###.#.#.#.###.#######.#.#.###.#.#.###.#.###.#.#.#.#.#.###.#####.###.###.#.#
#.#...#...#.#.#.#...........#.#...#.#.#.#.#.#.#...#.#...#.#.....#...#...#.#.#.#.#
#.###.#.###.#.#.#.###########.###.#.#.#.#.#.#.#.###.#####.#####.###.###.#.#.#.#.#
#...#...#.#.#.#...#...#.U...#.#.#...#.#.#...#.....#.#.....#...#...#...#...#...#.#
###.#.###.#.#.#####J#.#.#.###.#.#####.###.#######.#.#####.#.#####.#.#####.#####.#
#...#.Q.#.#.#.....#.#...#.....#.........#.......#.#f....#.L.#.....#h....#.#...#.#
#.#####.#.#.###.#.#.#################.#.#######.#.#####.###.#.#####.#.###.#.#.#.#
#.#...#...#...#.#.#.#...#.......#...#.#.#.#...G.#.....#.Z.#.#...#...#.....#.#...#
#.#.#####.###.###.#.#.#.#####.#.#.#.###.#.#.#############.#.###.#########.#.#####
#k#.#.....#.#...#.#..c#...#...#...#.#...#.#.#........n#...#...#.#.......#.#...#.#
#.#.#.#####.###.#.#######.#.#######.#.#.#.#.#.#######.#.###.###.#.#####.#####.#.#
#.#...#.....#...#.#.P...#.#.#.....#...#.#.#.#.#...#...#.#...#...#.....#.....#p..#
#.###.#.#.###.###.#.#.###.#.###.#.#####.#.#.#.#.###.###.###.#.#######.###.#####.#
#...#...#.#...#.#...#...#.#...#.#...#...#.O.#.#.....#.#...#b#.#.......#.#.#...#.#
###.#####.#.###.#.#####.#.###.#####.#.###.###.#.#####.#.#.###.#.#######.#.#.#.#.#
#.#.#.....#.#a..#.#...#.#.#...#.....#...#...#i#.#...#...#.Y.#.#.#....w..#.#.#...#
#.#R#######.#.#.#.###.#.#.#.###.#######.###.#.#.#.#.#######.#.#.#####.#.#.#.#####
#...........#.#.......#.....#...........#.....#x..#.........#.........#.#.......#
#################################################################################";
public static string INPUT2 = @"#################################################################################
#.......#.A...........#.........#.......#.#.........#.............#...#..r......#
#.###.###.#####.#####.#.#######.#.#######.#.#.#####.#.#.#.#######.###.#.###.###.#
#...#.#...#.....#.#...#...#.....#.......#...#.#...#o#.#.#.#...#.#...#.#...#.#...#
#####.#.###.#####.#.###.#W###.#########.#####.#.#.###.#.#.#.#.#.###.#K###.#.#####
#.....#.#.#...#...#...#.#...#...........#...#...#.....#.#.#.#.#.#...#...#.#.....#
#M###.#.#.###.#.#####.#####.###########.#.#.###.#######.###.#.#.#.#####.#.#####.#
#.#...#...#...#.#...#.....#...#..z....#.#.#...#...#.....#...#.#.#.#...#.......#.#
#.###.###.#.###.#.#.#####.###.#.###.#.#.#.###.#####.#.###.###.#.#.#.#.#####.###.#
#...#...#.#.#....y#.....#.....#.#.#.#.#.#...#.#...#.#.#...#...#.#...#.#...#.#m..#
#.#.#####.#.###########.#######.#.#.#.#.###.#.#.#X#.#.#.###.###.#####.#.#.###.###
#.#.#...#.#s..#.......#.......#...#.#.#.#...#...#.#.#.#.#.#.#.......#...#...#...#
###.#.#.#.###.#.#####.###.###.#####.#.#.#.#######.#.###.#.#.#.#####.#######.###.#
#...#.#...#.#...#...#.#...#.......#.#.#.#.#.......#.....#.#.#.#.....#.....#.....#
#.###.#####.#####.#.#C#.###.#####.#.#.#.#.#####.###.#####.#.###.#####.#.#.#####.#
#.....#.....#.....#.#.#.#...#...#...#.#.#.#.F.#...#...#...#...#.#...#.#.#.....#.#
#.#######.#.###.###.#.#.#####.#.#######.#.#.#.###.###.###.###.#.#.#.#.#.#######.#
#.#.......#...#.#...#.#...#...#.#.......#...#.#.#...#.......#.#.#.#.#.#.........#
#.#.#########.#.#####.###N#.###.#.###########.#.###.#########.#.#.#.#.###########
#...#...#.......#.....#...#.#.#.#.......#...#.#...............#...#.#.#....q....#
#####.###.#######.#####.###.#.#.#######.#.#.#.#############.#####.#.#.#.#.#####.#
#g..#.....#.....#...#.#...#...#.......#.#.#.#..l..........#.#...#.#.#.#.#...#...#
###.#.#####.###.###.#T#.#.###.###.#####.###.#############.#####B#.#.#.#.###.#####
#...#.#...#...#.....#.#.#...#.#.#.#...#.#.......#.......#...#...#.#...#...#.....#
#.###.###.###.#####.#.###.###.#.#.#.#.#.#.#####.#.###.#####.#.###.#####.#######.#
#...#...#...#.#.#...#...#.I...#.#...#...#.....#.#...#.#...#...#.#...#.#.#.......#
###.###.#.###.#.#.#####.#####.#.#############.#####.#.#.#.#####.###.#.#.#.#######
#.....#.#...#.#.......#.#...#...........#.....#.....#...#.......#.#.#.#.#.......#
#.#####.###.#.#######.#.#.#.#####.#######.###.#.###########.###.#.#.#.#.#######.#
#...........#.#e....#.#...#...#...#.....#.#...#...#.........#.....#.#...#.......#
#.###########.#.###.#########.#####.###.#.#######.#.#####.#######.#.#####.#####.#
#.....#.#.....#.#.#.........#.......#...#.#.......#.#.....#.....#.#...#...#.#...#
#####.#.#.#####.#.#####.#.###########.###.#.#######.#####.#.###.#.###.#.###.#.###
#...#.#.#.......#.#.....#.#.........#.#.#...#.#.....#...#.#.#...#...#.#...#...#.#
#.###.#.#########.#.#####.#V#.#####.#.#.#.###.#.###.#.#.###.#.#######.###.#.###.#
#.#...#.....#.....#.#.....#.#...#...#.#.#.#...#.#.#.#.#.....#.........#...#.#...#
#.#.###.###.#.#####.#######.###.#.###.#.#.###.#.#.#.#.#################.###.#.#.#
#.#.....#.#.#.....#.......#.#.#.#...#.#.#.#...#.#...#.#.........#.......#.S.#.#.#
#.#######.#.#####.#######.#.#.#.#####.#.#.#.#.#.#####.#####.###.#.#######.###.#.#
#.......................#.....#........@#@..#.#.............#.....#...........#.#
#################################################################################
#...............#.....#.....#..........@#@#.........................D.......#..u#
#.#############.#####.#.#.###.###.#####.#.#.#.#####.#######.###############.#.###
#.....#.....#...#...#...#.....#.#.#.....#...#....v#.#.....#.#.......#.....#.#.E.#
#####.#.#####.###.#.#.#########.#.#######.#######.###.###.###.#####.#.#####.#.#.#
#.....#.....#.....#.#.#...#.....#.......#.#.......#.....#.#...#...#.#....j#t#.#.#
#.#########.#######.#.#.#.#.###########.#.#.#######.#####.#.###.###.#####.#.#.#.#
#.......#...#...#...#...#...#.......#...#.#.#.....#.#.....#.#.....#.#...#.#.#.#.#
#######.#.#.###.#.#######.###.#####.#.#####.#.###.#.#.#####.#####.#.#.#.#.#.###.#
#.....#.#.#.....#...#.....#...#.....#...#...#.#.#...#.....#.......#...#.#.#.#...#
###.###.#.#####.###.#####.#.###.#####.#.#.#.#.#.#########.#######.#####.#.#.#.#.#
#...#...#...#...#.#.....#.#.#.#.#.....#.#.#d#.#.....#.......#.....#.....#.#...#.#
#.###.#####.#.###.#####.#.#.#.#.#######.#.###.###.#.#.#######.#####.#####.#####.#
#.....#...#.#.....#.....#.#.#.#...#.....#.....#...#.#.....#.....#...#...#.....#.#
#.#####.#.#.#.#####.#####.#.#.###.#.###.#######.#.#######.#.#####.#####.#.#.#.#.#
#.#.....#.#.#.#.....#.....#.#...#.#.#...#.......#.#.....#...#.#...#.....#.#.#.#.#
#.###.#.#.#.#.#.###########.###.#.#.#.###.#########.#.#######.#.#####.###.#.###.#
#.H.#.#.#.#.#.#.....#.....#.#...#...#...#.#.....#...#.........#.#.....#...#.....#
###.###.#.#.#.#####.#.###.#.#.#########.#.#.###.#.#######.#####.#.#.#.#.#########
#.#.#...#...#...#.#...#...#.#...#.......#...#.#...#.....#...#...#.#.#.#.........#
#.#.#.#.#######.#.#####.###.#.#.#.#######.###.#########.###.#.#####.#.#########.#
#...#.#.#...#.#.#...#...#...#.#.#...#...#...#...#.....#...#.#.#.....#.#.......#.#
#.###.###.#.#.#.###.#######.#.#.###.#.#.###.#.###.#.#.#.#.#.###.#####.###.###.#.#
#.#...#...#.#.#.#...........#.#...#.#.#.#.#.#.#...#.#...#.#.....#...#...#.#.#.#.#
#.###.#.###.#.#.#.###########.###.#.#.#.#.#.#.#.###.#####.#####.###.###.#.#.#.#.#
#...#...#.#.#.#...#...#.U...#.#.#...#.#.#...#.....#.#.....#...#...#...#...#...#.#
###.#.###.#.#.#####J#.#.#.###.#.#####.###.#######.#.#####.#.#####.#.#####.#####.#
#...#.Q.#.#.#.....#.#...#.....#.........#.......#.#f....#.L.#.....#h....#.#...#.#
#.#####.#.#.###.#.#.#################.#.#######.#.#####.###.#.#####.#.###.#.#.#.#
#.#...#...#...#.#.#.#...#.......#...#.#.#.#...G.#.....#.Z.#.#...#...#.....#.#...#
#.#.#####.###.###.#.#.#.#####.#.#.#.###.#.#.#############.#.###.#########.#.#####
#k#.#.....#.#...#.#..c#...#...#...#.#...#.#.#........n#...#...#.#.......#.#...#.#
#.#.#.#####.###.#.#######.#.#######.#.#.#.#.#.#######.#.###.###.#.#####.#####.#.#
#.#...#.....#...#.#.P...#.#.#.....#...#.#.#.#.#...#...#.#...#...#.....#.....#p..#
#.###.#.#.###.###.#.#.###.#.###.#.#####.#.#.#.#.###.###.###.#.#######.###.#####.#
#...#...#.#...#.#...#...#.#...#.#...#...#.O.#.#.....#.#...#b#.#.......#.#.#...#.#
###.#####.#.###.#.#####.#.###.#####.#.###.###.#.#####.#.#.###.#.#######.#.#.#.#.#
#.#.#.....#.#a..#.#...#.#.#...#.....#...#...#i#.#...#...#.Y.#.#.#....w..#.#.#...#
#.#R#######.#.#.#.###.#.#.#.###.#######.###.#.#.#.#.#######.#.#.#####.#.#.#.#####
#...........#.#.......#.....#...........#.....#x..#.........#.........#.#.......#
#################################################################################";