Problem:
ブロック

A さんの家に親戚の B 君がやってきました。彼は 3 歳でブロックが大好きです。彼が持っているブロックは図 1 のような形をしています。

図1

B 君はボードの上にブロックを敷き詰めています。彼に「何を作っているの?」と聞くと、彼は「迷路!!」と元気よく答えました。彼の言う迷路とは、スタートからゴールまで側面が接している、同じ色のブロックだけでたどることができるブロックの配置のことだそうです。図 2 は黄色のブロックにより、左上(スタート)から右下(ゴール)へ迷路ができていることを表しています。

図2

無邪気に遊んでいる B 君を横目に、プログラマーであるあなたは、ブロックの並びが迷路となっているかを確かめてみることにしました。

ブロックの情報とスタート、ゴールの座標を入力とし、ブロックが迷路となっていれば OK 、なっていなければ NG を出力するプログラムを作成してください。 ボードは横方向に w 、縦方向に h の大きさをもち、 左上の座標は(1 , 1)、右下の座標は(w, h)とします。ブロックは 2 × 4 の長方形ですべて同じ大きさです。ブロックの色 c は 1 (白)、2 (黄)、3 (緑)、4 (青)、5 (赤) のいずれかです。ブロックのボード上での向き d は 横方向に長い場合 0 、 縦方向に長い場合 1 とします。 ブロックの位置はブロックの左上の座標 (x, y) によって表されます。なお、ブロックの位置は他のブロックと重なることは無く、ボードからはみ出すこともありません。

Input

複数のデータセットの並びが入力として与えられます。 入力の終わりはゼロふたつの行で示されます。
各データセットは以下の形式で与えられます。

w h
xs ys
xg yg
n
c1 d1 x1 y1
c2 d2 x2 y2
:
cn dn xn yn

1 行目にボードの大きさw, h (4 ≤ w, h ≤ 100) が与えられます。2 行目にスタートの座標 xs, ys、3 行目にゴールの座標 xg, yg が与えられます。

4 行目にブロックの個数 n が与えられます。続く n 行に i 番目のブロックの色 ci、向き di、位置 xi, yi が与えられます。

データセットの数は 30 を超えません。

Output

入力データセットごとに、判別結果を１行に出力します。

Sample Input

20 20
1 1
9 9
7
2 0 1 1
5 1 1 3
2 1 3 3
1 1 5 2
5 1 7 3
2 0 2 7
2 0 6 8
20 20
9 9
1 1
6
2 0 1 1
1 0 5 1
2 1 1 3
5 0 1 7
3 1 5 5
4 1 8 5
0 0

Output for the Sample Input

OK
NG

Solution in Kotlin (judge verdict: Accepted)

import java.util.*

fun main(args:Array<String>?): Unit {
    val neighbors = listOf(Point(1, 0), Point(-1, 0), Point(0, 1), Point(0, -1))
    while(true){
        val (w, h) = readLine()!!.trim().split(' ').map(String::toInt)
        if (w == 0 && h == 0) return
        val board = Array(h){IntArray(w){0}}
        val (sx, sy) = readLine()!!.trim().split(' ').map(String::toInt)
        val (gx, gy) = readLine()!!.trim().split(' ').map(String::toInt)
        val start = Point(sx - 1, sy - 1)
        val goal = Point(gx - 1, gy - 1)
        val n = readLine()!!.trim().toInt()
        repeat(n){
            val (c, d, x, y) = readLine()!!.trim().split(' ').map(String::toInt)
            for (cell in Block(Point(x - 1, y - 1), d).cells()) {
                board[cell.y][cell.x] = c
            }
        }
        val queue: Queue<Point> = LinkedList()
        if (board[start.y][start.x] != 0) queue.add(start)
        while(queue.isNotEmpty() && queue.peek() != goal){
            val current = queue.poll()
            for (neighbor in neighbors.map{it + current}) if (neighbor.y in 0 until h && neighbor.x in 0 until w && board[neighbor.y][neighbor.x] != 0){
                if (board[current.y][current.x] == board[neighbor.y][neighbor.x]){
                    queue.add(neighbor)
                }
            }
            board[current.y][current.x] = 0
        }
        println(
                if (queue.isNotEmpty()) "OK" else "NG"
        )
    }
}
data class Point(val x: Int, val y: Int) {
    operator fun plus(that: Point): Point = Point(x + that.x, y + that.y)
}
data class Block(val position: Point, val state: Int) {
    fun cells(): Iterable<Point> {
        return when(state){
            0 -> listOf(Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 0),
                    Point(0, 1), Point(1, 1), Point(2, 1), Point(3, 1)).map{it + position}
            else -> listOf(Point(0, 0), Point(0, 1), Point(0, 2), Point(0, 3),
                    Point(1, 0), Point(1, 1), Point(1, 2), Point(1, 3)).map{it + position}
        }
    }
}