쵼쥬
쵼쥬의 개발공부 TIL
쵼쥬
전체 방문자
오늘
어제
  • 분류 전체보기 (276)
    • 코딩테스트 (192)
      • [알고리즘] 알고리즘 정리 (7)
      • [백준] 코딩테스트 연습 (126)
      • [프로그래머스] 코딩테스트 연습 (59)
    • Spring (71)
      • [인프런] 스프링 핵심 원리- 기본편 (9)
      • [인프런] 스프링 MVC 1 (6)
      • [인프런] 스프링 MVC 2 (4)
      • [인프런] 실전! 스프링 부트와 JPA 활용1 (7)
      • [인프런] 실전! 스프링 부트와 JPA 활용2 (5)
      • [인프런] 실전! 스프링 데이터 JPA (7)
      • [인프런] 실전! Querydsl (7)
      • JWT (5)
      • [인프런] Spring Cloud (17)
      • [인프런] Spring Batch (4)
    • Java (6)
      • [Java8] 모던인자바액션 (4)
      • [부스트코스] 웹 백엔드 (2)
      • [패스트캠퍼스] JAVA STREAM (0)
    • CS (6)
      • 디자인 패턴과 프로그래밍 패터다임 (2)
      • 네트워크 (4)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • 알고리즘
  • 누적합
  • 백준
  • 백분
  • BFS
  • 코딩테스트
  • 구현
  • 프로그래머스
  • 부스트코스
  • 타임리프
  • jpa
  • 인프런
  • Spring Data JPA
  • 자바
  • querydsl
  • MVC
  • 비트마스킹
  • spring
  • 스프링
  • 위클리 챌린지

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
쵼쥬

쵼쥬의 개발공부 TIL

자물쇠와 열쇠
코딩테스트/[프로그래머스] 코딩테스트 연습

자물쇠와 열쇠

2021. 9. 8. 23:08

문제 설명

고고학자인  "튜브"는 고대 유적지에서 보물과 유적이 가득할 것으로 추정되는 비밀의 문을 발견하였습니다. 그런데 문을 열려고 살펴보니 특이한 형태의 자물쇠로 잠겨 있었고 문 앞에는 특이한 형태의 열쇠와 함께 자물쇠를 푸는 방법에 대해 다음과 같이 설명해 주는 종이가 발견되었습니다.

잠겨있는 자물쇠는 격자 한 칸의 크기가  1 x 1인  N x N 크기의 정사각 격자 형태이고 특이한 모양의 열쇠는 M x M 크기인 정사각 격자 형태로 되어 있습니다.

자물쇠에는 홈이 파여 있고 열쇠 또한 홈과 돌기 부분이 있습니다. 열쇠는 회전과 이동이 가능하며 열쇠의 돌기 부분을 자물쇠의 홈 부분에 딱 맞게 채우면 자물쇠가 열리게 되는 구조입니다. 자물쇠 영역을 벗어난 부분에 있는 열쇠의 홈과 돌기는 자물쇠를 여는 데 영향을 주지 않지만, 자물쇠 영역 내에서는 열쇠의 돌기 부분과 자물쇠의 홈 부분이 정확히 일치해야 하며 열쇠의 돌기와 자물쇠의 돌기가 만나서는 안됩니다. 또한 자물쇠의 모든 홈을 채워 비어있는 곳이 없어야 자물쇠를 열 수 있습니다.

열쇠를 나타내는 2차원 배열 key와 자물쇠를 나타내는 2차원 배열 lock이 매개변수로 주어질 때, 열쇠로 자물쇠를 열수 있으면 true를, 열 수 없으면 false를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • key는 M x M(3 ≤ M ≤ 20, M은 자연수)크기 2차원 배열입니다.
  • lock은 N x N(3 ≤ N ≤ 20, N은 자연수)크기 2차원 배열입니다.
  • M은 항상 N 이하입니다.
  • key와 lock의 원소는 0 또는 1로 이루어져 있습니다.
    • 0은 홈 부분, 1은 돌기 부분을 나타냅니다.

입출력 예

key lock result
[[0, 0, 0], [1, 0, 0], [0, 1, 1]] [[1, 1, 1], [1, 1, 0], [1, 0, 1]] true

입출력 예에 대한 설명

key를 시계 방향으로 90도 회전하고, 오른쪽으로 한 칸, 아래로 한 칸 이동하면 lock의 홈 부분을 정확히 모두 채울 수 있습니다.

 


풀이 방법 생각

lock 배열을 상하좌우로 크기를 늘려서 한칸씩 움직이며 key를 넣어주었다.

key를 회전하는 rotate함수를 만들고 4번 반복해서 key를 넣었다. 

여기서 check함수는 key를 lock에 넣어주는 함수이고 checkLock은 lock에 key를 넣어서 열렸는지 혹인하는 함수이다.

 

 

내 코드

class Solution {
    public boolean solution(int[][] key, int[][] lock) {
        boolean answer = true;

        int[][] expandLock = new int[lock.length + 2 * (key.length - 1)][lock.length + 2 * (key.length - 1)];

        for (int i = key.length - 1; i < lock.length + key.length - 1; i++) {
            for (int j = key.length - 1; j < lock.length + key.length - 1; j++) {
                expandLock[i][j] = lock[i - (key.length - 1)][j - (key.length - 1)];
            }
        }


        for (int i = 0; i < 4; i++) {
            key = rotate(key);

            if (check(key, expandLock)) {
                return answer;
            }
        }

        return false;
    }

    int[][] rotate(int[][] key) {
        int[][] rotatedKey = new int[key.length][key.length];

        for (int i = 0; i < key.length; i++) {
            for (int j = 0; j < key.length; j++) {
                rotatedKey[i][j] = key[key.length - (j + 1)][i];
            }
        }
        return rotatedKey;
    }

    boolean check(int[][] key, int[][] expandLock) {
        int[][] copyLock = new int[expandLock.length][expandLock.length];


        for (int i = 0; i < expandLock.length - key.length + 1; i++) {
            for (int j = 0; j < expandLock.length - key.length + 1; j++) {

                for (int k = 0; k < expandLock.length; k++) {
                    for (int v = 0; v < expandLock.length; v++) {
                        copyLock[k][v] = expandLock[k][v];
                    }
                }

                for (int k = 0; k < key.length; k++) {
                    for (int u = 0; u < key.length; u++) {
                        if (copyLock[i + k][j + u] == 0)
                            copyLock[i + k][j + u] = key[k][u];
                        else if(copyLock[i+k][j+u] == 1 && key[k][u] ==1)
                            copyLock[i + k][j + u] = 0;
                    }
                }

                if (checkLock(copyLock, key.length))
                    return true;
            }
        }

        return false;
    }

    boolean checkLock(int[][] expandLock, int keySize) {
        for (int i = keySize - 1; i < expandLock.length - keySize + 1; i++) {
            for (int j = keySize - 1; j < expandLock.length - keySize + 1; j++) {
                if (expandLock[i][j] == 0)
                    return false;
            }
        }
        return true;
    }
}

 

다른 사람 풀이

class Solution {

    public int[][] roll(int[][] mat)
    {
        int[][] temp = new int[mat.length][mat.length];

        for (int i = 0; i < mat.length; i++)
        {
            for (int j = 0; j < mat.length; j++)
            {
                temp[i][j] = mat[mat.length - j - 1][i];
            }
        }

        return temp;
    }

    public int[][] move(int[][] key, int length, int row, int col)
    {
        int[][] temp = new int[length][length];

        for (int i = 0; i < key.length; i++)
        {
            for (int j = 0; j < key.length; j++)
            {
                if (i + row >= 0 && i + row < length && j + col >= 0 && j + col < length)
                {
                    temp[i + row][j + col] = key[i][j];
                }
            }
        }

        return temp;
    }

    public boolean same(int[][] key, int[][] lock)
    {
         for (int n = 0; n < lock.length; n++)
        {
            for (int m = 0; m < lock.length; m++)
            {
                if ((key[n][m] ^ lock[n][m]) == 0)
                {
                    return false;
                }
            }
        }
        return true;
    }

    public boolean check(int[][] key, int[][] lock)
    {
        int[][] mat = new int[lock.length * 2 - 1][lock.length * 2 - 1];

        for (int i = (1 - key.length); i < lock.length; i++)
        {
            for (int j = (1 - key.length); j < lock.length; j++)
            {
                int[][] temp = move(key, lock.length, i, j);
                if (same(temp, lock))
                {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean solution(int[][] key, int[][] lock) {
        boolean answer = false;

        for (int i = 0; i < key.length; i++)
        {
            if (check(key, lock))
            {
                return true;
            }

            key = roll(key);
        }



        return answer;
    }
}

돌기가 만나서는 안된다는 조건을 빼먹고 작성해서 애를 먹었다.... 

 

'코딩테스트 > [프로그래머스] 코딩테스트 연습' 카테고리의 다른 글

신규 아이디 추천  (0) 2021.09.09
순위 검색  (0) 2021.09.08
문자열 압축  (0) 2021.09.07
괄호 변환  (0) 2021.09.07
복서 정렬하기  (0) 2021.09.06
    '코딩테스트/[프로그래머스] 코딩테스트 연습' 카테고리의 다른 글
    • 신규 아이디 추천
    • 순위 검색
    • 문자열 압축
    • 괄호 변환
    쵼쥬
    쵼쥬

    티스토리툴바