Skip to content

Instantly share code, notes, and snippets.

@mununki
Last active April 18, 2022 18:11
Show Gist options
  • Save mununki/1baafc810643e846018edb472c574162 to your computer and use it in GitHub Desktop.
Save mununki/1baafc810643e846018edb472c574162 to your computer and use it in GitHub Desktop.
프로그래머스 코테 - 체스
open Belt
module rec Board: {
type rec t
and coord = (row, col)
and size = int
and col
and row
let init: size => t
let postPieces: (t, list<string>) => t
let markMovesOf: (t, list<string>) => t
let countOfUnMarked: t => int
} = {
exception Invalid_Operation(string)
type rec coord = (row, col)
and row = int
and col = int
and size = int
and canGo = bool
and statusOfCoord = NotOccupied(canGo) | Occupied(Piece.t)
module CoordCmp = Belt.Id.MakeComparable({
type t = coord
let cmp = (a, b) => Pervasives.compare(a, b)
})
type rec t = Belt.Map.t<CoordCmp.t, statusOfCoord, CoordCmp.identity>
let init = size => {
let rows = Array.makeBy(size, x => x + 65) // "A" = 65
let cols = Array.makeBy(size, x => x + 1)
let cells =
rows
->Array.map(r => cols->Array.map(c => (r, c)))
->Array.concatMany
->Array.map(c => (c, NotOccupied(false)))
cells->Map.fromArray(~id=module(CoordCmp))
}
let genCoord = piece =>
switch piece->Js.String2.split("") {
| [row, col] => {
let convertRow = row => {
let re = %re("/[ABCDEFGH]/")
let isValid = re->Js.Re.test_(row)
if isValid {
row->String.get(0)->Char.code->Some
} else {
None
}
}
switch (row->convertRow, col->Int.fromString) {
| (Some(row), Some(col)) => (row, col)
| _ => raise(Invalid_Operation(`Cann't generate the coord`))
}
}
| _ => raise(Invalid_Operation(`Cann't generate the coord`))
}
let postPiece: (t, coord, Piece.t) => t = (board, coord, piece) =>
switch board->Map.get(coord) {
| None => raise(Invalid_Operation(`Cann't find the cell`))
| Some(Occupied(_)) => raise(Invalid_Operation(`The position is taken`))
| Some(NotOccupied(_)) => board->Map.set(coord, Occupied(piece))
}
let rec postPieces = (board, pieces) =>
switch pieces {
| list{} => board
| list{hd, ...tl} => {
let coord = genCoord(hd)
let newBoard = board->postPiece(coord, Piece.Bishop)
postPieces(newBoard, tl)
}
}
let markMoves: (t, coord, Piece.t) => t = (board, coord, piece) => {
let rec markMovesAuxInfinite = (board, coord, direction) => {
let (row, col) = coord
let (deltaOfRow, deltaOfCol) = direction
let newCoord = (row + deltaOfRow, col + deltaOfCol)
switch board->Map.get(newCoord) {
| None
| Some(Occupied(_)) => board
| Some(NotOccupied(_)) => {
let newBoard = board->Map.set(newCoord, NotOccupied(true))
markMovesAuxInfinite(newBoard, newCoord, direction)
}
}
}
let rec markMovesAux = (board, coord, directions) => {
switch directions {
| list{} => board
| list{hd, ...tl} =>
switch piece {
| Bishop => {
let newBoard = markMovesAuxInfinite(board, coord, hd)
markMovesAux(newBoard, coord, tl)
}
}
}
}
markMovesAux(board, coord, piece->Piece.directions)
}
let rec markMovesOf = (board, pieces) =>
switch pieces {
| list{} => board
| list{hd, ...tl} => {
let coord = genCoord(hd)
let newBoard = board->markMoves(coord, Piece.Bishop)
markMovesOf(newBoard, tl)
}
}
let countOfUnMarked = board =>
board->Map.reduce(0, (acc, _, v) =>
switch v {
| Occupied(_) => acc
| NotOccupied(true) => acc
| NotOccupied(false) => acc + 1
}
)
}
and Piece: {
type rec t = Bishop // 모든 기물을 추가하진 않고 비숍만 추가함
and deltaOfCol = int
and deltaOfRow = int
and direction = (deltaOfRow, deltaOfCol)
and directions = list<direction>
let directions: t => directions
} = {
type rec t = Bishop
and deltaOfCol = int
and deltaOfRow = int
and direction = (deltaOfRow, deltaOfCol)
and directions = list<direction>
let directions = t =>
switch t {
| Bishop => list{(1, 1), (1, -1), (-1, 1), (-1, -1)}
}
}
let solution = pieces => {
let board = Board.init(8)
let pieces = pieces->List.fromArray
board->Board.postPieces(pieces)->Board.markMovesOf(pieces)->Board.countOfUnMarked
}
// 8 x 8 체스 보드에 대각선으로 움직일 수 있는 비숍이 배열로 주어지는 경우
// 비숍이 움직이지 못하는 보드 셀의 개수를 구하라.
// ["C6"] => 52
// ["C6", "A4", "E5"] => 35
module rec Board: {
type rec t
and coord = (row, col)
and size = int
and col
and row
let init: size => t
let postPieces: (t, list<string>) => t
let markMovesOf: (t, list<string>) => t
let countOfUnMarked: t => int
}
and Piece: {
type rec t = Bishop
and deltaOfCol = int
and deltaOfRow = int
and direction = (deltaOfRow, deltaOfCol)
and directions = list<direction>
let directions: t => directions
}
let solution: array<string> => int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment