일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 객체지향설계
- STL
- 멀티모듈
- DFS
- 비즈니스요구사항
- multi module
- ZonedDateTime
- 완전탐색
- 서버
- OCP
- 탄력적 ip
- C++
- 서버타임존설정
- EC2
- DP
- SW마에스트로
- google calendar api
- 에러로깅
- DIP
- localdatetime
- 해시충돌
- BFS
- 그리디
- web
- 정렬
- aws
- 자료구조
- 개방주소법
- 구현
- hashcollision
- Today
- Total
레츠고✨
[프로그래머스] 자물쇠와 열쇠 (python) 본문
https://school.programmers.co.kr/learn/courses/30/lessons/60059#
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
def solution(key, lock):
answer = False
n = len(lock)
new_lock = [[0] * 3 * n for _ in range(3 * n)]
for i in range(n):
new_lock[i + n] = [0] * n + lock[i] + [0] * n
match = 0
for _ in range(4):
# key + new_lock
result = [item[:] for item in new_lock]
for dx in range(1, 2 * n): # 0~2n
for dy in range(1, 2 * n): # 0~2n
for i in range(len(key)):
for j in range(len(key)):
result[i + dx][j + dy] += key[i][j]
# 확인
if check_key_and_lock(result, n):
return True
result = [item[:] for item in new_lock]
key = rotate_a_matrix_by_90_degree(key)
return answer
def check_key_and_lock(result, n):
for i in range(n, 2 * n):
for j in range(n, 2 * n):
if result[i][j] != 1:
return False
return True
# 2차원 리스트를 시계빙향(오른쪽) 90도 회전한 결과를 반환하는 함수
def rotate_a_matrix_by_90_degree(a):
n = len(a) # 행 길이 계산
m = len(a[0]) # 열 길이 계산
result = [[0] * n for _ in range(m)]
for i in range(n):
for j in range(m):
result[j][n - i - 1] = a[i][j]
return result
1. lock 배열을 3배 확장한 new_lock 배열을 만든다.
2. key를 회전시키면서
3. key와 new_lock을 합친다. 합치는 지점은 (1,1) 부터 (2n-1, 2n-1)까지
4. 합쳐서 만든 result 배열을 check_key_and_lock함수를 이용해 기존 lock배열 부분이 모두 1인지 확인한다.
5. 만약 모두 1인 지점이 나온다면 true를 반환하고
6. 아니라면 그 다음 계산을 계속해서 끝까지 true가 없으면 false를 반환한다.
복잡하다 복잡해 ...
일단 2차원 리스트를 90도 회전하는 함수는 외워둬야 할 것 같다.
그리고 key랑 new_lock배열을 합치는 부분은 4중반복문이라 효율성이 좋은 코드같지는 않다.
그래서 처음에는 (0,0)~ 부터 시작하는 걸로 제출했을 때에는 딱 1개의 테스트가 시간초과로 실패했는데,
(1,1)~로 바꾸고 혹시나 싶어 다시 제출했을 때 모두 성공했다. 그래도 오래 걸리는 코드인듯
리스트를 복사해오는 방식은 deepcopy와 slicing 방법이 있다고 하는데,
deepcopy가 더 느리다고 한다. 처음에는 result 에 new_lock을 복사할 때 deepcopy를 썼는데 slicing 방식으로 바꿔서 제출하니 속도가 훨씬 빨라졌다.
[파이썬] 리스트의 깊은복사는 deepcopy가 빠를까? slicing이 빠를까?
리스트의 깊은복사는 어떤게 더 빠를까?
velog.io
그리고 lock배열을 3배 확장시키는 아이디어는 [이취코]책에서 참고했다.
아직 구현 문제는 문제이해-아이디어-구현 까지 혼자 힘으로 하기 어려운 것 같다..ㅠ
나는 새로운 배열 리스트에 기존 배열을 복사한 뒤에 키값을 더하고, 다시 배열을 초기화하는 방식을 사용했는데
책에서는 키를 자물쇠에 꽂은 뒤에 다시 빼줌으로써 리스트 복사를 할 필요가 없는 방식을 사용했다.
이 방법도 괜찮은 것 같아서 책에서 나온 코드를 참고해서 수정해보았다.
def solution(key, lock):
n = len(lock)
new_lock = [[0] * 3 * n for _ in range(3 * n)]
for i in range(n):
new_lock[i + n] = [0] * n + lock[i] + [0] * n
match = 0
for _ in range(4):
key = rotate_a_matrix_by_90_degree(key)
# key + new_lock
for dx in range(1, 2 * n): # 0~2n
for dy in range(1, 2 * n): # 0~2n
for i in range(len(key)):
for j in range(len(key)):
new_lock[i + dx][j + dy] += key[i][j]
# 확인
if check_key_and_lock(new_lock, n):
return True
# 자물쇠에서 열쇠를 다시 빼기
for i in range(len(key)):
for j in range(len(key)):
new_lock[i + dx][j+ dy] -= key[i][j]
return False
def check_key_and_lock(result, n):
for i in range(n, 2 * n):
for j in range(n, 2 * n):
if result[i][j] != 1:
return False
return True
# 2차원 리스트를 시계빙향(오른쪽) 90도 회전한 결과를 반환하는 함수
def rotate_a_matrix_by_90_degree(a):
n = len(a) # 행 길이 계산
m = len(a[0]) # 열 길이 계산
result = [[0] * n for _ in range(m)]
for i in range(n):
for j in range(m):
result[j][n - i - 1] = a[i][j]
return result
'Problem Solving > Solution' 카테고리의 다른 글
[프로그래머스] 외벽점검 (python) (1) | 2024.01.27 |
---|---|
[백준] 15686. 치킨 배달 (python) (1) | 2024.01.27 |
[프로그래머스] 기둥과 보 설치 (python) (0) | 2024.01.26 |
[프로그래머스] 문자열 압축 - (python) (0) | 2024.01.25 |
[백준] 3190. 뱀 (python) (2) | 2024.01.25 |