ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코딩테스트 / 혼자서 하는 틱택토
    코딩 테스트/Level 2 2023. 2. 25. 18:16
    반응형

    https://school.programmers.co.kr/learn/courses/30/lessons/160585

    이런저런 케이스를 다 생각해서 풀어야 하는 문제... 

    1. 선공인 O와 후공인 X의 개수가 1 이상 나면 안 된다. 
    2. O와 X가 동시에 이겨서는 안 된다. 
    3. O가 이겼을 때 다음 X는 없다. 그러므로 O가 X보다 1개 많아야.. 
    4. X가 이겼을 때 다음 O는 없다. 그러므로 O와 X의 개수가 같아야.. 

    코틀린

    class Solution {
        private fun countMarker(board: Array<String>): Pair<Int, Int> {
            var (oCounter, xCounter) = arrayOf(0, 0)
            for (line in board)
                for (each in line)
                    if (each == 'O')
                        oCounter++
                    else if (each == 'X')
                        xCounter++
            return Pair(oCounter, xCounter)
        }
    
        private fun countWin(board: Array<String>): Pair<Int, Int> {
            var (oWin, xWin) = arrayOf(0, 0)
            for (i in 0..2) {
                var (oRow, xRow, oCol, xCol) = arrayOf(0, 0, 0, 0)
                for (j in 0..2) {
                    when (board[i][j]) {
                        'O' -> oRow++
                        'X' -> xRow++
                    }
                    when (board[j][i]) {
                        'O' -> oCol++
                        'X' -> xCol++
                    }
                }
                oWin += (if (oRow == 3) 1 else 0) + if (oCol == 3) 1 else 0
                xWin += (if (xRow == 3) 1 else 0) + if (xCol == 3) 1 else 0
            }
            var (oCnt1, xCnt1, oCnt2, xCnt2) = arrayOf(0, 0, 0, 0)
            for (i in 0..2) {
                oCnt1 += if (board[i][i] == 'O') 1 else 0
                xCnt1 += if (board[i][i] == 'X') 1 else 0
                oCnt2 += if (board[i][2 - i] == 'O') 1 else 0
                xCnt2 += if (board[i][2 - i] == 'X') 1 else 0
            }
            oWin += (if (oCnt1 == 3) 1 else 0) + if (oCnt2 == 3) 1 else 0
            xWin += (if (xCnt1 == 3) 1 else 0) + if (xCnt2 == 3) 1 else 0
            return Pair(oWin, xWin)
        }
    
        fun solution(board: Array<String>): Int {
            val (oCounter, xCounter) = countMarker(board)
            if (oCounter - xCounter !in 0..1)
                return 0
            val (oWin, xWin) = countWin(board)
            if ((oWin > 0 && xWin > 0) || (oWin > 0 && oCounter != xCounter + 1) || (xWin > 0 && oCounter != xCounter))
                return 0
            return 1
        }
    }
    class Solution {
        private fun countWin(board: Array<String>, marker: Char): Int {
            var win = board.map { row -> row.count { it == marker } }.count { it == 3 }
            win += (0..2).map { i -> ((0..2).map { j -> board[j][i] }) }.map { col -> col.count { it == marker } }.count { it == 3 }
            win += if ((0..2).count { board[it][it] == marker } == 3) 1 else 0
            win += if ((0..2).count { board[it][2 - it] == marker } == 3) 1 else 0
            return win
        }
    
        fun solution(board: Array<String>): Int {
            val countMarker = { array: Array<String>, marker: Char -> array.sumOf { row -> row.count { it == marker } } }
            val (oCounter, xCounter) = Pair(countMarker(board, 'O'), countMarker(board, 'X'))
            val (oWin, xWin) = Pair(countWin(board, 'O'), countWin(board, 'X'))
            return if ((oCounter - xCounter !in 0..1) || (oWin > 0 && xWin > 0) || (oWin > 0 && oCounter != xCounter + 1) || (xWin > 0 && oCounter != xCounter)) 0 else 1
        }
    }

     

    파이썬

    리스트 컴프리헨션에서 이중포문을 쓰는 건 좋지 않다. (하지만 썼다.)

    def count_win(board):
        win_o = win_x = 0
        for i in range(3):
            row_o = row_x = col_o = col_x = 0
            for j in range(3):
                if board[i][j] == 'O':
                    row_o += 1
                elif board[i][j] == 'X':
                    row_x += 1
                if board[j][i] == 'O':
                    col_o += 1
                elif board[j][i] == 'X':
                    col_x += 1
            win_o += (1 if row_o == 3 else 0) + (1 if col_o == 3 else 0)
            win_x += (1 if row_x == 3 else 0) + (1 if col_x == 3 else 0)
        cnt_o_1 = cnt_x_1 = cnt_o_2 = cnt_x_2 = 0
        for i in range(3):
            cnt_o_1 += 1 if board[i][i] == 'O' else 0
            cnt_x_1 += 1 if board[i][i] == 'X' else 0
            cnt_o_2 += 1 if board[i][2 - i] == 'O' else 0
            cnt_x_2 += 1 if board[i][2 - i] == 'X' else 0
        win_o += (1 if cnt_o_1 == 3 else 0) + (1 if cnt_o_2 == 3 else 0)
        win_x += (1 if cnt_x_1 == 3 else 0) + (1 if cnt_x_2 == 3 else 0)
        return win_o, win_x
    
    
    def solution(board):
        count_o, count_x = tuple(map(sum, zip(*((each == 'O', each == 'X') for line in board for each in line))))
        if count_o - count_x not in (0, 1):
            return 0
        win_o, win_x = count_win(board)
        if (win_o > 0 and win_x > 0) or (win_o > 0 and count_o != count_x + 1) or (win_x > 0 and count_o != count_x):
            return 0
        return 1

     

    (O(n)을 고려하여) 한번에 'O'와 'X'를 처리하니 코드가 지저분하다. O(n)을 포기했다.
    (과연 이래도 좋은가 애매하다. 읽기 좋은 코드가 선호되는 추세이긴 하다.)

    def count_win(board, marker):
        win = cnt1 = cnt2 = 0
        for i in range(3):
            row = col = 0
            for j in range(3):
                if board[i][j] == marker:
                    row += 1
                if board[j][i] == marker:
                    col += 1
            win += (1 if row == 3 else 0) + (1 if col == 3 else 0)
        for i in range(3):
            cnt1 += 1 if board[i][i] == marker else 0
            cnt2 += 1 if board[i][2 - i] == marker else 0
        win += (1 if cnt1 == 3 else 0) + (1 if cnt2 == 3 else 0)
        return win
    
    
    def solution(board):
        count_o, count_x = tuple(map(sum, zip(*((each == 'O', each == 'X') for line in board for each in line))))
        win_o, win_x = count_win(board, 'O'), count_win(board, 'X')
        if count_o - count_x not in (0, 1) or (win_o > 0 and win_x > 0) \
                or (win_o > 0 and count_o != count_x + 1) or (win_x > 0 and count_o != count_x):
            return 0
        return 1

     

    깔끔하게.. 

    def count_win(board, marker):
        win = sum(all(each == marker for each in row) for row in board)
        win += sum(all(each == marker for each in col) for col in zip(*board))
        win += all(board[i][i] == marker for i in range(3))
        win += all(board[i][2 - i] == marker for i in range(3))
        return win
    
    
    def solution(board):
        count_o, count_x = tuple(map(sum, zip(*((each == 'O', each == 'X') for line in board for each in line))))
        win_o, win_x = count_win(board, 'O'), count_win(board, 'X')
        if count_o - count_x not in (0, 1) or (win_o > 0 and win_x > 0) \
                or (win_o > 0 and count_o != count_x + 1) or (win_x > 0 and count_o != count_x):
            return 0
        return 1

    *board에 주의하자. 

    한 줄 더 줄여보자.. 

    def count_win(board, marker):
        win = sum(all(each == marker for each in row) for row in board)
        win += sum(all(each == marker for each in col) for col in zip(*board))
        win += sum(map(all, zip(*((board[i][i] == marker, board[i][2 - i] == marker) for i in range(3)))))
        return win
    
    
    def solution(board):
        count_o, count_x = tuple(map(sum, zip(*((each == 'O', each == 'X') for line in board for each in line))))
        win_o, win_x = count_win(board, 'O'), count_win(board, 'X')
        if count_o - count_x not in (0, 1) or (win_o > 0 and win_x > 0) \
                or (win_o > 0 and count_o != count_x + 1) or (win_x > 0 and count_o != count_x):
            return 0
        return 1

    그만하자.

    반응형
Designed by Tistory.