Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 267
Good morning! Here's your coding interview problem for today.

This problem was asked by Oracle.

You are presented with an 8 by 8 matrix representing the positions of pieces on a chess board. The only pieces on the board are the black king and various white pieces. Given this matrix, determine whether the king is in check.

For details on how each piece moves, see here.

For example, given the following matrix:
```
...K....
........
.B......
......P.
.......R
..N.....
........
.....Q..
```
You should return True, since the bishop is attacking the king diagonally.

Pull request:
Day267
Resolves #543.

Patch:
diff --git a/README.md b/README.md
index 9af05f1..4dac06d 100644
--- a/README.md
+++ b/README.md
@@ -273,6 +273,7 @@ problems from
 * [Day 260](https://github.com/vaskoz/dailycodingproblem-go/issues/533)
 * [Day 263](https://github.com/vaskoz/dailycodingproblem-go/issues/539)
 * [Day 266](https://github.com/vaskoz/dailycodingproblem-go/issues/542)
+* [Day 267](https://github.com/vaskoz/dailycodingproblem-go/issues/543)
 * [Day 268](https://github.com/vaskoz/dailycodingproblem-go/issues/544)
 * [Day 269](https://github.com/vaskoz/dailycodingproblem-go/issues/547)
 * [Day 270](https://github.com/vaskoz/dailycodingproblem-go/issues/548)
diff --git a/day267/problem.go b/day267/problem.go
new file mode 100644
index 0000000..fdc97bf
--- /dev/null
+++ b/day267/problem.go
@@ -0,0 +1,141 @@
+package day267
+
+// Chessboard is a slice of strings. The first string represents the top row
+// and the last string represents the bottom row of the board.
+// The top is the black player's side and the bottom is the white player's side.
+type Chessboard []string
+
+// IsSoloBlackKingInCheck answers if a solo black king is in check.
+// All other pieces on the board are white pieces.
+func IsSoloBlackKingInCheck(board Chessboard) bool {
+	kR, kC := findBlackKing(board)
+	for r := range board {
+		for c := range board[r] {
+			switch board[r][c] {
+			case 'B':
+				if bishop(board, r, c, kR, kC) {
+					return true
+				}
+			case 'N':
+				if knight(board, r, c, kR, kC) {
+					return true
+				}
+			case 'P':
+				if pawn(board, r, c, kR, kC) {
+					return true
+				}
+			case 'R':
+				if rook(board, r, c, kR, kC) {
+					return true
+				}
+			case 'Q':
+				if queen(board, r, c, kR, kC) {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func knight(_ Chessboard, nR, nC, kR, kC int) bool {
+	return (nR-2 == kR && nC+1 == kC) ||
+		(nR-1 == kR && nC+2 == kC) ||
+		(nR+1 == kR && nC+2 == kC) ||
+		(nR+2 == kR && nC+1 == kC) ||
+		(nR+2 == kR && nC-1 == kC) ||
+		(nR+1 == kR && nC-2 == kC) ||
+		(nR-1 == kR && nC-2 == kC) ||
+		(nR-2 == kR && nC-1 == kC)
+}
+
+func pawn(_ Chessboard, pR, pC, kR, kC int) bool {
+	return (pR-1 == kR && pC-1 == kC) || (pR-1 == kR && pC+1 == kC)
+}
+
+func queen(board Chessboard, qR, qC, kR, kC int) bool {
+	return rook(board, qR, qC, kR, kC) || bishop(board, qR, qC, kR, kC)
+}
+
+func rook(board Chessboard, rR, rC, kR, kC int) bool {
+	// up
+	for r := rR - 1; r >= 0; r-- {
+		if r == kR && rC == kC {
+			return true
+		} else if board[r][rC] != '.' {
+			break
+		}
+	}
+	// left
+	for c := rC - 1; c >= 0; c-- {
+		if rR == kR && c == kC {
+			return true
+		} else if board[rR][c] != '.' {
+			break
+		}
+	}
+	// right
+	for c := rC + 1; c < 8; c++ {
+		if rR == kR && c == kC {
+			return true
+		} else if board[rR][c] != '.' {
+			break
+		}
+	}
+	// down
+	for r := rR + 1; r < 8; r++ {
+		if r == kR && rC == kC {
+			return true
+		} else if board[r][rC] != '.' {
+			break
+		}
+	}
+	return false
+}
+
+func bishop(board Chessboard, bR, bC, kR, kC int) bool {
+	// up-right
+	for r, c := bR-1, bC+1; r >= 0 && c < 8; r, c = r-1, c+1 {
+		if r == kR && c == kC {
+			return true
+		} else if board[r][c] != '.' {
+			break
+		}
+	}
+	// up-left
+	for r, c := bR-1, bC-1; r >= 0 && c >= 0; r, c = r-1, c-1 {
+		if r == kR && c == kC {
+			return true
+		} else if board[r][c] != '.' {
+			break
+		}
+	}
+	// down-right
+	for r, c := bR+1, bC+1; r < 8 && c < 8; r, c = r+1, c+1 {
+		if r == kR && c == kC {
+			return true
+		} else if board[r][c] != '.' {
+			break
+		}
+	}
+	// down-left
+	for r, c := bR+1, bC-1; r < 8 && c >= 0; r, c = r+1, c-1 {
+		if r == kR && c == kC {
+			return true
+		} else if board[r][c] != '.' {
+			break
+		}
+	}
+	return false
+}
+
+func findBlackKing(board Chessboard) (row int, col int) {
+	for row := range board {
+		for col := range board[row] {
+			if board[row][col] == 'K' {
+				return row, col
+			}
+		}
+	}
+	return
+}


Test patch:
diff --git a/day267/problem_test.go b/day267/problem_test.go
new file mode 100644
index 0000000..4a92d0e
--- /dev/null
+++ b/day267/problem_test.go
@@ -0,0 +1,183 @@
+package day267
+
+import "testing"
+
+// nolint
+var testcases = []struct {
+	board   Chessboard
+	inCheck bool
+}{
+	{
+		Chessboard{
+			"...K....",
+			"........",
+			".B......",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			".....Q..",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"...K....",
+			"........",
+			".P..N...",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			".....Q..",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"...K....",
+			"..P.....",
+			".P..N...",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			".....Q..",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"...K....",
+			"........",
+			".P......",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"...R.Q..",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"K.......",
+			"........",
+			".P......",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"...R...Q",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"Q.......",
+			"........",
+			".PK.....",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"...R....",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"....Q...",
+			"........",
+			".PK.....",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"...R....",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"........",
+			"........",
+			".PK...R.",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"........",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"........",
+			"........",
+			"Q.K.....",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"........",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"..R.....",
+			"........",
+			"..K.....",
+			"......P.",
+			".......R",
+			"..N.....",
+			"........",
+			"........",
+		},
+		true,
+	},
+	{
+		Chessboard{
+			"...K....",
+			"........",
+			"........",
+			"PPPPPPPP",
+			".B.....R",
+			"P.N.....",
+			"....Q...",
+			".R......",
+		},
+		false,
+	},
+	{ // missing king
+		Chessboard{
+			"........",
+			"........",
+			"........",
+			"PPPPPPPP",
+			".B.....R",
+			"P.N.....",
+			"....Q...",
+			".R......",
+		},
+		false,
+	},
+}
+
+func TestIsSoloBlackKingInCheck(t *testing.T) {
+	t.Parallel()
+	for tcid, tc := range testcases {
+		if result := IsSoloBlackKingInCheck(tc.board); result != tc.inCheck {
+			t.Errorf("testcase id:%d expected %v, got %v", tcid, tc.inCheck, result)
+		}
+	}
+}
+
+func BenchmarkIsSoloBlackKingInCheck(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			IsSoloBlackKingInCheck(tc.board)
+		}
+	}
+}