## 4. Python을 서브언어로 편하게 PS해보자!
PS의 주류는 C++이고, 문제의 제한 또한 보통 C++ 기준으로 만들어지기 때문에, Python 등의 C++이 아닌 기타 언어가 PS의 세계에서 주인공이 되기는 힘듭니다. 저 또한 대부분의 PS 문제를 C++로 풉니다.
하지만 Python 은 간결한 코드에서 나오는 강력한 생산성과 특정 편의 기능들을 바탕으로 PS의 특수한 상황에서는 굉장히 빠르게 코드를 짤 수 있어 쓸 만한 가치가 있기도 합니다.
이번 발표에서는 특수한 상황의 PS에서 Python을 유용하게 해 주는 다음과 같은 몇 가지 특징들을 소개하며, Python을 서브언어로 쓰기 좋은 문제들을 알아 볼 것입니다:
1. int: 내장된 integer 임의 정밀도 큰 수 연산의 편리함
2. Decimal, Fraction: floating number의 임의 정밀도를 처리하기 편한 모듈
3. itertools: C++의 next_permutation의 강화판, 다양한 순열과 조합을 구하는 함수들이 들어있는 모듈
4. 기타: operator 모듈의 itemgetter를 이용한 sort의 key 정하기, pow(n,mod-2,mod)를 통해 modular inverse 편하게 하기, list comprehension[ f(a) for a in lis ]등
### 슥삭 (BOJ ban4861)
Python과 PS를 향유하는 것을 좋아하는 PS 향유회의 코포 블루/솔브드 다이아 PS러입니다.
## 4. Python을 서브언어로 편하게 PS해보자!
PS의 주류는 C++이고, 문제의 제한 또한 보통 C++ 기준으로 만들어지기 때문에, Python 등의 C++이 아닌 기타 언어가 PS의 세계에서 주인공이 되기는 힘듭니다. 저 또한 대부분의 PS 문제를 C++로 풉니다.
하지만 Python 은 간결한 코드에서 나오는 강력한 생산성과 특정 편의 기능들을 바탕으로 PS의 특수한 상황에서는 굉장히 빠르게 코드를 짤 수 있어 쓸 만한 가치가 있기도 합니다.
이번 발표에서는 특수한 상황의 PS에서 Python을 유용하게 해 주는 다음과 같은 몇 가지 특징들을 소개하며, Python을 서브언어로 쓰기 좋은 문제들을 알아 볼 것입니다:
1. int: 내장된 integer 임의 정밀도 큰 수 연산의 편리함
2. Decimal, Fraction: floating number의 임의 정밀도를 처리하기 편한 모듈
3. itertools: C++의 next_permutation의 강화판, 다양한 순열과 조합을 구하는 함수들이 들어있는 모듈
4. 기타: operator 모듈의 itemgetter를 이용한 sort의 key 정하기, pow(n,mod-2,mod)를 통해 modular inverse 편하게 하기, list comprehension[ f(a) for a in lis ]등
### 슥삭 (BOJ ban4861)
Python과 PS를 향유하는 것을 좋아하는 PS 향유회의 코포 블루/솔브드 다이아 PS러입니다.
6. 피보나치 수열이란?
피보나치 수는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은
바로 앞 두 항의 합인 수열
예)
F(1) = 1
F(2) = 1
F(3) = F(2) + F(1) = 2
F(4) = F(3) + F(2) = 3
F(5) = F(4) + F(3) = 5
…
7. 피보나치 수열을 구현하는 5가지 방법
1) 일반 함수 방식(Function)
2) 재귀함수 방식(Recursive Function)
3) 메모이제이션 구현 방식(Memoization)
4) 파이썬 람다 함수 이용
5) 행렬 연산(Matrix Operational)
8. 재귀함수 VS 동적계획법(메모이제이션)
재귀함수 방식 메모이제이션(동적계획법)
동일한 계산을 반복할 때,
이전 계산 값을 메모리에 저장해서
동일 반복 수행 제거
프로그램 실행 속도 up
9. 피보나치 수열에 적용한
재귀함수 VS 동적계획법(메모이제이션)
재귀함수 메모이제이션
F(1) = F(2) = 1 가정한 뒤,
F(3) 계산 & 저장
F(4) 구하기 위해 F(3)을 재계산 X
이미 저장된 F(3) 이용해 F(4)계산
F(10) 구하기 위해 f(8) 다시 계산
F(8) 구하기 위해 f(6) 다시 계산
F(6) 구하기 위해 f(4) 다시 계산
…(반복)… 매우 비효율적
엄청 효율적임
11. 재귀함수 원리 설명
F(2) F(2)
F(3) F(1)
F(4) F(3)
F(2) F(1)
F(5)
t번째 값 F(t) = F(t - 1) + F(t - 2)
F(1) = 1
F(2) = 1 을 가정할 때,
**F(5)를 구하기 위해서는
4번의 계산과정이 필요함
F(5)를 얻기위해서는
재귀함수: 4번 연산
메모이제이션: 3번 연산
12. 재귀함수방식
#코드 시작----------------------------------
def fibo(n):
if n == 1 or n == 2:
return 1
else:
return fibo(n - 1) + fibo(n - 2)
for n in range(1, 21):
print(n, fibo(n))
#코드 끝------------------------------------
피보나치 함수
정의
n = 1 또는 2 일때,
1 반환 F(1) = F(2) = 1
그렇지 않다면,
n번째 항에 n-1 번째항 + n-2 번째항 삽입
피보나치 수열 출력
만약,
13. 메모이제이션 구현 방식(동적 계획법)
#코드 시작---------------------------------------
암기노트 = {1: 1, 2: 1}
def fibo(n):
if n in 암기노트:
return 암기노트[n]
else:
output = fibo(n - 1) + fibo(n - 2)
암기노트[n] = output
return output
for n in range(1, 21):
print(n, fibo(n))
#코드 끝----------------------------------------
피보나치 함수
정의
암기노트 정의
F(1) = F(2) = 1
피보나치 수열 출력
암기노트n번째에 n-1 번째항 + n-2 번째항
계산 & 저장
그렇지 않다면,
n값이 암기노트에 존재한다면
n번째 항 출력 F(1) = F(2) =1
만약,
14. 재귀함수가 비효율적인 이유?
#코드 시작----------------------------------
counter = 0
def fibo(n):
global counter
counter += 1
if n == 1 or n == 2:
return 1
else:
return fibo(n - 1) + fibo(n - 2)
for n in range(1, 33):
print(n, '번째 항: ', fibo(n))
print('연산 횟수: ', counter, '번')
print(‘’)
#코드 끝----------------------------------------
연산 횟수만큼 숫자를
증가시키는 변수 생성
연산 횟수 출력
18. 1번 문제
- 다음 중 동일 계산 반복에 효율적인 방식을 고르시오
1) 재귀함수 방식(Recursive Function)
2) 메모이제이션 구현 방식(Memoization)
정답: 2번
19. 2번 문제
- 다음 중에서 가장 이질적인 한 가지를 고르시오
Dynamic
Programming 동적계획법
메모이제이션
動的計劃法
재귀함수
20. 3번 문제
- 동적계획법이 아닌 일반 재귀함수 방식으로 피보나치 수열을 구할 때, F(6)을
구하기 위한 계산 횟수를 구하시오
t번째 값 F(t) = F(t - 1) + F(t - 2)
F(1) = 1
F(2) = 1 을 가정할 때,
**F(5)를 구하기 위해서는 4번의 계산과정이 필요함
F(2) F(2)
F(3) F(1)
F(4) F(3)
F(2) F(1)
F(5)