import scala.
collection .
immutable .
Queue
type Grid
[ A
] = Array
[ Array
[ A
] ]
type Indices
= ( Int, Int
)
type Opt2
[ A
] = Option
[ Option
[ A
] ]
type IndexGrid
= Grid
[ Opt2
[ Indices
] ]
type Predicate
[ A
] = A
=> Boolean
def validAndTraversable
[ A
] ( isTraversable
: Predicate
[ A
] , grid
: Grid
[ A
] , xy
: Indices
) : Boolean
= { val ybound
= grid
( 0 ) .
length val withinBounds
= ( x
>= 0 ) && ( x
< xbound
) && ( y
>= 0 ) && ( y
< ybound
) withinBounds && isTraversable( grid( x) ( y) )
}
def getPath
( grid
: IndexGrid, end
: Indices
) = {
def pathAccumulator
( grid
: IndexGrid, path
: List
[ Indices
] , xy
: Indices
) : List
[ Indices
] = { case Some
( Some
( prevXY
) ) => pathAccumulator
( grid, xy
:: path, prevXY
) case Some
( None
) => xy
:: path
}
}
pathAccumulator( grid, Nil, end)
}
def mazeSolverLoop
[ A
] ( isFinish
: ( Indices, A
) => Boolean,
isTraversable: Predicate[ A] ,
grid: Grid[ A] ,
queue: Queue[ Indices] ,
indexGrid
: IndexGrid
) : List
[ Indices
] = if ( queue.
isEmpty ) Nil
else { val ( currentXY, rest
) = queue.
dequeue if ( isFinish
( currentXY, grid
( x
) ( y
) ) ) { getPath( indexGrid, currentXY) // not really
}
val neighbors
= List
( ( x +
1 , y
) ,
( x, y +
1 ) ,
( x -
1 , y
) ,
( x, y -
1 ) ) val unvisited
= neighbors.
filter { case ij
@ ( i, j
) => validAndTraversable
( isTraversable, grid, ij
) && indexGrid
( i
) ( j
) .
isEmpty } for ( ( i, j
) < - unvisited
) { indexGrid( i) ( j) = Some( Some( currentXY) )
}
val updatedQueue
= rest ++ unvisited
mazeSolverLoop( isFinish, isTraversable, grid, updatedQueue, indexGrid)
}
}
def findUnknownFinish
[ A
] ( start
: Indices,
isFinish: ( Indices, A) => Boolean,
isTraversable: Predicate[ A] ,
grid: Grid[ A] ) =
if ( validAndTraversable
( isTraversable, grid, start
) ) { val indexGrid
= Array.
fill [ Opt2
[ Indices
] ] ( grid.
length , grid
( 0 ) .
length ) ( None
) indexGrid( x) ( y) = Some( None)
mazeSolverLoop( isFinish, isTraversable, grid, Queue( start) , indexGrid)
}
Nil
}
def findKnownFinish
[ A
] ( start
: Indices,
finish: Indices,
isTraversable: Predicate[ A] ,
grid: Grid[ A] ) = findUnknownFinish( start, ( xy: Indices, a: A) => ( xy == finish) , isTraversable, grid)
def escapeMaze
[ A
] ( start
: Indices, isTraversable
: Predicate
[ A
] , grid
: Grid
[ A
] ) = { val ybound
= grid
( 0 ) .
length val boundaryPred
= ( xy
: Indices, a
: A
) => { ( ( x == 0 ) || ( x == xbound - 1 ) || ( y == 0 ) || ( y == ybound - 1 ) )
}
findUnknownFinish( start, boundaryPred, isTraversable, grid)
}
def escapeMazeV2
[ A
] ( start
: Indices, isTraversable
: Predicate
[ A
] , grid
: Grid
[ A
] ) = { val ybound
= grid
( 0 ) .
length val boundaryPred
= ( xy
: Indices, a
: A
) => { ( ( x == 0 ) || ( x == xbound - 1 ) || ( y == 0 ) || ( y == ybound - 1 ) ) && ( xy != start)
}
findUnknownFinish( start, boundaryPred, isTraversable, grid)
}
def printMazeGrid
[ A
] ( grid
: Grid
[ A
] ) = { grid.foreach { row => println( row.mkString ( " " ) ) } ;
println( ) ;
}
def printPath
( path
: List
[ Indices
] ) { path.foreach ( println( _ ) ) ;
println( ) ;
}
}
val maze
_ 01
= Array
( Array
( 1 ,
1 ,
1 ,
1 ,
1 ,
1 ,
0 ) ,
Array( 0 ,0 ,0 ,0 ,0 ,0 ,0 ) ,
Array( 1 ,1 ,1 ,1 ,1 ,1 ,0 ) ,
Array( 0 ,0 ,0 ,0 ,0 ,0 ,0 ) ,
Array( 0 ,1 ,1 ,1 ,1 ,1 ,1 ) ,
Array( 0 ,0 ,0 ,0 ,0 ,0 ,0 ) ,
Array( 1 ,1 ,1 ,0 ,1 ,1 ,1 ) ,
Array( 0 ,0 ,0 ,0 ,0 ,0 ,0 ) ,
Array( 0 ,1 ,1 ,1 ,1 ,1 ,0 ) )
val maze
_ 02
= Array
( "xxxxxxxxxxxxxxxxxxxxx" ,
"x x x" ,
"xx xxxx xxxxxx xxx x" ,
"x x x x xx x" ,
"x xxxxx xxxxxxxx x x" ,
"x x xx x" ,
"xxxxxx xxxxx xxxx x" ,
"x xxxx x x x" ,
"x xx x x x x x x xxx" ,
"x xx x x x x x x" ,
"xx x x x xxx xxx xxx" ,
"x xx x x" ,
"xxxx x xxxxxx xxxx x" ,
"x xx x x x x" ,
"xxxxxx x x xxxxx xxx" ,
"x xx x x x x" ,
"xxx x xx xxx xxx x x" ,
"x x x x x x" ,
"x x xxxxxx xxxx xxx x" ,
"x x ox" ,
"x xxxxxxxxxxxxxxxxxxx" ) .map ( _ .toArray )
val maze
_ 03
= Array
( "###########" ,
"# #" ,
"# ##### # #" ,
" # # #" ,
"### # ### #" ,
"# # #" ,
"# # ### ###" ,
"# # # " ,
"# ### # # #" ,
"# # #" ,
"###########" ) .map ( _ .toArray )
val maze1
_ s1
= MazeSolver.
findKnownFinish ( start
= ( 1 ,
0 ) ,
finish = ( 8 ,6 ) ,
isTraversable = ( x: Int) => ( x == 0 ) ,
grid = maze_ 01)
val maze2
_ s1
= MazeSolver.
findUnknownFinish ( start
= ( 1 ,
1 ) ,
isFinish = ( xy: ( Int, Int) , c: Char) => ( c == 'o' ) ,
isTraversable = ( c: Char) => ( c != 'x' ) ,
grid = maze_ 02)
val maze2
_ s2
= MazeSolver.
escapeMaze ( start
= ( 1 ,
1 ) ,
isTraversable = ( c: Char) => ( c != 'x' ) ,
grid = maze_ 02)
val maze3
_ s1
= MazeSolver.
escapeMazeV2 ( start
= ( 3 ,
0 ) ,
isTraversable = ( c: Char) => ( c != '#' ) ,
grid = maze_ 03)
val maze3
_ s2
= MazeSolver.
escapeMazeV2 ( start
= ( 7 ,
10 ) ,
isTraversable = ( c: Char) => ( c != '#' ) ,
grid = maze_ 03)
MazeSolver.printMazeGrid ( maze_ 01)
MazeSolver.printPath ( maze1_ s1)
MazeSolver.printMazeGrid ( maze_ 02)
MazeSolver.printPath ( maze2_ s1)
MazeSolver.printPath ( maze2_ s2)
MazeSolver.printMazeGrid ( maze_ 03)
MazeSolver.printPath ( maze3_ s1)
MazeSolver.printPath ( maze3_ s2)
}
aW1wb3J0IHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlF1ZXVlCgpvYmplY3QgTWF6ZVNvbHZlciB7CgogICAgdHlwZSBHcmlkW0FdID0gQXJyYXlbQXJyYXlbQV1dCgogICAgdHlwZSBJbmRpY2VzID0gKEludCwgSW50KQoKICAgIHR5cGUgT3B0MltBXSA9IE9wdGlvbltPcHRpb25bQV1dCgogICAgdHlwZSBJbmRleEdyaWQgPSBHcmlkW09wdDJbSW5kaWNlc11dCgogICAgdHlwZSBQcmVkaWNhdGVbQV0gPSBBID0+IEJvb2xlYW4KCiAgICBkZWYgdmFsaWRBbmRUcmF2ZXJzYWJsZVtBXShpc1RyYXZlcnNhYmxlOiBQcmVkaWNhdGVbQV0sIGdyaWQ6IEdyaWRbQV0sIHh5OiBJbmRpY2VzKTogQm9vbGVhbiA9IHsKICAgICAgICB2YWwgKHgsIHkpID0geHkKICAgICAgICB2YWwgeGJvdW5kID0gZ3JpZC5sZW5ndGgKICAgICAgICB2YWwgeWJvdW5kID0gZ3JpZCgwKS5sZW5ndGgKICAgICAgICB2YWwgd2l0aGluQm91bmRzID0gKHggPj0gMCkgJiYgKHggPCB4Ym91bmQpICYmICh5ID49IDApICYmICh5IDwgeWJvdW5kKQogICAgICAgIHdpdGhpbkJvdW5kcyAmJiBpc1RyYXZlcnNhYmxlKGdyaWQoeCkoeSkpCiAgICB9CgogICAgZGVmIGdldFBhdGgoZ3JpZDogSW5kZXhHcmlkLCBlbmQ6IEluZGljZXMpID0gewoKICAgICAgICBkZWYgcGF0aEFjY3VtdWxhdG9yKGdyaWQ6IEluZGV4R3JpZCwgcGF0aDogTGlzdFtJbmRpY2VzXSwgeHk6IEluZGljZXMpOiBMaXN0W0luZGljZXNdID0gewogICAgICAgICAgICB2YWwgKHgsIHkpID0geHkKICAgICAgICAgICAgZ3JpZCh4KSh5KSBtYXRjaCB7CiAgICAgICAgICAgICAgICBjYXNlIFNvbWUoU29tZShwcmV2WFkpKSA9PiBwYXRoQWNjdW11bGF0b3IoZ3JpZCwgeHkgOjogcGF0aCwgcHJldlhZKQogICAgICAgICAgICAgICAgY2FzZSBTb21lKE5vbmUpID0+IHh5IDo6IHBhdGgKICAgICAgICAgICAgICAgIGNhc2UgTm9uZSA9PiBOaWwKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICBwYXRoQWNjdW11bGF0b3IoZ3JpZCwgTmlsLCBlbmQpCiAgICB9CgogICAgZGVmIG1hemVTb2x2ZXJMb29wW0FdKGlzRmluaXNoOiAoSW5kaWNlcywgQSkgPT4gQm9vbGVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RyYXZlcnNhYmxlOiBQcmVkaWNhdGVbQV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZDogR3JpZFtBXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBxdWV1ZTogUXVldWVbSW5kaWNlc10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhHcmlkOiBJbmRleEdyaWQpOiBMaXN0W0luZGljZXNdID0gaWYgKHF1ZXVlLmlzRW1wdHkpIE5pbCBlbHNlIHsKICAgICAgICB2YWwgKGN1cnJlbnRYWSwgcmVzdCkgPSBxdWV1ZS5kZXF1ZXVlCiAgICAgICAgdmFsICh4LCB5KSA9IGN1cnJlbnRYWQogICAgICAgIGlmIChpc0ZpbmlzaChjdXJyZW50WFksIGdyaWQoeCkoeSkpKSB7CiAgICAgICAgICAgIGdldFBhdGgoaW5kZXhHcmlkLCBjdXJyZW50WFkpIC8vIG5vdCByZWFsbHkKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIHZhbCBuZWlnaGJvcnMgPSBMaXN0KCh4ICsgMSwgeSksICh4LCB5ICsgMSksICh4IC0gMSwgeSksICh4LCB5IC0gMSkpCiAgICAgICAgICAgIHZhbCB1bnZpc2l0ZWQgPSBuZWlnaGJvcnMuZmlsdGVyIHsgY2FzZSBpaiBAIChpLCBqKSA9PiB2YWxpZEFuZFRyYXZlcnNhYmxlKGlzVHJhdmVyc2FibGUsIGdyaWQsIGlqKSAmJiBpbmRleEdyaWQoaSkoaikuaXNFbXB0eSB9CiAgICAgICAgICAgIGZvciAoIChpLCBqKSA8LSB1bnZpc2l0ZWQgKSB7CiAgICAgICAgICAgICAgICBpbmRleEdyaWQoaSkoaikgPSBTb21lKFNvbWUoY3VycmVudFhZKSkKICAgICAgICAgICAgfQogICAgICAgICAgICB2YWwgdXBkYXRlZFF1ZXVlID0gcmVzdCArKyB1bnZpc2l0ZWQKICAgICAgICAgICAgbWF6ZVNvbHZlckxvb3AoaXNGaW5pc2gsIGlzVHJhdmVyc2FibGUsIGdyaWQsIHVwZGF0ZWRRdWV1ZSwgaW5kZXhHcmlkKQogICAgICAgIH0KICAgIH0KCiAgICBkZWYgZmluZFVua25vd25GaW5pc2hbQV0oc3RhcnQ6IEluZGljZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRmluaXNoOiAoSW5kaWNlcywgQSkgPT4gQm9vbGVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNUcmF2ZXJzYWJsZTogUHJlZGljYXRlW0FdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkOiBHcmlkW0FdKSA9IAogICAgaWYgKHZhbGlkQW5kVHJhdmVyc2FibGUoaXNUcmF2ZXJzYWJsZSwgZ3JpZCwgc3RhcnQpKSB7CiAgICAgICAgdmFsICh4LCB5KSA9IHN0YXJ0CiAgICAgICAgdmFsIGluZGV4R3JpZCA9IEFycmF5LmZpbGxbT3B0MltJbmRpY2VzXV0oZ3JpZC5sZW5ndGgsIGdyaWQoMCkubGVuZ3RoKShOb25lKQogICAgICAgIGluZGV4R3JpZCh4KSh5KSA9IFNvbWUoTm9uZSkKICAgICAgICBtYXplU29sdmVyTG9vcChpc0ZpbmlzaCwgaXNUcmF2ZXJzYWJsZSwgZ3JpZCwgUXVldWUoc3RhcnQpLCBpbmRleEdyaWQpCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBOaWwKICAgIH0KCiAgICBkZWYgZmluZEtub3duRmluaXNoW0FdKHN0YXJ0OiBJbmRpY2VzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluaXNoOiBJbmRpY2VzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNUcmF2ZXJzYWJsZTogUHJlZGljYXRlW0FdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZDogR3JpZFtBXSkgPSBmaW5kVW5rbm93bkZpbmlzaChzdGFydCwgKHh5OiBJbmRpY2VzLCBhOiBBKSA9PiAoeHkgPT0gZmluaXNoKSwgaXNUcmF2ZXJzYWJsZSwgZ3JpZCkKICAgIAogICAgCiAgICBkZWYgZXNjYXBlTWF6ZVtBXShzdGFydDogSW5kaWNlcywgaXNUcmF2ZXJzYWJsZTogUHJlZGljYXRlW0FdLCBncmlkOiBHcmlkW0FdKSA9IHsKICAgICAgICB2YWwgeGJvdW5kID0gZ3JpZC5sZW5ndGgKICAgICAgICB2YWwgeWJvdW5kID0gZ3JpZCgwKS5sZW5ndGgKICAgICAgICB2YWwgYm91bmRhcnlQcmVkID0gKHh5OiBJbmRpY2VzLCBhOiBBKSA9PiB7CiAgICAgICAgICAgIHZhbCAoeCwgeSkgPSB4eQogICAgICAgICAgICAoKHggPT0gMCkgfHwgKHggPT0geGJvdW5kIC0gMSkgfHwgKHkgPT0gMCkgfHwgKHkgPT0geWJvdW5kIC0gMSkpCiAgICAgICAgfQogICAgICAgIGZpbmRVbmtub3duRmluaXNoKHN0YXJ0LCBib3VuZGFyeVByZWQsIGlzVHJhdmVyc2FibGUsIGdyaWQpCiAgICB9CgogICAgZGVmIGVzY2FwZU1hemVWMltBXShzdGFydDogSW5kaWNlcywgaXNUcmF2ZXJzYWJsZTogUHJlZGljYXRlW0FdLCBncmlkOiBHcmlkW0FdKSA9IHsKICAgICAgICB2YWwgeGJvdW5kID0gZ3JpZC5sZW5ndGgKICAgICAgICB2YWwgeWJvdW5kID0gZ3JpZCgwKS5sZW5ndGgKICAgICAgICB2YWwgYm91bmRhcnlQcmVkID0gKHh5OiBJbmRpY2VzLCBhOiBBKSA9PiB7CiAgICAgICAgICAgIHZhbCAoeCwgeSkgPSB4eQogICAgICAgICAgICAoKHggPT0gMCkgfHwgKHggPT0geGJvdW5kIC0gMSkgfHwgKHkgPT0gMCkgfHwgKHkgPT0geWJvdW5kIC0gMSkpICYmICh4eSAhPSBzdGFydCkKICAgICAgICB9CiAgICAgICAgZmluZFVua25vd25GaW5pc2goc3RhcnQsIGJvdW5kYXJ5UHJlZCwgaXNUcmF2ZXJzYWJsZSwgZ3JpZCkKICAgIH0KCiAgICBkZWYgcHJpbnRNYXplR3JpZFtBXShncmlkOiBHcmlkW0FdKSA9IHsKICAgICAgICBncmlkLmZvcmVhY2ggeyByb3cgPT4gcHJpbnRsbihyb3cubWtTdHJpbmcoIiAiKSkgfTsKICAgICAgICBwcmludGxuKCk7CiAgICB9CgogICAgZGVmIHByaW50UGF0aChwYXRoOiBMaXN0W0luZGljZXNdKSB7CiAgICAgICAgcGF0aC5mb3JlYWNoKHByaW50bG4oXykpOwogICAgICAgIHByaW50bG4oKTsKICAgIH0KfQoKb2JqZWN0IE1haW4gZXh0ZW5kcyBBcHAgewoJdmFsIG1hemVfMDEgPSBBcnJheShBcnJheSgxLDEsMSwxLDEsMSwwKSwKICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkoMCwwLDAsMCwwLDAsMCksCiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5KDEsMSwxLDEsMSwxLDApLAogICAgICAgICAgICAgICAgICAgICAgICBBcnJheSgwLDAsMCwwLDAsMCwwKSwKICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkoMCwxLDEsMSwxLDEsMSksCiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5KDAsMCwwLDAsMCwwLDApLAogICAgICAgICAgICAgICAgICAgICAgICBBcnJheSgxLDEsMSwwLDEsMSwxKSwKICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkoMCwwLDAsMCwwLDAsMCksCiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5KDAsMSwxLDEsMSwxLDApKQoKICAgIHZhbCBtYXplXzAyID0gQXJyYXkoInh4eHh4eHh4eHh4eHh4eHh4eHh4eCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4ICAgICAgICAgICAgeCAgICAgIHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieHggeHh4eCB4eHh4eHggeHh4ICB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInggICB4ICAgeCAgICAgIHggeHggeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4IHh4eHh4IHh4eHh4eHh4ICB4IHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieCB4ICAgICAgICAgICAgICB4eCB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInh4eHh4eCAgeHh4eHggeHh4eCAgeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4ICAgIHh4eHggICB4IHggICAgIHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieCB4eCAgeCB4IHggeCB4IHggeHh4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInggIHh4IHggICB4IHggeCB4ICAgeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4eCAgeCB4IHggeHh4IHh4eCB4eHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieCAgeHggICB4ICAgICAgICAgICB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInh4eHggIHggeHh4eHh4IHh4eHggeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4ICAgIHh4IHggeCAgICB4ICAgIHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieHh4eHh4ICB4IHggeHh4eHggeHh4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInggICAgICB4eCB4ICAgICB4IHggeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4eHggeCB4eCAgeHh4IHh4eCB4IHgiLAogICAgICAgICAgICAgICAgICAgICAgICAieCB4IHggICAgICAgeCAgIHggICB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgInggeCB4eHh4eHggeHh4eCB4eHggeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ4ICAgICAgeCAgICAgICAgICAgb3giLAogICAgICAgICAgICAgICAgICAgICAgICAieCB4eHh4eHh4eHh4eHh4eHh4eHh4IikubWFwKF8udG9BcnJheSkKCiAgICB2YWwgbWF6ZV8wMyA9IEFycmF5KCIjIyMjIyMjIyMjIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICAgICAgICAgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICMjIyMjICMgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIgICAgIyAgICMgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjIyMgIyAjIyMgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICAgICAjICAgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICMgIyMjICMjIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICMgICAjICAgICIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICMjIyAjICMgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjICAgICAjICAgIyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIjIyMjIyMjIyMjIyIpLm1hcChfLnRvQXJyYXkpCiAgICAKICAgIHZhbCBtYXplMV9zMSA9IE1hemVTb2x2ZXIuZmluZEtub3duRmluaXNoKHN0YXJ0ID0gKDEsMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmlzaCA9ICg4LDYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVHJhdmVyc2FibGUgPSAoeDogSW50KSA9PiAoeCA9PSAwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkID0gbWF6ZV8wMSkKCiAgICAgICAgdmFsIG1hemUyX3MxID0gTWF6ZVNvbHZlci5maW5kVW5rbm93bkZpbmlzaChzdGFydCA9ICgxLDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNGaW5pc2ggPSAoeHk6IChJbnQsIEludCksIGM6IENoYXIpID0+IChjID09ICdvJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RyYXZlcnNhYmxlID0gKGM6IENoYXIpID0+IChjICE9ICd4JyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkID0gbWF6ZV8wMikKCiAgICAgICAgdmFsIG1hemUyX3MyID0gTWF6ZVNvbHZlci5lc2NhcGVNYXplKHN0YXJ0ID0gKDEsMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVHJhdmVyc2FibGUgPSAoYzogQ2hhcikgPT4gKGMgIT0gJ3gnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZCA9IG1hemVfMDIpCgogICAgICAgIHZhbCBtYXplM19zMSA9IE1hemVTb2x2ZXIuZXNjYXBlTWF6ZVYyKHN0YXJ0ID0gKDMsMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNUcmF2ZXJzYWJsZSA9IChjOiBDaGFyKSA9PiAoYyAhPSAnIycpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyaWQgPSBtYXplXzAzKQoKICAgICAgICB2YWwgbWF6ZTNfczIgPSBNYXplU29sdmVyLmVzY2FwZU1hemVWMihzdGFydCA9ICg3LDEwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RyYXZlcnNhYmxlID0gKGM6IENoYXIpID0+IChjICE9ICcjJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZCA9IG1hemVfMDMpCgogICAgICAgIE1hemVTb2x2ZXIucHJpbnRNYXplR3JpZChtYXplXzAxKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRQYXRoKG1hemUxX3MxKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRNYXplR3JpZChtYXplXzAyKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRQYXRoKG1hemUyX3MxKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRQYXRoKG1hemUyX3MyKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRNYXplR3JpZChtYXplXzAzKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRQYXRoKG1hemUzX3MxKQogICAgICAgIE1hemVTb2x2ZXIucHJpbnRQYXRoKG1hemUzX3MyKQp9
stdout
1 1 1 1 1 1 0
0 0 0 0 0 0 0
1 1 1 1 1 1 0
0 0 0 0 0 0 0
0 1 1 1 1 1 1
0 0 0 0 0 0 0
1 1 1 0 1 1 1
0 0 0 0 0 0 0
0 1 1 1 1 1 0
(1,0)
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
(1,6)
(2,6)
(3,6)
(3,5)
(3,4)
(3,3)
(3,2)
(3,1)
(3,0)
(4,0)
(5,0)
(5,1)
(5,2)
(5,3)
(6,3)
(7,3)
(7,4)
(7,5)
(7,6)
(8,6)
x x x x x x x x x x x x x x x x x x x x x
x x x
x x x x x x x x x x x x x x x x
x x x x x x x
x x x x x x x x x x x x x x x x
x x x x x
x x x x x x x x x x x x x x x x
x x x x x x x x
x x x x x x x x x x x x
x x x x x x x x x
x x x x x x x x x x x x x x
x x x x x
x x x x x x x x x x x x x x x x
x x x x x x x
x x x x x x x x x x x x x x x x
x x x x x x x
x x x x x x x x x x x x x x
x x x x x x
x x x x x x x x x x x x x x x x
x x o x
x x x x x x x x x x x x x x x x x x x x
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
(1,6)
(1,7)
(2,7)
(3,7)
(4,7)
(5,7)
(5,8)
(5,9)
(5,10)
(5,11)
(5,12)
(5,13)
(6,13)
(7,13)
(8,13)
(9,13)
(10,13)
(11,13)
(11,14)
(11,15)
(11,16)
(11,17)
(11,18)
(11,19)
(12,19)
(13,19)
(13,18)
(13,17)
(14,17)
(15,17)
(16,17)
(17,17)
(17,18)
(17,19)
(18,19)
(19,19)
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
(1,6)
(1,7)
(2,7)
(3,7)
(4,7)
(5,7)
(5,8)
(5,9)
(5,10)
(5,11)
(5,12)
(5,13)
(6,13)
(7,13)
(8,13)
(9,13)
(10,13)
(11,13)
(11,12)
(11,11)
(11,10)
(11,9)
(10,9)
(9,9)
(9,8)
(9,7)
(10,7)
(11,7)
(12,7)
(13,7)
(14,7)
(14,6)
(15,6)
(15,5)
(15,4)
(15,3)
(16,3)
(17,3)
(18,3)
(19,3)
(19,2)
(19,1)
(20,1)
# # # # # # # # # # #
# #
# # # # # # # #
# # #
# # # # # # # #
# # #
# # # # # # # #
# # #
# # # # # # #
# # #
# # # # # # # # # # #
(3,0)
(3,1)
(2,1)
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
(1,6)
(1,7)
(1,8)
(1,9)
(2,9)
(3,9)
(4,9)
(5,9)
(5,8)
(5,7)
(6,7)
(7,7)
(7,8)
(7,9)
(7,10)
(7,10)
(7,9)
(7,8)
(7,7)
(6,7)
(5,7)
(5,8)
(5,9)
(4,9)
(3,9)
(2,9)
(1,9)
(1,8)
(1,7)
(1,6)
(1,5)
(1,4)
(1,3)
(1,2)
(1,1)
(2,1)
(3,1)
(3,0)