import java.lang.RuntimeException

fun main() {
    val maze = mutableMapOf<Coord, Maze>()

    val input = mutableMapOf<Coord, String>()
    INPUT20.split("\n")
        .forEachIndexed { i, row ->
            row.split("").filter { it != "" }.forEachIndexed { j, cell ->
                val coord = Coord(j, i)
                input[coord] = cell
            }
        }
    input.forEach { coord, cell ->
        when (cell) {
            "#" -> maze[coord] = Maze(coord, MazeWall())
            "." -> maze[coord] = Maze(coord, MazeHall())
            else -> maze[coord] = Maze(coord, MazeNothing())
        }
    }

    input.forEach { coord, cell ->
        if (isLetter(cell)) {
            val (label, portalCoord) = readLabel(input, cell, coord)
            maze[portalCoord] = Maze(portalCoord, MazePortal(label, if (isOuter(coord, input)) -1 else 1))
        }
    }

    val mazePortals = maze.filter { it.value.mazeBlock is MazePortal }
    mazePortals
        .forEach { mazePortal ->
            maze.filter { it.value.mazeBlock is MazePortal }
                .filter { it != mazePortal }
                .filter { (it.value.mazeBlock as MazePortal).label == (mazePortal.value.mazeBlock as MazePortal).label }
                .forEach { (it.value.mazeBlock as MazePortal).portsTo = mazePortal.key }
        }
    maze.values.forEach {
        val validNeighbours = mutableListOf<Pair<Maze, Int>>()
        processMazeNeighbour(it.coord.north(), maze, validNeighbours)
        processMazeNeighbour(it.coord.south(), maze, validNeighbours)
        processMazeNeighbour(it.coord.east(), maze, validNeighbours)
        processMazeNeighbour(it.coord.west(), maze, validNeighbours)
        val current = maze[it.coord]!!.mazeBlock
        if (current is MazePortal) {
            if (current.portsTo != null) {
                validNeighbours.add(Pair(maze[current.portsTo!!]!!, current.levelChange))
            }
        }
        it.validNeighbors = validNeighbours
    }

    val start = maze.values.first { it.mazeBlock is MazePortal && it.mazeBlock.label == "AA" }.also { (it.mazeBlock as MazePortal).levelChange = 0 }
    val end = maze.values.first { it.mazeBlock is MazePortal && it.mazeBlock.label == "ZZ" }.also { (it.mazeBlock as MazePortal).levelChange = 0 }

    processMazeBlock(start, 0, 0)

    println("second result")
    println(end.steps[0])
}

fun isOuter(coord: Coord, input: MutableMap<Coord, String>): Boolean {
    val maxX = input.keys.maxBy { it.x }!!.x
    val maxY = input.keys.maxBy { it.y }!!.y

    val minX = input.keys.minBy { it.x }!!.x
    val minY = input.keys.minBy { it.y }!!.y

    return coord.x == maxX || coord.x == maxX - 1 || coord.x == minX || coord.x == minX + 1 || coord.y == maxY || coord.y == maxY - 1 || coord.y == minY || coord.y == minY + 1
}

fun processMazeBlock(current: Maze, steps: Int, level: Int) {
    if (level < 0 || level > 30) {
        return
    }
    if (current.mazeBlock is MazePortal) {
        println("Walking through ${current.mazeBlock.label} on level $level with $steps steps")
    }

    current.steps[level] = steps

    current.validNeighbors
        .filter { it.first.steps[level + it.second] ?: Int.MAX_VALUE > steps }
        .forEach { processMazeBlock(it.first, steps + 1, level + it.second) }
}

fun getLevelChange(it: Maze): Int {
    return if (it.mazeBlock is MazePortal) {
        it.mazeBlock.levelChange
    } else {
        0
    }
}

fun processMazeNeighbour(coord: Coord, maze: MutableMap<Coord, Maze>, validNeighbors: MutableList<Pair<Maze, Int>>) {
    val block = maze[coord] ?: return
    when (block.mazeBlock) {
        is MazeWall -> return
        is MazeNothing -> return
    }
    validNeighbors.add(Pair(block, 0))
}

private fun readLabel(input: Map<Coord, String>, cell: String, coord: Coord): Pair<String, Coord> {
    if (isLetter(input[coord.north()])) {
        if (input[coord.south()] == ".") {
            return Pair(input[coord.north()] + cell, coord.south())
        } else {
            return Pair(input[coord.north()] + cell, coord.north().north())
        }
    } else if (isLetter(input[coord.south()])) {
        if (input[coord.south().south()] == ".") {
            return Pair(cell + input[coord.south()], coord.south().south())
        } else {
            return Pair(cell + input[coord.south()], coord.north())
        }
    } else if (isLetter(input[coord.west()])) {
        if (input[coord.west().west()] == ".") {
            return Pair(input[coord.west()] + cell, coord.west().west())
        } else {
            return Pair(input[coord.west()] + cell, coord.east())
        }
    } else if (isLetter(input[coord.east()])) {
        if (input[coord.west()] == ".") {
            return Pair(cell + input[coord.east()], coord.west())
        } else {
            return Pair(cell + input[coord.east()], coord.east().east())
        }
    } else {
        throw RuntimeException()
    }
}


private fun isLetter(cell: String?): Boolean {
    if (cell == null) {
        return false;
    }
    return cell.toLowerCase() != cell
}

data class Maze(val coord: Coord, val mazeBlock: MazeBlock) {
    var validNeighbors = mutableListOf<Pair<Maze, Int>>()
    var steps = mutableMapOf<Int, Int>()
}

sealed class MazeBlock(val char: Char)

class MazeNothing : MazeBlock(' ')
class MazeWall : MazeBlock('#')
class MazeHall : MazeBlock('.')
class MazePortal(val label: String, var levelChange: Int) : MazeBlock('.') {
    var portsTo: Coord? = null
    override fun toString(): String {
        return "MazePortal(label='$label', levelChange=$levelChange, portsTo=$portsTo)"
    }


}

const val TEST201 = """
         A           
         A           
  #######.#########  
  #######.........#  
  #######.#######.#  
  #######.#######.#  
  #######.#######.#  
  #####  B    ###.#  
BC...##  C    ###.#  
  ##.##       ###.#  
  ##...DE  F  ###.#  
  #####    G  ###.#  
  #########.#####.#  
DE..#######...###.#  
  #.#########.###.#  
FG..#########.....#  
  ###########.#####  
             Z       
             Z       """

const val TEST202 = """
             Z L X W       C                 
             Z P Q B       K                 
  ###########.#.#.#.#######.###############  
  #...#.......#.#.......#.#.......#.#.#...#  
  ###.#.#.#.#.#.#.#.###.#.#.#######.#.#.###  
  #.#...#.#.#...#.#.#...#...#...#.#.......#  
  #.###.#######.###.###.#.###.###.#.#######  
  #...#.......#.#...#...#.............#...#  
  #.#########.#######.#.#######.#######.###  
  #...#.#    F       R I       Z    #.#.#.#  
  #.###.#    D       E C       H    #.#.#.#  
  #.#...#                           #...#.#  
  #.###.#                           #.###.#  
  #.#....OA                       WB..#.#..ZH
  #.###.#                           #.#.#.#  
CJ......#                           #.....#  
  #######                           #######  
  #.#....CK                         #......IC
  #.###.#                           #.###.#  
  #.....#                           #...#.#  
  ###.###                           #.#.#.#  
XF....#.#                         RF..#.#.#  
  #####.#                           #######  
  #......CJ                       NM..#...#  
  ###.#.#                           #.###.#  
RE....#.#                           #......RF
  ###.###        X   X       L      #.#.#.#  
  #.....#        F   Q       P      #.#.#.#  
  ###.###########.###.#######.#########.###  
  #.....#...#.....#.......#...#.....#.#...#  
  #####.#.###.#######.#######.###.###.#.#.#  
  #.......#.......#.#.#.#.#...#...#...#.#.#  
  #####.###.#####.#.#.#.#.###.###.#.###.###  
  #.......#.....#.#...#...............#...#  
  #############.#.#.###.###################  
               A O F   N                     
               A A D   M                     """

const val INPUT20 = """
                                       I           N S       T       Q     I         K                                         
                                       W           P J       E       O     K         E                                         
  #####################################.###########.#.#######.#######.#####.#########.#######################################  
  #.#.#.....#...#.#...........#.#.#.....#.#.........#.......#...#.........#.#.....#...#.......#.........#.......#.......#...#  
  #.#.#####.###.#.###.#.#.###.#.#.#####.#.#####.#####.#####.#.#.###.#####.#.#.###.#.###.#.###.#.###.#######.###.###.#######.#  
  #...........#...#.#.#.#.#.........#...#.....#.....#...#...#.#.#.#...#...#.....#.#.....#...#.#.#.#...#.#...#.#.#.#.........#  
  ###########.#.###.#######.###.###.###.#.#.###.###########.###.#.###.#########.#.#######.#####.#.#.#.#.#.###.###.#.###.###.#  
  #...#.#.#.......#...#.#...#...#.#...#.#.#.#.....#.#.....#...#...#...#.#.....#.#.#.......#.......#.#.#...#.#...#.#...#.#...#  
  ###.#.#.###.###.#.###.#########.###.#.#.#####.###.#####.#.###.#.#.###.###.#.###.#.#########.###.#####.###.#.#.#.#.#######.#  
  #...#.#.....#...#.....#.#.....#...........#.#.........#.....#.#.#.#.....#.#.....#.............#.#.......#.#.#.#.#.......#.#  
  ###.#.#########.###.###.#.#.#.#.###.#####.#.#.#.#######.#####.#.#.#.#.###.###.#########.#.#.#.#####.#####.###.#.#.#####.#.#  
  #.......#...............#.#.#...#.#.#...#...#.#.....#.....#.#.#.#.#.#...#.#.#.#...#...#.#.#.#.#.....#.......#.........#.#.#  
  #####.###########.#.#.###########.#####.###.###.###.#####.#.###.#.#.###.#.#.#.###.###.#.#######.#.#####.#####.#############  
  #.....#...#...#.#.#.#.#.#.#.........#.......#.....#.#.......#.#.#...#...#...#.#.....#...#.......#.....#.#.#.........#.....#  
  #####.###.###.#.###.###.#.#######.###.#######.#.#.#######.###.#.###.#.#####.#####.#.#.###.#####.#.###.#.#.#.#####.#####.###  
  #.#...........#.............................#.#.#.......#.#.....#...#.....#.....#.#.#.....#...#.#...#.........#.#...#.....#  
  #.#.#.#.#.###.#.#.#####.###.#.#.#####.#####.#.###.#######.#.###.#.#.###.#####.#.#.#.###.#.#.###.#######.#.#.###.#######.###  
  #.#.#.#.#...#.#.#.#.....#.#.#.#.#.......#...#...#...#.....#...#.#.#.#.#...#...#.#.#.....#.....#.#...#...#.#.........#.....#  
  #.#######.#######.###.###.###.#####.###.###.#.#####.#.#.#.#.#####.###.#.#######.#.#.#.#######.###.#####.###.#####.###.#.#.#  
  #.#...#...#.#.#.#...#.#.......#.....#...#.#.#.#.#.#.#.#.#.#.....#.#.#.#.#.......#.#.#.......#.........#.#...#.......#.#.#.#  
  #.#.#####.#.#.#.###############.###.#####.#.#.#.#.###.###.#.#####.#.#.#.###.#.#.#.#####.#.###.#.#####.#################.#.#  
  #...#.#...#.....#.#.#.....#.#.....#.#.......#.....#...#...#.....#.#.....#.#.#.#.#...#...#...#.#...#.....#...#...#.#.#.#.#.#  
  ###.#.###.###.###.#.#.###.#.###.#######.###.###.#.#######.#.###########.#.#####.#.#########.###.#########.#####.#.#.#.###.#  
  #.#.....#.#...#.....#.#.#...........#.#.#.#...#.#.#...#...#.....#...#...#.....#.#...#.....#.#.#.#.......#.#.#...#...#.#...#  
  #.###.###.#.###.#.#####.#######.#.###.###.#.###.#.###.###.#.#.#.#.#####.###.###.#.#######.###.#####.#.###.#.#.###.###.###.#  
  #.............#.#.#.#.....#.....#.#.........#...#.#.......#.#.#.#.....#.#.....#.#...#...#.....#.#.#.#.....#.#.#...#...#...#  
  ###.#.#####.#####.#.#.###################.###.#########.###.#####.#.#.#.#.###.#.###.#.###.#####.#.###.#####.#.###.###.###.#  
  #...#...#.#.#.......#.#...#.#...#.....#.#...#...#.#.......#.....#.#.#...#.#...#...#.......#.#.#.....#...#...#...#...#...#.#  
  #####.#.#.#.#####.#.#.###.#.#.#######.#.###.#.###.#.#####.#.###########.#.#.###.###.###.###.#.#.#####.#####.###.#.###.###.#  
  #...#.#...#.#.....#.#...#.................#.#.....#.#...#.#.....#...#...#.#.....#...#...#.#.#.....#.#...#.....#.....#.#...#  
  #.#####.#######.#.#.#.###.###########.###.#.###.#######.#.#.#####.#####.#.###.#.#.#.#.#.#.#.#.###.#.#.#####.###.#.###.###.#  
  #...#.#.#.#...#.#.#.#...#.#.....#.#.....#.....#...#...#...#...#.#.....#.#.#.#.#.#.#.#.#.........#.#...#.......#.#.......#.#  
  ###.#.#.#.###.###.###.###.#####.#.#####.###.#####.###.###.#.###.#.#.###.#.#.#.#.###.###.###.#.#######.###.#########.#####.#  
  #.....#...#.#.#.#...#.#.#.#.....#.........#.#.....#.......#.#.....#.....#.#...#.#...#.....#.#.#.#...#...#...#.#.........#.#  
  ###.#.#.#.#.#.#.###.#.#.#######.#####.#########.#######.###.#####.#######.###########.#####.###.#.###.###.###.###.###.###.#  
  #...#.#.#.#.#...........#...#...#    N         P       N   C     I       D           K    #.#.#...#.......#.#...#.#.#.....#  
  ###.###.###.#.#####.#####.#.###.#    K         E       P   J     E       B           N    ###.###.###.#####.#.#####.###.#.#  
NW....#.........#.#.#...#...#.#...#                                                         #...#.....#.....#.....#.#...#.#.#  
  ###.#.#####.###.#.#######.#####.#                                                         #.#.###.#.#.#.#####.#.#.#.#####.#  
  #.....#.....#.#.#.#.#.#.#.#.#....DF                                                       #.#.#.#.#...#...#...#.#.....#....ZM
  #####.#.#####.#.#.#.#.#.#.#.###.#                                                         ###.#.#.#####.#####.###.#######.#  
  #.....#.#...#.....#.....#.#.#...#                                                       VI....#...#.#...#.#.......#.#.#.#.#  
  #######.#.#.#.###.###.#.#.#.###.#                                                         #.#.#.###.#.###.###.###.#.#.#.#.#  
  #.#.#.....#...#.......#.........#                                                         #.#...#.#.............#.........#  
  #.#.#.###.#.#.#.#####.#####.#####                                                         #####.#.###.#.###.#.###.#########  
RY....#.#.#.#.#.#.#...#.#.#.#.#....TE                                                       #...#.#...#.#.#...#.#...#.......#  
  #.#####.#########.#####.#.###.#.#                                                         #.#.###.###########.#######.###.#  
  #...#.....#.....#.#.#.......#.#.#                                                       CN..#.........#.....#.#.#.....#...#  
  #.#.#.###.###.###.#.#.###.#####.#                                                         #####.###########.###.#.#.###.###  
  #.#...#.................#.......#                                                         #.#.#...#.#...#.#...#...#.#...#..AS
  #####################.#.#######.#                                                         #.#.#.###.#.###.#.#####.###.###.#  
CT....#.....#.......#...#...#.#.#.#                                                         #.........................#.....#  
  ###.#.###.###.#.#.#######.#.#.###                                                         ###.#.#############.#.#.###.#.###  
  #...#...#...#.#.#.#.#...#.#......DN                                                       #...#.#.......#.#...#.#.#...#.#.#  
  #.#####.###.#.#.###.###.###.#####                                                         #########.###.#.#####.#########.#  
  #.....#.#...#.#...........#.#...#                                                         #...#.#.....#...#...#...#...#.#..CJ
  ###.###.###.#.#.#.###.#.#.#.###.#                                                         ###.#.#####.#.#####.#.#####.#.#.#  
  #.......#.....#.#...#.#.#...#...#                                                       NW....#.....#.#.#.....#.#.........#  
  ###############.#####.#######.###                                                         #.#.#.###.#.#.#####.#####.#####.#  
  #...........#.#...#.#...#.....#.#                                                         #.#...#.#...#...............#.#.#  
  #.###.#.#####.#####.#####.###.#.#                                                         #######.#####################.###  
QW..#...#...#...#.#.........#...#..IK                                                       #.............#.....#...........#  
  #.#.#######.#.#.#####.#####.###.#                                                         #.#####.#.###.#.#.###.#########.#  
  #.#.#.....#.#.#...#.......#...#..RY                                                       #.#...#.#...#...#...#.......#...#  
  #.#.#.#.###.###.#######.#####.#.#                                                         #.#######.###.#####.#####.###.###  
BM..#...#...................#.....#                                                         #.......#.#.....#.......#.#......GM
  #################.#.#.###########                                                         ###.#.#############.#.#.#.#.###.#  
  #.#.............#.#.#...#.#.....#                                                       IW....#.#...#.#...#...#.#...#...#.#  
  #.#.#########.#.#.#######.###.###                                                         #######.###.#.###########.#######  
VI..#.......#...#.#.#.#...#.......#                                                         #...#.#.....#...#...#...#.#.#.#..KN
  #.#######.#####.###.#.###.#.#.###                                                         #.###.#.#####.###.#.###.###.#.#.#  
  #.......#.#.......#.....#.#.#...#                                                       ZM..#.....#.#.#...#.#.#............ZZ
  ###.#####.#######.#.###.###.#.###                                                         #.#.#.###.#.#.###.#.#.#.#####.#.#  
  #.........#.#.#.......#.....#....GM                                                       #...#.............#...#.#.#.#.#.#  
  ###########.#.###.#############.#                                                         #############.#.#########.#.#####  
  #.....#.........#...#.#.......#.#                                                       QW........#.#...#.#.........#...#..GZ
  #.#.#####.#####.#####.###.###.###                                                         #####.###.#####.###.#####.#.#.#.#  
  #.#...#.....#.#.#.....#...#.....#                                                         #...........#...#.....#...#.#...#  
  #.###.#.#.#.#.#.#####.#.#.###.#.#                                                         ###.#####.###########.###.#.###.#  
  #...#...#.#.#.....#.#...#.#.#.#..GZ                                                       #.....#.#.#.....#.#.#.#...#...#.#  
  ###.###.#.#.#.#.#.#.#.###.#.#.#.#                                                         #.#.#.#.#####.###.#.#.###.#.###.#  
DN......#.#.#.#.#.#.....#.#.#...#.#                                                         #.#.#.................#.......#.#  
  #.#.#.#.#######.#####.#.###.#.#.#        Q   P     A     K         B       S         C    ###.#.#.#.#####.#.#.###.#.#.#.###  
  #.#.#.#.#...........#...#...#.#.#        O   M     S     E         M       J         T    #...#.#.#...#...#.#.#.#.#.#.#...#  
  #.#.#.#.###.#.#.#.###.#.###.#############.###.#####.#####.#########.#######.#########.#####.#.#.###.#.#.#.###.#.#.#.#.#.#.#  
  #.#.#.#...#.#.#.#...#.#.#.....#.#.#.#.....#...#.#.....#.........#.#.......#...#.....#.#.#...#.#...#.#.#.#.#.#...#.#.#.#.#.#  
  #.###.#####.#####.#####.###.###.#.#.###.###.###.#####.###.#######.###.#####.#.#####.#.#.#######.#.#####.###.#.###.###.#####  
  #...#.#...#...#.#.....#.#.....#.......#.#.#.....#.#...#.....#...........#.#.#.#...#.......#.....#.#...#...#.....#.#.....#.#  
  #.#.#.###.#.#.#.###.###.###.#######.###.#.#####.#.#.#.#.###.###.###.#####.###.#.#.#.###########.#.###.#.###.#.###.#.###.#.#  
  #.#.#.#.....#.#.#.#.#.#.#.....#.#.........#.......#.#.#.#.....#...#.#.#...#...#.#.....#.#.....#.#...#...#.#.#...#.#...#...#  
  #.#.#######.###.#.#.#.#.#.#.#.#.###.#.###.#.#########.###.###.###.###.#.#.#.###.#######.###.#.#.#.###.#.#.###.###.#.###.#.#  
  #.#...#.#.#.#.#.....#...#.#.#.#.....#.#.#.#...#...#...#...#.#.#.#.....#.#...#...#...........#.#.#.#...#.....#...#.#...#.#.#  
  ###.#.#.#.#.#.###.#####.###.#####.###.#.#.###.###.###.#.#.#.###.#####.#.###.###.#.###.#.#######.#####.#.#.###.#######.#.#.#  
  #...#.#.........#...#...#.....#.....#.#.#.#...#.....#.#.#.#.......#...#...#.#...#...#.#.......#...#...#.#.#.#.....#...#.#.#  
  ###.#.#.###.###########.###.#.#.#######.#.#.###.#.#.#.#.###.#.#######.###.#####.###.#.#########.#####.###.#.#.#.#.#######.#  
  #.#.#.#...#.........#.....#.#.#.#...#.....#.....#.#.#.#.....#.#...#...#...#.........#.#...#...#.#.#.....#.#...#.#.......#.#  
  #.#.#####.#.#.#####.###############.#####.#######.###.#######.#.###.#.#.#######.#.#.#.###.#.###.#.#.#.#.###.#.#.#.###.#####  
  #...#.#...#.#...#...#.....#.......#.........#.......#.....#.......#.#.#.......#.#.#.#.........#.#.#.#.#...#.#.#.#...#.....#  
  ###.#.#.#####.#.#####.#.#####.#.#.#.#####.#####.#####.#.#####.#.#####.#.###########.#.###.#.###.#.#.###########.###.###.###  
  #.....#.#.....#.#...#.#...#.#.#.#.#.#.#.....#.....#...#.#.....#.#.....#.#...#...#.#.#...#.#...#.#.#.#...#.......#...#.....#  
  #.###.###.###.#####.###.###.###.#####.#.###.#####.###.#####.#.#####.###.#.###.###.###.#####.#####.###.#######.#.#######.###  
  #.#.#.#...#...#.........#.#...#.#.......#...#.....#...#...#.#.#.#.....#.........#.......#.#.#...#.#.....#.#...#.....#.....#  
  ###.###################.#.#.###.#.#####.#.#######.###.###.###.#.###.###.#.###.###.#######.###.###.###.#.#.###.#.###.#####.#  
  #.........#.#.#.........#.#.#...#.#.....#.#.........#.......#.#.......#.#.#.#.#.....#.................#.....#.#.#.#.....#.#  
  #####.#####.#.#########.#.#.#.#.#####.###########.###.#######.#.#####.#.###.#####.#.###.#.#.#.#####.###########.#.#.#.###.#  
  #.#.#.....#.#.#.#...#.........#...#.#.......#.#...#...#.#...#.#.....#.#.........#.#...#.#.#.#.....#.......#.....#...#.#...#  
  #.#.###.###.#.#.###.#####.#.#.###.#.#.###.###.###.#.###.###.#.#####.#####.#.#.#######.#.#######.###.#.#####.###.#.#.#.###.#  
  #.......#.#.....#.#...#.#.#.#.#.#.#.....#.#.....#.#.....#.....#.......#...#.#.#.#.#.......#...#...#.#...#.#...#.#.#.#.#...#  
  #.#.###.#.###.###.###.#.#######.#.#.#######.#####.#.#.###.#.###.#.#####.#######.#.###.###.###.#######.###.###.#.###.#####.#  
  #.#.#.#...............#.....#.#.#.........#...#...#.#...#.#.#...#.....#.#...#...#.#.....#.......#...........#.#...#.#.....#  
  #####.#.###.#.#.#####.###.###.#.#######.###.#.#.###.#####.#####.#####.#.#.#####.#.###.#######.#.###.#.#.#.###.#.###.#.###.#  
  #.......#...#.#.#.....#...............#...#.#.#.#.....#.......#.#...#.#.....#.#.....#.....#.#.#.#.#.#.#.#.#.#.#.#...#...#.#  
  #.###.#####.#.#.###.#.#####.#######.#.###.#.#.#.#.###.#######.#.###.#####.###.#.###.#.#####.#####.#########.#.#####.###.#.#  
  #.#.......#.#.#.#...#.........#.#.#.#.#...#.#...#.#...#.#.....#.#.....#...#...#.#.#.........................#.#...#.#.#.#.#  
  #######.###.###.#####.#########.#.#.#.#.###.#######.###.#.###.#.#.###.#.###.#.#.#.#.###.###.#.###.#.#.#.#.#####.#.#.#.#####  
  #.......#...#.....#...#.............#...#.........#.....#.#...#...#...#.....#.#.#.#...#...#.#...#.#.#.#.#.......#.#.......#  
  ###################################.###########.###.#.###.###########.#######.#.###########################################  
                                     P           N   P A   D           C       D I                                             
                                     M           K   E A   F           N       B E                                             """

import java.lang.RuntimeException

fun main() {
    val maze = mutableMapOf<Coord, Maze>()

    val input = mutableMapOf<Coord, String>()
    INPUT20.split("\n")
        .forEachIndexed { i, row ->
            row.split("").filter { it != "" }.forEachIndexed { j, cell ->
                val coord = Coord(j, i)
                input[coord] = cell
            }
        }
    input.forEach { coord, cell ->
        when (cell) {
            "#" -> maze[coord] = Maze(coord, MazeWall())
            "." -> maze[coord] = Maze(coord, MazeHall())
            else -> maze[coord] = Maze(coord, MazeNothing())
        }
    }

    input.forEach { coord, cell ->
        if (isLetter(cell)) {
            val (label, portalCoord) = readLabel(input, cell, coord)
            maze[portalCoord] = Maze(portalCoord, MazePortal(label, if (isOuter(coord, input)) -1 else 1))
        }
    }

    val mazePortals = maze.filter { it.value.mazeBlock is MazePortal }
    mazePortals
        .forEach { mazePortal ->
            maze.filter { it.value.mazeBlock is MazePortal }
                .filter { it != mazePortal }
                .filter { (it.value.mazeBlock as MazePortal).label == (mazePortal.value.mazeBlock as MazePortal).label }
                .forEach { (it.value.mazeBlock as MazePortal).portsTo = mazePortal.key }
        }
    maze.values.forEach {
        val validNeighbours = mutableListOf<Pair<Maze, Int>>()
        processMazeNeighbour(it.coord.north(), maze, validNeighbours)
        processMazeNeighbour(it.coord.south(), maze, validNeighbours)
        processMazeNeighbour(it.coord.east(), maze, validNeighbours)
        processMazeNeighbour(it.coord.west(), maze, validNeighbours)
        val current = maze[it.coord]!!.mazeBlock
        if (current is MazePortal) {
            if (current.portsTo != null) {
                validNeighbours.add(Pair(maze[current.portsTo!!]!!, current.levelChange))
            }
        }
        it.validNeighbors = validNeighbours
    }

    val start = maze.values.first { it.mazeBlock is MazePortal && it.mazeBlock.label == "AA" }.also { (it.mazeBlock as MazePortal).levelChange = 0 }
    val end = maze.values.first { it.mazeBlock is MazePortal && it.mazeBlock.label == "ZZ" }.also { (it.mazeBlock as MazePortal).levelChange = 0 }

    processMazeBlock(start, 0, 0)

    println("second result")
    println(end.steps[0])
}

fun isOuter(coord: Coord, input: MutableMap<Coord, String>): Boolean {
    val maxX = input.keys.maxBy { it.x }!!.x
    val maxY = input.keys.maxBy { it.y }!!.y

    val minX = input.keys.minBy { it.x }!!.x
    val minY = input.keys.minBy { it.y }!!.y

    return coord.x == maxX || coord.x == maxX - 1 || coord.x == minX || coord.x == minX + 1 || coord.y == maxY || coord.y == maxY - 1 || coord.y == minY || coord.y == minY + 1
}

fun processMazeBlock(current: Maze, steps: Int, level: Int) {
    if (level < 0 || level > 30) {
        return
    }
    if (current.mazeBlock is MazePortal) {
        println("Walking through ${current.mazeBlock.label} on level $level with $steps steps")
    }

    current.steps[level] = steps

    current.validNeighbors
        .filter { it.first.steps[level + it.second] ?: Int.MAX_VALUE > steps }
        .forEach { processMazeBlock(it.first, steps + 1, level + it.second) }
}

fun getLevelChange(it: Maze): Int {
    return if (it.mazeBlock is MazePortal) {
        it.mazeBlock.levelChange
    } else {
        0
    }
}

fun processMazeNeighbour(coord: Coord, maze: MutableMap<Coord, Maze>, validNeighbors: MutableList<Pair<Maze, Int>>) {
    val block = maze[coord] ?: return
    when (block.mazeBlock) {
        is MazeWall -> return
        is MazeNothing -> return
    }
    validNeighbors.add(Pair(block, 0))
}

private fun readLabel(input: Map<Coord, String>, cell: String, coord: Coord): Pair<String, Coord> {
    if (isLetter(input[coord.north()])) {
        if (input[coord.south()] == ".") {
            return Pair(input[coord.north()] + cell, coord.south())
        } else {
            return Pair(input[coord.north()] + cell, coord.north().north())
        }
    } else if (isLetter(input[coord.south()])) {
        if (input[coord.south().south()] == ".") {
            return Pair(cell + input[coord.south()], coord.south().south())
        } else {
            return Pair(cell + input[coord.south()], coord.north())
        }
    } else if (isLetter(input[coord.west()])) {
        if (input[coord.west().west()] == ".") {
            return Pair(input[coord.west()] + cell, coord.west().west())
        } else {
            return Pair(input[coord.west()] + cell, coord.east())
        }
    } else if (isLetter(input[coord.east()])) {
        if (input[coord.west()] == ".") {
            return Pair(cell + input[coord.east()], coord.west())
        } else {
            return Pair(cell + input[coord.east()], coord.east().east())
        }
    } else {
        throw RuntimeException()
    }
}


private fun isLetter(cell: String?): Boolean {
    if (cell == null) {
        return false;
    }
    return cell.toLowerCase() != cell
}

data class Maze(val coord: Coord, val mazeBlock: MazeBlock) {
    var validNeighbors = mutableListOf<Pair<Maze, Int>>()
    var steps = mutableMapOf<Int, Int>()
}

sealed class MazeBlock(val char: Char)

class MazeNothing : MazeBlock(' ')
class MazeWall : MazeBlock('#')
class MazeHall : MazeBlock('.')
class MazePortal(val label: String, var levelChange: Int) : MazeBlock('.') {
    var portsTo: Coord? = null
    override fun toString(): String {
        return "MazePortal(label='$label', levelChange=$levelChange, portsTo=$portsTo)"
    }


}

const val TEST201 = """
         A           
         A           
  #######.#########  
  #######.........#  
  #######.#######.#  
  #######.#######.#  
  #######.#######.#  
  #####  B    ###.#  
BC...##  C    ###.#  
  ##.##       ###.#  
  ##...DE  F  ###.#  
  #####    G  ###.#  
  #########.#####.#  
DE..#######...###.#  
  #.#########.###.#  
FG..#########.....#  
  ###########.#####  
             Z       
             Z       """

const val TEST202 = """
             Z L X W       C                 
             Z P Q B       K                 
  ###########.#.#.#.#######.###############  
  #...#.......#.#.......#.#.......#.#.#...#  
  ###.#.#.#.#.#.#.#.###.#.#.#######.#.#.###  
  #.#...#.#.#...#.#.#...#...#...#.#.......#  
  #.###.#######.###.###.#.###.###.#.#######  
  #...#.......#.#...#...#.............#...#  
  #.#########.#######.#.#######.#######.###  
  #...#.#    F       R I       Z    #.#.#.#  
  #.###.#    D       E C       H    #.#.#.#  
  #.#...#                           #...#.#  
  #.###.#                           #.###.#  
  #.#....OA                       WB..#.#..ZH
  #.###.#                           #.#.#.#  
CJ......#                           #.....#  
  #######                           #######  
  #.#....CK                         #......IC
  #.###.#                           #.###.#  
  #.....#                           #...#.#  
  ###.###                           #.#.#.#  
XF....#.#                         RF..#.#.#  
  #####.#                           #######  
  #......CJ                       NM..#...#  
  ###.#.#                           #.###.#  
RE....#.#                           #......RF
  ###.###        X   X       L      #.#.#.#  
  #.....#        F   Q       P      #.#.#.#  
  ###.###########.###.#######.#########.###  
  #.....#...#.....#.......#...#.....#.#...#  
  #####.#.###.#######.#######.###.###.#.#.#  
  #.......#.......#.#.#.#.#...#...#...#.#.#  
  #####.###.#####.#.#.#.#.###.###.#.###.###  
  #.......#.....#.#...#...............#...#  
  #############.#.#.###.###################  
               A O F   N                     
               A A D   M                     """

const val INPUT20 = """
                                       I           N S       T       Q     I         K                                         
                                       W           P J       E       O     K         E                                         
  #####################################.###########.#.#######.#######.#####.#########.#######################################  
  #.#.#.....#...#.#...........#.#.#.....#.#.........#.......#...#.........#.#.....#...#.......#.........#.......#.......#...#  
  #.#.#####.###.#.###.#.#.###.#.#.#####.#.#####.#####.#####.#.#.###.#####.#.#.###.#.###.#.###.#.###.#######.###.###.#######.#  
  #...........#...#.#.#.#.#.........#...#.....#.....#...#...#.#.#.#...#...#.....#.#.....#...#.#.#.#...#.#...#.#.#.#.........#  
  ###########.#.###.#######.###.###.###.#.#.###.###########.###.#.###.#########.#.#######.#####.#.#.#.#.#.###.###.#.###.###.#  
  #...#.#.#.......#...#.#...#...#.#...#.#.#.#.....#.#.....#...#...#...#.#.....#.#.#.......#.......#.#.#...#.#...#.#...#.#...#  
  ###.#.#.###.###.#.###.#########.###.#.#.#####.###.#####.#.###.#.#.###.###.#.###.#.#########.###.#####.###.#.#.#.#.#######.#  
  #...#.#.....#...#.....#.#.....#...........#.#.........#.....#.#.#.#.....#.#.....#.............#.#.......#.#.#.#.#.......#.#  
  ###.#.#########.###.###.#.#.#.#.###.#####.#.#.#.#######.#####.#.#.#.#.###.###.#########.#.#.#.#####.#####.###.#.#.#####.#.#  
  #.......#...............#.#.#...#.#.#...#...#.#.....#.....#.#.#.#.#.#...#.#.#.#...#...#.#.#.#.#.....#.......#.........#.#.#  
  #####.###########.#.#.###########.#####.###.###.###.#####.#.###.#.#.###.#.#.#.###.###.#.#######.#.#####.#####.#############  
  #.....#...#...#.#.#.#.#.#.#.........#.......#.....#.#.......#.#.#...#...#...#.#.....#...#.......#.....#.#.#.........#.....#  
  #####.###.###.#.###.###.#.#######.###.#######.#.#.#######.###.#.###.#.#####.#####.#.#.###.#####.#.###.#.#.#.#####.#####.###  
  #.#...........#.............................#.#.#.......#.#.....#...#.....#.....#.#.#.....#...#.#...#.........#.#...#.....#  
  #.#.#.#.#.###.#.#.#####.###.#.#.#####.#####.#.###.#######.#.###.#.#.###.#####.#.#.#.###.#.#.###.#######.#.#.###.#######.###  
  #.#.#.#.#...#.#.#.#.....#.#.#.#.#.......#...#...#...#.....#...#.#.#.#.#...#...#.#.#.....#.....#.#...#...#.#.........#.....#  
  #.#######.#######.###.###.###.#####.###.###.#.#####.#.#.#.#.#####.###.#.#######.#.#.#.#######.###.#####.###.#####.###.#.#.#  
  #.#...#...#.#.#.#...#.#.......#.....#...#.#.#.#.#.#.#.#.#.#.....#.#.#.#.#.......#.#.#.......#.........#.#...#.......#.#.#.#  
  #.#.#####.#.#.#.###############.###.#####.#.#.#.#.###.###.#.#####.#.#.#.###.#.#.#.#####.#.###.#.#####.#################.#.#  
  #...#.#...#.....#.#.#.....#.#.....#.#.......#.....#...#...#.....#.#.....#.#.#.#.#...#...#...#.#...#.....#...#...#.#.#.#.#.#  
  ###.#.###.###.###.#.#.###.#.###.#######.###.###.#.#######.#.###########.#.#####.#.#########.###.#########.#####.#.#.#.###.#  
  #.#.....#.#...#.....#.#.#...........#.#.#.#...#.#.#...#...#.....#...#...#.....#.#...#.....#.#.#.#.......#.#.#...#...#.#...#  
  #.###.###.#.###.#.#####.#######.#.###.###.#.###.#.###.###.#.#.#.#.#####.###.###.#.#######.###.#####.#.###.#.#.###.###.###.#  
  #.............#.#.#.#.....#.....#.#.........#...#.#.......#.#.#.#.....#.#.....#.#...#...#.....#.#.#.#.....#.#.#...#...#...#  
  ###.#.#####.#####.#.#.###################.###.#########.###.#####.#.#.#.#.###.#.###.#.###.#####.#.###.#####.#.###.###.###.#  
  #...#...#.#.#.......#.#...#.#...#.....#.#...#...#.#.......#.....#.#.#...#.#...#...#.......#.#.#.....#...#...#...#...#...#.#  
  #####.#.#.#.#####.#.#.###.#.#.#######.#.###.#.###.#.#####.#.###########.#.#.###.###.###.###.#.#.#####.#####.###.#.###.###.#  
  #...#.#...#.#.....#.#...#.................#.#.....#.#...#.#.....#...#...#.#.....#...#...#.#.#.....#.#...#.....#.....#.#...#  
  #.#####.#######.#.#.#.###.###########.###.#.###.#######.#.#.#####.#####.#.###.#.#.#.#.#.#.#.#.###.#.#.#####.###.#.###.###.#  
  #...#.#.#.#...#.#.#.#...#.#.....#.#.....#.....#...#...#...#...#.#.....#.#.#.#.#.#.#.#.#.........#.#...#.......#.#.......#.#  
  ###.#.#.#.###.###.###.###.#####.#.#####.###.#####.###.###.#.###.#.#.###.#.#.#.#.###.###.###.#.#######.###.#########.#####.#  
  #.....#...#.#.#.#...#.#.#.#.....#.........#.#.....#.......#.#.....#.....#.#...#.#...#.....#.#.#.#...#...#...#.#.........#.#  
  ###.#.#.#.#.#.#.###.#.#.#######.#####.#########.#######.###.#####.#######.###########.#####.###.#.###.###.###.###.###.###.#  
  #...#.#.#.#.#...........#...#...#    N         P       N   C     I       D           K    #.#.#...#.......#.#...#.#.#.....#  
  ###.###.###.#.#####.#####.#.###.#    K         E       P   J     E       B           N    ###.###.###.#####.#.#####.###.#.#  
NW....#.........#.#.#...#...#.#...#                                                         #...#.....#.....#.....#.#...#.#.#  
  ###.#.#####.###.#.#######.#####.#                                                         #.#.###.#.#.#.#####.#.#.#.#####.#  
  #.....#.....#.#.#.#.#.#.#.#.#....DF                                                       #.#.#.#.#...#...#...#.#.....#....ZM
  #####.#.#####.#.#.#.#.#.#.#.###.#                                                         ###.#.#.#####.#####.###.#######.#  
  #.....#.#...#.....#.....#.#.#...#                                                       VI....#...#.#...#.#.......#.#.#.#.#  
  #######.#.#.#.###.###.#.#.#.###.#                                                         #.#.#.###.#.###.###.###.#.#.#.#.#  
  #.#.#.....#...#.......#.........#                                                         #.#...#.#.............#.........#  
  #.#.#.###.#.#.#.#####.#####.#####                                                         #####.#.###.#.###.#.###.#########  
RY....#.#.#.#.#.#.#...#.#.#.#.#....TE                                                       #...#.#...#.#.#...#.#...#.......#  
  #.#####.#########.#####.#.###.#.#                                                         #.#.###.###########.#######.###.#  
  #...#.....#.....#.#.#.......#.#.#                                                       CN..#.........#.....#.#.#.....#...#  
  #.#.#.###.###.###.#.#.###.#####.#                                                         #####.###########.###.#.#.###.###  
  #.#...#.................#.......#                                                         #.#.#...#.#...#.#...#...#.#...#..AS
  #####################.#.#######.#                                                         #.#.#.###.#.###.#.#####.###.###.#  
CT....#.....#.......#...#...#.#.#.#                                                         #.........................#.....#  
  ###.#.###.###.#.#.#######.#.#.###                                                         ###.#.#############.#.#.###.#.###  
  #...#...#...#.#.#.#.#...#.#......DN                                                       #...#.#.......#.#...#.#.#...#.#.#  
  #.#####.###.#.#.###.###.###.#####                                                         #########.###.#.#####.#########.#  
  #.....#.#...#.#...........#.#...#                                                         #...#.#.....#...#...#...#...#.#..CJ
  ###.###.###.#.#.#.###.#.#.#.###.#                                                         ###.#.#####.#.#####.#.#####.#.#.#  
  #.......#.....#.#...#.#.#...#...#                                                       NW....#.....#.#.#.....#.#.........#  
  ###############.#####.#######.###                                                         #.#.#.###.#.#.#####.#####.#####.#  
  #...........#.#...#.#...#.....#.#                                                         #.#...#.#...#...............#.#.#  
  #.###.#.#####.#####.#####.###.#.#                                                         #######.#####################.###  
QW..#...#...#...#.#.........#...#..IK                                                       #.............#.....#...........#  
  #.#.#######.#.#.#####.#####.###.#                                                         #.#####.#.###.#.#.###.#########.#  
  #.#.#.....#.#.#...#.......#...#..RY                                                       #.#...#.#...#...#...#.......#...#  
  #.#.#.#.###.###.#######.#####.#.#                                                         #.#######.###.#####.#####.###.###  
BM..#...#...................#.....#                                                         #.......#.#.....#.......#.#......GM
  #################.#.#.###########                                                         ###.#.#############.#.#.#.#.###.#  
  #.#.............#.#.#...#.#.....#                                                       IW....#.#...#.#...#...#.#...#...#.#  
  #.#.#########.#.#.#######.###.###                                                         #######.###.#.###########.#######  
VI..#.......#...#.#.#.#...#.......#                                                         #...#.#.....#...#...#...#.#.#.#..KN
  #.#######.#####.###.#.###.#.#.###                                                         #.###.#.#####.###.#.###.###.#.#.#  
  #.......#.#.......#.....#.#.#...#                                                       ZM..#.....#.#.#...#.#.#............ZZ
  ###.#####.#######.#.###.###.#.###                                                         #.#.#.###.#.#.###.#.#.#.#####.#.#  
  #.........#.#.#.......#.....#....GM                                                       #...#.............#...#.#.#.#.#.#  
  ###########.#.###.#############.#                                                         #############.#.#########.#.#####  
  #.....#.........#...#.#.......#.#                                                       QW........#.#...#.#.........#...#..GZ
  #.#.#####.#####.#####.###.###.###                                                         #####.###.#####.###.#####.#.#.#.#  
  #.#...#.....#.#.#.....#...#.....#                                                         #...........#...#.....#...#.#...#  
  #.###.#.#.#.#.#.#####.#.#.###.#.#                                                         ###.#####.###########.###.#.###.#  
  #...#...#.#.#.....#.#...#.#.#.#..GZ                                                       #.....#.#.#.....#.#.#.#...#...#.#  
  ###.###.#.#.#.#.#.#.#.###.#.#.#.#                                                         #.#.#.#.#####.###.#.#.###.#.###.#  
DN......#.#.#.#.#.#.....#.#.#...#.#                                                         #.#.#.................#.......#.#  
  #.#.#.#.#######.#####.#.###.#.#.#        Q   P     A     K         B       S         C    ###.#.#.#.#####.#.#.###.#.#.#.###  
  #.#.#.#.#...........#...#...#.#.#        O   M     S     E         M       J         T    #...#.#.#...#...#.#.#.#.#.#.#...#  
  #.#.#.#.###.#.#.#.###.#.###.#############.###.#####.#####.#########.#######.#########.#####.#.#.###.#.#.#.###.#.#.#.#.#.#.#  
  #.#.#.#...#.#.#.#...#.#.#.....#.#.#.#.....#...#.#.....#.........#.#.......#...#.....#.#.#...#.#...#.#.#.#.#.#...#.#.#.#.#.#  
  #.###.#####.#####.#####.###.###.#.#.###.###.###.#####.###.#######.###.#####.#.#####.#.#.#######.#.#####.###.#.###.###.#####  
  #...#.#...#...#.#.....#.#.....#.......#.#.#.....#.#...#.....#...........#.#.#.#...#.......#.....#.#...#...#.....#.#.....#.#  
  #.#.#.###.#.#.#.###.###.###.#######.###.#.#####.#.#.#.#.###.###.###.#####.###.#.#.#.###########.#.###.#.###.#.###.#.###.#.#  
  #.#.#.#.....#.#.#.#.#.#.#.....#.#.........#.......#.#.#.#.....#...#.#.#...#...#.#.....#.#.....#.#...#...#.#.#...#.#...#...#  
  #.#.#######.###.#.#.#.#.#.#.#.#.###.#.###.#.#########.###.###.###.###.#.#.#.###.#######.###.#.#.#.###.#.#.###.###.#.###.#.#  
  #.#...#.#.#.#.#.....#...#.#.#.#.....#.#.#.#...#...#...#...#.#.#.#.....#.#...#...#...........#.#.#.#...#.....#...#.#...#.#.#  
  ###.#.#.#.#.#.###.#####.###.#####.###.#.#.###.###.###.#.#.#.###.#####.#.###.###.#.###.#.#######.#####.#.#.###.#######.#.#.#  
  #...#.#.........#...#...#.....#.....#.#.#.#...#.....#.#.#.#.......#...#...#.#...#...#.#.......#...#...#.#.#.#.....#...#.#.#  
  ###.#.#.###.###########.###.#.#.#######.#.#.###.#.#.#.#.###.#.#######.###.#####.###.#.#########.#####.###.#.#.#.#.#######.#  
  #.#.#.#...#.........#.....#.#.#.#...#.....#.....#.#.#.#.....#.#...#...#...#.........#.#...#...#.#.#.....#.#...#.#.......#.#  
  #.#.#####.#.#.#####.###############.#####.#######.###.#######.#.###.#.#.#######.#.#.#.###.#.###.#.#.#.#.###.#.#.#.###.#####  
  #...#.#...#.#...#...#.....#.......#.........#.......#.....#.......#.#.#.......#.#.#.#.........#.#.#.#.#...#.#.#.#...#.....#  
  ###.#.#.#####.#.#####.#.#####.#.#.#.#####.#####.#####.#.#####.#.#####.#.###########.#.###.#.###.#.#.###########.###.###.###  
  #.....#.#.....#.#...#.#...#.#.#.#.#.#.#.....#.....#...#.#.....#.#.....#.#...#...#.#.#...#.#...#.#.#.#...#.......#...#.....#  
  #.###.###.###.#####.###.###.###.#####.#.###.#####.###.#####.#.#####.###.#.###.###.###.#####.#####.###.#######.#.#######.###  
  #.#.#.#...#...#.........#.#...#.#.......#...#.....#...#...#.#.#.#.....#.........#.......#.#.#...#.#.....#.#...#.....#.....#  
  ###.###################.#.#.###.#.#####.#.#######.###.###.###.#.###.###.#.###.###.#######.###.###.###.#.#.###.#.###.#####.#  
  #.........#.#.#.........#.#.#...#.#.....#.#.........#.......#.#.......#.#.#.#.#.....#.................#.....#.#.#.#.....#.#  
  #####.#####.#.#########.#.#.#.#.#####.###########.###.#######.#.#####.#.###.#####.#.###.#.#.#.#####.###########.#.#.#.###.#  
  #.#.#.....#.#.#.#...#.........#...#.#.......#.#...#...#.#...#.#.....#.#.........#.#...#.#.#.#.....#.......#.....#...#.#...#  
  #.#.###.###.#.#.###.#####.#.#.###.#.#.###.###.###.#.###.###.#.#####.#####.#.#.#######.#.#######.###.#.#####.###.#.#.#.###.#  
  #.......#.#.....#.#...#.#.#.#.#.#.#.....#.#.....#.#.....#.....#.......#...#.#.#.#.#.......#...#...#.#...#.#...#.#.#.#.#...#  
  #.#.###.#.###.###.###.#.#######.#.#.#######.#####.#.#.###.#.###.#.#####.#######.#.###.###.###.#######.###.###.#.###.#####.#  
  #.#.#.#...............#.....#.#.#.........#...#...#.#...#.#.#...#.....#.#...#...#.#.....#.......#...........#.#...#.#.....#  
  #####.#.###.#.#.#####.###.###.#.#######.###.#.#.###.#####.#####.#####.#.#.#####.#.###.#######.#.###.#.#.#.###.#.###.#.###.#  
  #.......#...#.#.#.....#...............#...#.#.#.#.....#.......#.#...#.#.....#.#.....#.....#.#.#.#.#.#.#.#.#.#.#.#...#...#.#  
  #.###.#####.#.#.###.#.#####.#######.#.###.#.#.#.#.###.#######.#.###.#####.###.#.###.#.#####.#####.#########.#.#####.###.#.#  
  #.#.......#.#.#.#...#.........#.#.#.#.#...#.#...#.#...#.#.....#.#.....#...#...#.#.#.........................#.#...#.#.#.#.#  
  #######.###.###.#####.#########.#.#.#.#.###.#######.###.#.###.#.#.###.#.###.#.#.#.#.###.###.#.###.#.#.#.#.#####.#.#.#.#####  
  #.......#...#.....#...#.............#...#.........#.....#.#...#...#...#.....#.#.#.#...#...#.#...#.#.#.#.#.......#.#.......#  
  ###################################.###########.###.#.###.###########.#######.#.###########################################  
                                     P           N   P A   D           C       D I                                             
                                     M           K   E A   F           N       B E                                             """
