문제
https://school.programmers.co.kr/learn/courses/30/lessons/12946
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
풀이
나의 풀이
def solution(n):
answer = []
def func(n):
# n층의 결과값 만드는 함수
# n-1층
h = len(floor[n-1])//2
# n-1층의 절반
h1 = floor[n-1][:h]
h1 = [h1[0][::-1]]+h1[1:] # 첫번째 원소 반전
# 나머지 절반
h2 = floor[n-1][h:]
h2 = [h2[0][::-1]]+h2[1:] # 첫번째 원소 반전
n1 = h1+h2
# n-2층
n2 = floor[n-2]
# n층 결과
res = n2+n1+n2
return res
floor = [[] for _ in range(16)]
if n%2==0:
floor[1] = [[1,2]]
floor[2] = [[1,3],[2,3]]
else:
floor[1] = [[1,3]]
floor[2] = [[1,2],[3,2]]
for i in range(3,n+1):
floor[i] = func(i)
for i in range(n+1):
answer+=floor[i]
return answer
팬시한 코드는 아니지만, n층의 탑이 있다고 할 때 탑의 일부분이 똑바로 세워지기 위해서 어떤 결과가 나오는지를 분석해서
위와 같은 점화식을 세울 수 있었다.
예시 : n = 3
n=3인 탑을 규칙에 맞게 세번째 봉으로 옮기기 위해서는 다음과 같은 과정을 거쳐야 한다.
- 1,2층의 블럭을 두번째 봉으로 옮긴다.
- 세번째 층을 세번째 봉으로 옮긴다.
- 두번째 봉의 2개의 층을 세번째 봉으로 옮긴다.
잘 생각해보면 n이 어떤 값이던지 위의 세가지 과정은 동일하게 이루어짐을 알 수 있다.
따라서, 위의 세 과정을 일반화 하면
- n-1층의 탑을 두번째 봉에 세운다
- n층을 세번째 봉으로 옮긴다.
- 두번째 봉의 n-1층의 탑을 세번째 봉으로 옮긴다.
나는 이 점을 참고해 n층의 탑을 옮기기 위해서는 1, 2, ..., n-1층의 부분적인 탑이 그 과정에서 세워져야 했음에 주목하였고
각 부분 탑이 세워지는데 어떤 과정이 소요되는지를 살펴보며 패턴을 파악하려고 하였다.
(n=1)
1 : [1,3]
(n=2)
1 : [1,2]
2 : [1,3],[2,3]
(n=3)
1 : [1,3]
2 : [1,2],[3,2]
3 : [1,3],[2,1],[2,3],[1,3]
(n=4)
1 : [1,2]
2 : [1,3], [2,3]
3 : [1,2], [3,1], [3,2], [1,2]
4 : [1,3], [2,3], [2,1], [3,1], [2,3], [1,2], [1,3], [2,3]
이하 생략
여기서 규칙을 몇개 정도 생각해볼 수 있는데,
- 부분탑의 층수를 하나 늘리기 위해서는 $2^{n-1}$번의 시행이 필요하다
- n층을 완성시키기 위해서는 `n-2층의 과정` + `n-1층의 변형된 과정` + `n-2층의 과정` 이 필요하다
`n-1층의 변형된 과정`이란 다음과 같다.
- n-1층의 과정을 절반으로 나눈다(half_1, half_2)
- half_1의 첫번째를 역전시킨다([1,2] -> [2,1])
- half_2의 첫번째를 역전시킨다
- half_1과 half_2를 이어붙인다
다음의 과정을 따르면, n층을 만드는데 필요한 과정이 도출되므로
n층의 탑을 전체 다 옮기는 데 필요한 과정은 각 층별 소요되는 과정을 모두 합치면 된다.
다른 풀이
위에서 언급한 일반화된 3단계의 과정을 점화식으로 만들어 조금더 Fancy한 코드를 작성할 수도 있다.
def solution(n):
answer = []
# 첫번째 봉(start)에서 두번째 봉(middle)을 사용해 세번째 봉(end)에 n층의 탑을 세우기
def hanoi(start, middle, end, n):
if n == 1:
answer.append([start, end])
else:
# 첫번째 봉(start)에서 세번째 봉을 사용해(end) 두번째 봉(middle)에 n-1층의 탑을 세우기
hanoi(start,end,middle,n-1)
# 첫번째 봉에서 세번째 봉으로 마지막 n층을 옮기기
hanoi(start,middle,end,1)
# 두번째 봉에서(middle) 첫번째 봉을 사용해(start) 세번째 봉(end)으로 n-1층의 탑을 세우기
hanoi(middle,start,end,n-1)
hanoi(1,2,3,n)
return answer
P.S : 직관적으로는 이해가 되는 코드이지만, 안의 구동원리까지 완벽히 이해가 되지는 않는다.
'알고리즘' 카테고리의 다른 글
[Python] 프로그래머스 - 줄 서는 방법 (1) | 2024.11.20 |
---|---|
[Python] 프로그래머스 - 보석 쇼핑 (2) | 2024.11.05 |
[Python] 프로그래머스 - 불량 사용자 (0) | 2024.07.29 |
[Python] 프로그래머스 - 스티커 모으기(2) (0) | 2024.07.24 |
[Python] 프로그래머스 - 연속된 부분 수열의 합 (0) | 2024.07.19 |