해설을 생각하기가 내게는 정말 어려운..문제였다. 카카오 2020년도 문제들 자체가 전반적으로..좀 어려운 것 같다. 결국다른 사람 논리를 보고 풀었는데 이번엔 또 중첩함수를 해결하는 부분에서 막혀서, 이 기회에 중첩함수에서 그동안 내가 막혔던 부분을 정리해보려고한다.
문제 코드만 볼 분은 깃허브 링크 눌러주세요. +중첩함수 부분 에러만 볼 분은 맨아래로..
GitHub - Rhyankwon/algorithms
Contribute to Rhyankwon/algorithms development by creating an account on GitHub.
github.com
문제 설명 ㄱㄱ
코딩테스트 연습 - 자물쇠와 열쇠
[[0, 0, 0], [1, 0, 0], [0, 1, 1]] [[1, 1, 1], [1, 1, 0], [1, 0, 1]] true
programmers.co.kr


문제 해결 논리
1. Lock 배열의 테두리부분에 key길이만큼씩 1로 이루어진 배열을 추가한다.
2. new Lock 배열의 맨 왼쪽 윗부분부터 Key배열을 넣어보면서 지금 Lock 부분의 값이 모두 1인지 확인한다.
3. Lock을 만족하지 않는 경우 Key를 오른쪽으로 90도 회전해서 다시 2번을 반복한다.
4. Lock 부분이 모두 1이면 True, 프로그램이 끝날때까지 True가 안 나오면 False 리턴.
간단히 얘기하면 Lock의 상하좌우를 key가 쉽게 훑을 수 있도록 Lock배열을 재구성한뒤 해당 배열의 각 부분마다 key를 더해보고 매번 Lock부분이 모두 채워지는지 확인하는 것이다. 처음에 봤을때 어떻게 풀지? 했는데 다른사람 풀이를 보니까 너무.. 쉽게 풀어서 깜짝 놀랐다. 내가 참고한 풀이는 여기.
자물쇠와 열쇠 - 2020 카카오 공채 (python)
2차원 배열을 다루는게 익숙해야 풀만할 것 같은 문제. 효율성이 없기 때문에 완전탐색으로 풀면 된다.
velog.io
아무튼 나는 위 풀이의 논리만 확인하고 내 방식대로 풀려고 시도를 했다. 근데 나는 원래 중첩함수를 사용하는걸 좋아해서 ..ㅋㅋㅋㅋㅋ 중첩함수를 써서 풀려고 햇는데 ㅠ자꾸 에러가 났다. 난 항상 이런 식이였달까?
중첩함수 시도 -> 에러 -> 앗 시발 그냥 외부함수로 만들어서 풀어야지 -> 품
아무튼, 나는 외부함수를 쓰면 변수들을 전부 보내야하고 또 리턴받고 하는게 좀 번거로워서 중첩함수를 좋아한다.
이번에 에러가 났던 부분은, 2차원 배열의 중첩함수에서 변수를 변경하는 부분이다.
def solution(key): # key = [[1, 1], [0, 0]]
def rotate():
key = list(zip(*key[::-1]))
rotate()
위와 같은 함수가 있다고 치면 여기에서는 local variable 변수 referenced before assignment 라고 에러가 뜨게 된다.
하지만 rotate내에서 solution함수의 변수 key를 인지하지 못하는 것은 아니다. 다만 중첩함수 내부에서 key = 이런식으로 코딩을 하면 이 중첩함수는 시작하는 시간부터 외부 변수 key와는 이미 완전히 다른 변수가 되는 것이다.
이럴 때에는
def solution(key): # key = [[1, 1], [0, 0]]
def rotate():
r_key = list(zip(*key[::-1]))
return r_key
key = rotate()
이런식으로 변수명을 바꿔주면 쉽게 해결된다. (외부 변수 key를 사용해 r_key를 받은후 이를 리턴해 다시 key에 할당)
하지만 여기에서 약간 헷갈릴 수 있는 부분이, 그렇다고 해서 외부변수 key를 중첩함수 내에서 바꿀 수 없는 것도 아니다. 가령,
def solution(key): # key = [[1, 1], [0, 0]]
def rotate():
key[0] = key[1]
rotate()
print(key) #key = [[0, 0], [0, 0]]
solution([[1, 1], [0, 0]])
이런 식으로 key,를 그대로 활용해서 key값에 넣는게 아니라 일부값을 가져와서 일부를 변경하면 그대로 외부 key에도 바뀐 key가 적용된다. 하지만
def solution(key): # key = [[1, 1], [0, 0]]
def rotate():
key = [[2, 2], [0, 0]]
rotate()
print(key) #key = [[1, 1], [0, 0]], 변경안됨
solution([[1, 1], [0, 0]])
이런식으로 외부변수와 똑같은 이름의 변수를 중첩함수 내부에서 만드는 경우 이제 외부변수와 내부변수는 이름만 같을 뿐 서로 다른 변수가 된다.
다시 말하면, 중첩함수 내부에서는 외부변수에 자유롭게 접근하고 출력할 수 있다. 그리고 배열의 경우 그 내부값을 변경하는 경우 외부함수에서도 그 변경된 값이 적용된다. 하지만 중첩함수 내부에서 외부변수와 똑같은 이름의 변수를 설정하는 경우 외부함수의 변수와 이름만 같을 뿐 완전히 다른 변수가 되고 그렇게 변수를 정의하고 나서부터는 외부함수의 동일명 변수에 접근할 수 없다. 그리고 그에 따라 중첩함수 내부에서 외부변수와 같은 이름의 변수를 정의하려는 경우 그 시도를 할 때부터 이미 외부변수에의 접근이 금지되므로 key = 어쩌고..key 이런식으로 외부변수를 그대로 가져와서 새로운 내부변수를 만들 순 없다.
여기까지 읽은 사람이 있다면, 들만한 의문이 있을 것이다. 내부함수에 rotate(key) 이런식으로 변수를 직접 전해주는 경우는 어떻게 될까?
def solution(key): # key = [[1, 1], [0, 0]]
def rotate(key):
key = list(zip(*key[::-1]))
rotate(key)
print(key) #key = [[1, 1], [0, 0]], 변경안됨
solution([[1, 1], [0, 0]])
중첩함수에 key변수를 입력받을 때부터 저 변수는 이미 외부함수의 변수와 이름만 같을 뿐 완전히 다른 변수이다. 따라서 이런 경우에는 이미 key가 지역변수로 assigned되어있다고 볼 수 있고 직접 key에 key를 할당하여 값을 변경할 수 있다. 물론 외부에는 아무런 영향이 없다.
간단히 얘기하면, 중첩함수 내부에서 외부함수의 변수와 똑같은 이름의 변수를 선언하려고 한다면 해당 선언문이 중첩함수 내부의 위에 있든 아래에 있든 이미 중첩함수를 시작할 때부터 해당 변수명은 더이상 외부변수를 의미하지 않는다. 하지만 그렇게하지 않는다면 그 내부의 값은 얼마든지 바꿀 수 있고 그 변경된 내용은 외부함수에서도 동일하게 적용된다. 지금 내가 말하는건 다 '배열'이라는걸 잊지 말자. 배열도 그 자체를 중첩함수 내부에서 바꿀 순 없듯이, 그 어떤 변수도 변수명 = 무엇 이런 식으로 중첩함수 내부에서 외부 변수를 변경할 순 없다. 배열은 배열의 주소값 따로, 배열 내부값들의 주소값 따로 이런식으로 파이썬에서 작동하기 때문에 예외로 내부값을 변경하는게 가능할 뿐이다.
만약 중첩함수 내부에서 외부값을 직접 변경하고 싶으면 다른 함수들과 마찬가지로 외부함수에서 global 변수를 선언하고 중첩함수 내부에서 다시 global 변수명 을 써서 전역변수로 변경 후 풀어야 한다.
다시 얘기하면, 간단히 얘기하면 어쩌고를 두번이나 해버렸는데 그만큼 나한텐 많이 헷갈렸던 부분이고 사람들도 많이 헷갈려했을 내용인 것 같다. 도움이 됐길.
+ 최근에 자꾸 혼자 풀 수 있는 문제가 없었어서 조금 우울했는데, 다시 생각해보면 내가 못 푸는 문제가 있다면 그걸 남의걸 보고 해결하는 과정이 정말로 공부하는 거..다. 우울하지 않아! 난 공부중이거든 ㅎ
'코딩테스트 > 카카오 기출' 카테고리의 다른 글
| 2021 카카오 신규 아이디 추천 파이썬 풀이, 코드 / 쉬운 구현문제 (0) | 2022.01.30 |
|---|---|
| 카카오 2020 코딩테스트 괄호 변환 해설/코드 (파이썬), 간단한 재귀 구현 문제 (0) | 2022.01.15 |
| 카카오 2020기출, 블록 이동하기 파이썬 코드/해설, 까다로운 구현 문제 LV3, 리스트 집합 속도 차이 (0) | 2022.01.14 |
| 카카오 2020기출 문자열 압축 코드, 해설 (파이썬) LV2 구현문제 (0) | 2022.01.12 |
| 카카오 2019 블라인드 채용 코딩테스트 1번 오픈채팅방, 2번 실패율, 5번 길 찾기 게임 파이썬 해설 (0) | 2021.08.27 |