FrontEnd/프로그래머스

[JS] 2차원 동전 뒤집기

728x90

동전뒤집기 문제에서 생각할 점은 어느 칸이던 같은 줄을 2번이상 뒤집는건 의미가 없다는 것이다.

 

즉 , 가로 1~10 세로 1~10 까지 있다고 가정한다면 

 

가로 3번째 라인을 1번뒤집나 3번뒤집나 5번 뒤집나 해당 라인의 결과는 같게 된다.

 

따라서 모든 라인의 줄을 최대 1번까지만 뒤집을 수 있다고 생각할 수 있다.

 

 

그다음으로 생각해야 할점은 순서가 상관이 없다는 것이다.

 

가로 3번 -> 세로2번 -> 가로 6번 이런식으로 뒤집나

세로 2번 -> 가로 6번 -> 가로3번 이런식으로 뒤집나 결과가 같게 나온다.

 

 

 

즉 위 문제는 2^10으로 나오는 완전탐색을 할 필요가 없다! 10번의 경우만 체크하면 된다.

 

 

 

1. 우선 문제를 조금 간략화 하기 위해서 beginning과 target 배열을 비교해서 같으면 false 다르면 true로 반환한다.

위 과정을 통해서 beginning을 target으로 만드는 문제가 아닌, 배열을 false로 만들면 되는 문제로 변하였다.

 

2. 먼저 세로줄의 맨 위칸을 모두 false로 만들어주게 세로줄을 바꿔준다.

3. 그 이후 가로줄의 첫 열을 모두 false로 만들어주게 가로줄을 바꿔준다.

 

2-3 번과정을 거치면서 바꿔야 할 점을 모두 찾을 수 있다.

 

하지만 이 경우 예외케이스가 2가지 더 발생하게 된다.

 

첫열 첫행 즉 [0][0]에 해당하는 부분이 2번 바뀌어야 할때 방금과 같은 로직으로는 무조건 행부터 바꾸기 때문에 예외가 생길 수 있다. 따라서 열부터도 검사를 해주는 과정이 필요하다.

 

단, 해당 부분이 2번바뀌어야 할때 행-> 열 열-> 행 2가지 케이스를 검사를 해주어야 하므로 총 케이스는 3가지가 나오게 된다.

 

 

 

약간 구조화를 마지막에 잘 못한 문제인 같아 접근은 잘 이해했는데 해결이 아쉬운 문제였다.

 

function solution(beginning, target) {
    let map = [...Array(beginning.length)].map(_ => Array(beginning[0].length).fill(false))
    const rLen = beginning.length
    const cLen = beginning[0].length
    
    const clearMap = () => {
        for (let i = 0 ; i < rLen ; i++){
            for (let j = 0 ; j< cLen ;j++){
                if (beginning[i][j]!==target[i][j]) map[i][j] = true
                else map[i][j] = false
            }
        }
    }
    
    
    const changeRow = (n) => {
        for (let i = 0 ; i < cLen ; i++) map[n][i] = !map[n][i]
    }
    const changeCol = (n) => {
        for (let i = 0 ; i < rLen ; i++) map[i][n] = !map[i][n]
    }
    
    const reverseCol = (ret) => {
        for (let i = 0 ; i < cLen ; i++){
            if (map[0][i]) {
                changeCol(i)
                ret ++
            }
        }
        return ret
    }
    
    const reverseRow = (ret) => {
        for (let i = 0 ; i < rLen ; i++){
            if(map[i][0]) {
                changeRow(i)
                ret ++
            }
        }
        return ret
    }
    
    
    let ret = []
    
    clearMap()
    let tmp = 0
    tmp = reverseCol(tmp)
    tmp = reverseRow(tmp)
    for (let i = 0 ; i < rLen ; i++){
        for (let j = 0 ; j < cLen ; j++){
            if(map[i][j]) return -1
        }
    }
    ret.push(tmp)
    
    clearMap()
    tmp = 1
    changeCol(0)
    tmp = reverseRow(tmp)
    tmp = reverseCol(tmp)
    for (let i = 0 ; i < rLen ; i++){
        for (let j = 0 ; j < cLen ; j++){
            if(map[i][j]) return -1
        }
    }
    ret.push(tmp)
    
    clearMap()
    tmp = 1
    changeRow(0)
    tmp = reverseCol(tmp)
    tmp = reverseRow(tmp)
    for (let i = 0 ; i < rLen ; i++){
        for (let j = 0 ; j < cLen ; j++){
            if(map[i][j]) return -1
        }
    }
    ret.push(tmp)
    
    clearMap()
    let cRet = 1
    changeCol(0)
    cRet = reverseRow(cRet)
    cRet = reverseCol(cRet)
    for (let i = 0 ; i < rLen ; i++){
        for (let j = 0 ; j < cLen ; j++){
            if(map[i][j]) return -1
        }
    }
    
    return Math.min(...ret)
}
728x90

'FrontEnd > 프로그래머스' 카테고리의 다른 글

[JS] 카운트 다운  (0) 2023.10.24
[JS] 고고학 최고의 발견  (0) 2023.10.23
[JS] 부대복귀  (1) 2023.10.21
[JS,Python] 등대  (1) 2023.10.20
[JS] 숫자 타자 대회  (1) 2023.10.19