[프로그래머스] 자물쇠와 열쇠

2020. 5. 5. 16:35프로그래머스/카카오

import java.util.*;

class Solution {
    class LockInfo{
        int x;
        int y;
        
        LockInfo(int x, int y){ 
        this.x = x;
        this.y = y;
        }
    }
   
    List<LockInfo> allLock = new ArrayList<>();
    
    public boolean solution(int[][] key, int[][] lock) {
        boolean answer = false;
 
        int[][] bigLock = new int[lock.length*3][lock.length*3];
        
        makeBigLock(bigLock,lock);
        
        if(allLock.size()==0){
            return true;
        }
        
        
         for(int i=0; i<4; i++){
                key = rorateKey(key);
                if(compareKey(key,bigLock)){
                    answer=true;
                    break;
                }
            }
        
        return answer;
    }
    
    private int[][] makeBigLock(int[][] bigLock, int[][] lock){
        for(int i=0; i<bigLock.length; i++){
            for(int j=0; j<bigLock.length; j++){
                bigLock[i][j]=3;
            }
        }
        
        for(int i=lock.length; i<lock.length*2; i++){
            for(int j=lock.length; j<lock.length*2; j++){
                bigLock[i][j] = lock[i-lock.length][j-lock.length];
                if(bigLock[i][j]==0){
                    allLock.add(new LockInfo(i,j));
                }
            }
        }
        return bigLock;
    }
    
     private int[][] rorateKey (int[][] key){
        int[][] roratedKey = new int[key.length][key.length];
        
        for (int i=0; i<key.length; i++){
            for(int j=0; j<key.length; j++){
                roratedKey[i][j] = key[key.length-1-j][i];
            }
        }
        return roratedKey;
    }
    
    private boolean compareKey(int[][] key, int[][] bigLock){
        for(int i=0; i<=bigLock.length-key.length; i++){
            for(int j=0; j<=bigLock.length-key.length; j++){
                int[][] copyLock=makeCopyLock(key,bigLock,i, j);
                if(compareCopyLock(key,copyLock,bigLock,i,j)){
                 return true;   
                }
            }
        }
        return false;
    }
    
    private int[][] makeCopyLock (int[][] key,int[][] bigLock,int copyX, int copyY){
        int[][] copyLock = new int[bigLock.length][bigLock.length];
        
        for(int i=0; i<bigLock.length; i++){
            for(int j=0; j<bigLock.length; j++){
                copyLock[i][j] = bigLock[i][j];
            }
        }
        
        for(int i=copyX; i<copyX +key.length; i++){
            for(int j=copyY; j<copyY +key.length; j++){
                copyLock[i][j] = key[i-copyX][j-copyY];
            }
        }
        return copyLock;
    }
    
 private boolean compareCopyLock (int[][] key, int[][] copyLock, int[][] bigLock, int rangeX, int rangeY){
     int count =0;  
     for(int i=rangeX; i< rangeX+key.length; i++){
            for(int j=rangeY; j<rangeY +key.length; j++){
                if(copyLock[i][j]==1 && bigLock[i][j]==1){
                    return false;
                }
                
                if(copyLock[i][j] == 1 && bigLock[i][j] == 0){
                    count ++;
                }
                
            }
        }
     
     if(count==allLock.size()){
                        return true;
                    }
    return false;
    }
    
}

1. 회전과 이동을 이용할 수 있다는 점에서 경우의 수를 어떻게 검사할지 고민끝에 주어진 범위가 크지 않아서,

lock을 품는 bigLock을 만들기로 생각했다.

2. bigLock의 가운데에 lock을 놓는다.

3. key를 bigLock의 모든부분에 대입시키면서 lock을 풀 수 있는 조건을 만족하는지 검사한다.

이를 위해, key가 위치할 수 있는 모든 가능성을  copyLock을 통해 만들고 copyLock과 bigLock을 비교하며 조건을 검사한다.

*** lock이 애초에 모두 1이면 그냥 열려있다는 의미이므로 true를 바로 반환해줘야한다. (이 부분때문에 긴 삽질을 하였다.)