Level
프로그래머스 Lv3
Day
20일
kakao
2020 카카오 블라인드
 
function solution(n, build_frame) {
    var answer = []
    const built = Array(n+1).fill(0).map(r => Array(n+1).fill(16))
    
    const canBuild = (x,y,type) => {
        if(type==='pillar'){
            // 바닥일 떄
            if(y===0) return true
            
            // 기둥 머리, 보 앞, 보 뒤가 있을 떄 0111
            if(built[y][x] & 7) return true
            
            return false
        }
        
        if(type==='floor'){
            if(built[y][x] & 4) return true // 기둥 머리
            if(built[y][x+1] & 4) return true // 뒤가 기둥 머리
            
            if((built[y][x] & 1) && (built[y][x+1] & 2)) return true // 보 사이
               
            return false
        }
    } 
    
    const canDelete = (x,y, type) => {
        for(let dx=-1; dx<2; dx++){
            for(let dy=-1; dy<2; dy++){
                const xx = x + dx
                const yy = y + dy
                
                if(yy < 0 || yy > n || xx < 0 || xx > n) continue;
                const frame = built[yy][xx]
            
                if(frame & 2){
                    if(!canBuild(xx,yy,'floor')) return false;
                }

                if(frame & 8){
                    if(!canBuild(xx,yy, 'pillar')) return false;
                }
            }
        }
        
        return true;
    }
    
        
    build_frame.forEach(frame => {
        const [x, y, isFloor, shouldBuild] = frame
        
        const action = shouldBuild ? 'build' : 'delete'
        const type = isFloor ? 'floor' : 'pillar'
        
        if(action==='build' && canBuild(x,y,type)){
            if(type==='pillar'){
                built[y][x] |= 8
                built[y+1][x] |= 4
            }
            
            if(type==='floor'){
                built[y][x] |= 2
                built[y][x+1] |= 1
            }                              
        }
        
         if(action==='delete'){
            if(type==='pillar'){
                built[y][x] &= 7
                built[y+1][x] &= 11
                
                if(!canDelete(x,y, type)){
                     built[y][x] |= 8
                     built[y+1][x] |= 4                   
                }
            }
            
            if(type==='floor'){
                built[y][x] &= 13
                built[y][x+1] &= 14
                
                if(!canDelete(x,y, type)){
                     built[y][x] |= 2
                     built[y][x+1] |= 1                   
                }
            }
        }
    })     

    for(let x=0; x<n+1; x++){
        for(let y=0; y<n+1; y++){
            if(built[y][x] & 8){
                answer.push([x,y,0])
            }
            if(built[y][x] & 2){
                answer.push([x,y,1])   
            }
        }
    }
    
    console.log(answer)
    
    return answer
}
 
실패 (테케만 통과)
function solution(n, build_frame) {
    var answer = []
    const built = Array(n+1).fill(0).map(r => Array(n+1).fill(16))
    
    const canBuild = (x,y,type) => {
        if(type==='pillar'){
            // 바닥일 떄
            if(y===0) return true
            
            // 기둥 머리, 보 앞, 보 뒤가 있을 떄 0111
            if(built[y][x] & 7) return true
            
            return false
        }
        
        if(type==='floor'){
            if(built[y][x] & 4) return true // 기둥 머리
            if(built[y][x+1] & 4) return true // 뒤가 기둥 머리
            
            if((built[y][x] & 1) && (built[y][x+1] & 2)) return true // 보 사이
               
            return false
        }
    } 
    const canDelete = (x,y, type) => {
        if(type==='pillar'){
            if(built[y+1][x] & 8){
                if(!canBuild(x, y+1, 'pillar')) return false;
            }
            if(built[y][x] & 2){
                if(!canBuild(x,y, 'floor')) return false;
            }
            if(built[y][x] & 1){
                if(!canBuild(x-1,y,'floor')) return false;
            }
        }
        
        if(type==='floor'){    
            if(built[y][x+1] & 8){
                if(!canBuild(x+1, y, 'pillar')) return false
            }            
            if(built[y][x] & 8){
                if(!canBuild(x, y, 'pillar')) return false
            }            
            if(built[y][x+1] & 2){
                if(!canBuild(x+1, y, 'floor')) return false
            }
            if(built[y][x-1] & 2){
                if(!canBuild(x-1, y, 'floor')) return false
            }      
        }
        
        return true;
    }
    
        
    build_frame.forEach(frame => {
        const [x, y, isFloor, shouldBuild] = frame
        
        const action = shouldBuild ? 'build' : 'delete'
        const type = isFloor ? 'floor' : 'pillar'
        
        if(action==='build' && canBuild(x,y,type)){
            if(type==='pillar'){
                built[y][x] |= 8
                built[y+1][x] |= 4
            }
            
            if(type==='floor'){
                built[y][x] |= 2
                built[y][x+1] |= 1
            }                              
        }
        
         if(action==='delete'){
            if(type==='pillar'){
                built[y][x] &= 7
                built[y+1][x] &= 11
                
                if(!canDelete(x,y, type)){
                     built[y][x] |= 8
                     built[y+1][x] |= 4                   
                }
            }
            
            if(type==='floor'){
                built[y][x] &= 13
                built[y][x+1] &= 14
                
                if(!canDelete(x,y, type)){
                     built[y][x] |= 2
                     built[y][x+1] |= 1                   
                }
            }
        }
    })     

    for(let x=0; x<n+1; x++){
        for(let y=0; y<n+1; y++){
            if(built[y][x] & 8){
                answer.push([x,y,0])
            }
            if(built[y][x] & 2){
                answer.push([x,y,1])   
            }
        }
    }
    return answer
}