삽질의 현장/- ETC

프로그램을 작성하는 33가지 방법 - Chaptor 02 정리

shovelman 2019. 3. 23. 19:29

최근 '프로그래밍 패턴 (프로그램을 작성하는 33가지 방법)' 을 읽기 시작했다.

한 가지의 기능을 Chaptor 마다 각각 다른 패턴으로 구현하여 설명한 책이다.

모두 비슷하게 동작하지만 환경과 상황이라는 제약 조건 안에서 탄생된 패턴을 직접 코드로 보여주고 있어직접 코딩을 하며 이해하고 있는 중이다.


책에서 소개하는 한 가지 기능은 '텍스트 파일을 읽어 단어 빈도 출력' 하는 프로그램이다.

가장 빈도가 높은 단어 순으로 그에 해당하는 빈도를 내림차순으로 출력하는 기능을 구현하고 있다.

이전 Chaptor 보기 : 프로그램을 작성하는 33가지 방법 - Chaptor 01 정리


Chaptor 02. 포스로

포스는 스택 개념을 핵심으로 한다. 데이터가 즉시 필요하지 않으면 힙이라고 하는 메모리에 둘 수 있다.

  • 데이터 스택이 존재한다. 조건, 산술 등의 모든 연산은 스택에 있는 데이터를 대상으로 이뤄진다.
  • 나중에 연산해야 하는 데이터를 저장할 힙(heap)이 존재한다. 힙 데이터는 이름(즉 변수)과 연관될 수 있다. 모든 연산은 스택에 있는 데이터에 대해 이뤄지므로 연산해야 하는 모든 힙 데이터는 먼저 스택으로 옮겨야 하고 최종적으로는 다시 힙으로 옮긴다.
  • 사용자 정의 '프로시저'(즉, 명령 집합을 가리키는 이름이며, 전혀 다른 명칭으로 부를 수도 있다) 형태의 추상화가 존재한다.


스택과 힙을 정의한다

stack = []
heap = {}


프로시저 집합을 정의한다

def read_file():
def filter_char():
def scan():
def remove_stop_word():
def frequencies():
def sort():


모든 프로시저는 스택에서 데이터를 꺼내 사용하고, 스택에 데이터를 넣는다

def read_file():
    f = open(stack.pop())
    # 스택에 그 결과를 넣는다
    stack.append([f.read()])
    f.close()

def filter_char():
    stack.append(re.compile('[\\W_]+'))
    # 그 결과를 스택에 넣는다
    stack.append([stack.pop().sub(' ', stack.pop()[0]).lower()])

def scan():
    stack.extend(stack.pop()[0].split())


나중에 연산해야 하는 데이터를 힙(heap) 상의 변수에 넣는다

	heap['stop_words'] = stack.pop()


단순하게 처리하기 위해 별도 스택에 데이터를 넣는다.

	heap['words'] = []
	while len(stack) > 0:
      if stack[-1] in heap['stop_words']:
          stack.pop() # 꺼낸 후 버린다
      else:
          heap['words'].append(stack.pop()) # 꺼낸 후 저장한다
  stack.extend(heap['words']) # 단어를 스택에 적재한다
  del heap['stop_words']; del heap['words'] #불필요하다


힙에 저장할 데이터의 변수를 할당하여, 순회하며 데이터를 적재한다.

def frequencies():
    heap['word_freqs'] = {}
    # 실제 '포스(Forth)' 형식의 특색이 약간 나타나는 부분은 여기서부터...
    while len(stack) > 0:
        if stack[-1] in heap['word_freqs']:
            # 빈도를 증가시키며, 다음과 같은 후위 형식이다: f 1 +
            stack.append(heap['word_freqs'][stack[-1]]) # f를 넣는다.
            stack.append(1) # 1 을 넣는다
            stack.append(stack.pop() + stack.pop()) # 더한다
        else:
            stack.append(1) # stack[2]에 1을 넣는다
        # 갱신한 빈도를 힙에 다시 적재한다
        heap['word_freqs'][stack.pop()] = stack.pop()

    # 그 결과를 스택에 넣는다.
    stack.append(heap['word_freqs'])
    del heap['word_freqs'] # 이 변수는 더 이상 필요치 않다