..

정글 알고리즘 1강

Structure and Interpretation of Computer Programs

Structure and Interpretation of Computer Programs (컴퓨터 프로그램의 구조와 해석)
내용 중 일부

 

프로그래밍의 요소(Element of Programming)

기본 표현식 (primitivie expression) 언어가 다루는 가장 단순한 요소 (which represent the simplest entities the language is concerned with)
결합 수단 (means of combination) 단순한 요소들을 결합하여 복합적인 요소를 만드는 방법 (by which compound elements are built from simpler ones, and)
추상화 수단 (means of abstraction) 복합 요소에 이름을 붙이고, 그것을 하나의 단위로써 다룰 수 있게 해주는 방법 (by which compound elements can be named and manipulated as units)

추상화가 무엇인가 -> 복합 요소의 이름을 지정하고 단위로 조작할 수 있는 것
(means of abstraction, by which compound elements can be named and manipulated as units)

추상화를 해서 써야 한다 -> 재사용성이 좋아짐

Substitution Model (치환 모델)

 

Applicative Order Evaluation (C, C++, Java, Python 등)

인자를 먼저 계산한 뒤, 함수 본문에 치환하여 실행

    def f(a):
        return sum_of_square(a+1, a*2)
    def sum_of_squares(x,y):
        return square(x) + square(y)
    def square(x):
        return x * x

 

Normal Order Evaluation (Haskell이나 일부 LISP 시스템)

함수 본문에서 실제로 필요한 시점까지 인자 평가를 미룸

    def p():
        while true:
            pass
    def test(x, y):
        return 0 if x == 0 else y 

    test(0, p())

test(0, p())에서 무한 루프로 빠지지 않고 0을 리턴 하는 이유 -> Normal Order Evaluation

필요할때까지 매개 변수 계산을 미룸

 

재귀 (Recursion)

recursion은 사람의 생각대로 자연스럽게 쓰는 방식

 

0부터 10까지 더하는 함수를 재귀로 표현

def nsum(n):
    if n == 0:
        return 0
    return n + nsum(n-1)

print(nsum(10))

 

0부터 10까지 더하는 함수를 꼬리 재귀로 표현

def exp_iter(n, total):
    if n == 0:
        return total
    else:
        return exp_iter(n-1, total+n)
    
def sum(n):
    return exp_iter(n, 0)

 

거듭제곱의 예시

\[b^n = \begin{cases} 1 & \text{if } n = 0 \\ b \times b^{n-1} & \text{if } n > 0 \end{cases}\]
# recursion version

def expt(b, n):
    if n == 0:
        return 1
    else:
        return b * expt(b, n - 1)
# iteration version

def expt_iter(b, n):
    product = 1
    for i in range(n):
        product *= b
    
return product
# tail recursion version

 def expt_iter(b, counter, product):
    if counter == 0:
        return product
    else:
        return expt_iter(b, counter - 1, b * product)

#product = 누적값 = 1

 

  • 꼬리 재귀(Tail Recursion)은 결과값을 누적하며 계산-> 더 빠르게 값을 알 수 있다

  • 꼬리 재귀는 for문과 유사하다

  • for문, 재귀, 꼬리 재귀에서 제일 오래 걸리는 것은 일반 재귀 함수이다 (스택으로 인한 오버헤드)

 

Break the problem into smaller subproblems

재귀는 큰 문제를 작은 문제로 나누고, 그 작은 문제가 자기 자신과 구조가 동일할 때 적용할 수 있는 해결 방법

  • 문제 파악: 이 문제를 자기 자신보다 작은 하위 문제로 표현할 수 있는가?

  • 기저 조건 정의: 언제 재귀 호출을 멈출 것인가?

  • 하위 문제 호출: 더 작은 인풋에 대해 자기 자신을 호출

  • 결과 조합: 하위 문제의 결과를 조합하여 전체 문제 해결