누군가 x의 y승은 얼마인가? 라고 물었다. 그에 대한 대답은?

그냥 x ** y를 리턴하면 되긴 하지만(Python 기준), 그거 말고.

 

일반적으로는 다음과 같이 구할 수 있다.

def pow(x, y):
    answer = 1
    for i in range(y):       
    	answer *= x
    return answer

이 방법의 시간복잡도는 O(y)이다.

 

근데 더 빠르게 구할 순 없을까?


첨에는 단순하게, 저 방법은 루프를 y번 돌면서 하는거니까 루프횟수를 줄이면 된다고 생각했다.

만약 x의 y승을 구할 때 y가 짝수라면

x의 y승 = (x의 y/2승) * (x의 y/2승)

이고, y가 홀수라면

x의 y승 = (x의 y/2승) * (x의 y/2승) * (x)

이므로, 루프를 y번까지 돌 필요없이 y의 반 정도까지만 돌면 된다!고 생각해서 다음과 같이 코드를 짰었다.

def pow(x, y):
    answer = 1
    for i in range(y//2):
        answer *= i
    if y%2 == 0:                     # y가 짝수
        return answer * answer
    else:                            # y가 홀수
    	return answer * answer * 1

그러나 이것의 시간복잡도도 O(y)이다. y가 커질수록 y의 반까지만 루프를 돈다는 건 의미가 없어지기 때문..

 

그러나 이것의 시간복잡도를 O(lg y)로 줄일 수 있는 방법이 있다.


우선 거듭제곱을 구할 때 루프가 아니라 재귀로도 구할 수 있다는 점에 힌트가 있다.

다음과 같이 코드를 짜면 재귀의 방법으로 거듭제곱을 구할 수 있다.

def pow(x, y):
    if y == 0:
        return 1
    return x * pow(x, y - 1)

물론 저것의 시간복잡도 역시 아직은 O(y)임.

 

그러나 예를 들어서, 2의 8승은 다음과 같은 과정으로 구할 수 있다는 점에 주목하자.

 

2의 8승 = (2의 4승) * (2의 4승)

2의 8승 = ((2의 2승) * (2의 2승)) * ((2의 2승) * (2의 2승))

.....

 

즉 다음과 같이 가능하다는 말.

def pow(x, y):       
    if y == 1:
        return 1
    return pow(x, y//2) * pow(x, y//2)    # 물론 y가 짝수일 때만 가능

근데 같은 내용에 대해 재귀를 두 번 호출할 필요는 없으니, 다음과 같이 하는게 더 빠르다.

def pow(x, y):       
    if y == 1:
        return 1
    sub_answer = pow(x, y//2)
    return sub_answer * sub_answer    # 물론 y가 짝수일 때만 가능

아까 x의 y승을 구할 때 y가 홀수라면 x의 y승 = x의 y/2승 * x의 y/2승 * x라고 했었으니, y가 홀수일 때도 포함해 다음과 같이 완성 가능하다.

def pow(x, y):       
    if y == 1:
        return 1
    sub_answer = pow(x, y//2)
    
    if y%2 == 0:
    	return sub_answer * sub_answer    
    else:
        return sub_answer * sub_answer * x

이렇게 하면 O(lg y)의 시간복잡도로 거듭제곱을 더 빠르게 계산할 수 있다.


내가 한 거랑 뭐가 달랐던 걸까?

우선 기본적인 접근법은 같았던 것 같다. y가 짝수인지 아닌지에 따라, 2/y까지만 곱한 걸 다루는 면에서.

그러나 y가 만약 16으로 주어졌을 때, x의 16승은 x의 8승 * x의 8승이 맞긴 하지만 x의 8승을 구하는 것도 다시 반으로 쪼개서 할 수 있다는 점을 간과했다.

 

동아리에서 해커톤을 할 때 Heroku를 통해서 배포했는데, 까먹지 않기 위해 글을 남긴다.


https://www.heroku.com/

 

Cloud Application Platform | Heroku

Heroku is a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.

www.heroku.com

우선 여기 들어가서 회원가입을 해준다. 이후,

https://devcenter.heroku.com/articles/heroku-cli

 

The Heroku CLI | Heroku Dev Center

Last updated April 27, 2021 The Heroku Command Line Interface (CLI) makes it easy to create and manage your Heroku apps directly from the terminal. It’s an essential part of using Heroku. Download and install The Heroku CLI requires Git, the popular vers

devcenter.heroku.com

여기서 헤로쿠 CLI을 설치한다. 첫 설치라면 재부팅해야 작동한다.

 

이후 가상환경을 활성화하고, python -m pip install --upgrade pip를 해줘서 pip도 최신버전으로 업그레이드.

다 됐다면 settings.py를 열어 다음 부분들을 아래처럼 수정해준다.

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY','원래 시크릿 키')
DEBUG = bool(os.environ.get('DJANGO_DEBUG', True))
ALLOWED_HOSTS = ['*']

MIDDLEWARE = [
    .....
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

settings.py의 

그리고 manage.py가 있는 디렉토리에 .gitinore파일을 만들어줘야 한다!

gitignore파일 안의 내용은 밑의 링크에서 django를 검색해 나온 내용을 붙여넣기해주자.

 

https://www.toptal.com/developers/gitignore

 

gitignore.io

Create useful .gitignore files for your project

www.toptal.com

 

다 됐다면, manage.py가 있는 파일에 Profile이란 파일을 새로 만들어주고, 다음 내용을 적어준다.

web: gunicorn <프로젝트이름>.wsgi

앱이름이 아니라 프로젝트이름을 적어준다는 것에 유의할 것. wsgi뒤에 --log-file-도 원래 적어줘야 하는디, 정확한 이유는 모르겠으나 그렇게 하면 오류가 생겨서 wsgi까지만 적어줬더니 에러가 생기지 않았다. 왜일까..흐음

 

그리고 터미널에 pip install gunicorn whitenoise django-Heroku psycopg2-binary를 입력! 여러 모듈들을 하나의 명령어로 설치하는 것이다.

 

이후. settings.py를 열어서 맨 밑에 다음 코드들을 추가.

import dj_database_url 
db_from_env = dj_database_url.config(conn_max_age=500) 
DATABASES['default'].update(db_from_env)

 

다 됐으면, pip freeze > requirements.txt를 하여 라이브러리 리스트를 만들어주고 이를 manage.py와 동일한 위치에 둔다! 그후 manage.py가 있는 곳에 runtime.txt를 만들고, 그 안에 python-x.x.x를 작성한다. 파이썬 버전을 적는 것인데, 이는 터미널에 python -version을 입력하는 것으로 확인가능하다.

 

이제 모든 준비가 끝났는데, 내 경우에는 가상환경과 관련된 폴더가 프로젝트 디렉토리와 같은 곳에 있었는데, 이 때 프로젝트 디렉토리 안으로 가상환경 폴더를 이동시켜야만 에러가 발생하지 않았다. 내 가상환경 이름이 venv고 프로젝트 디렉토리가 project1이었다면, project1디렉토리 안에 venv가 위치해야만 했다. 즉 manage.py와 venv가 같은 곳에 있어야 했음!

 

여까지 다 됐다면, 이제 깃허브에 새 레포지토리를 만들고, manage.py가 있는 위치에서 다음 작업들을 해준다.

  1. git init
  2. git add .
  3. git commit -m "커밋메시지"
  4. git remote add origin <레포지토리 url>
  5. git push origin master

그리고 터미널에서 heroku login을 입력하면 헤로쿠 사이트가 뜨는데 로그인해준다. 그 후 터미널에 heroku create <서버이름>을 입력해서 배포서버를 만들어준다. 서버이름은 내 맘대로 정하는 것임. 이미 만든 서버가 존재한다면, heroku git:remote -a <서버이름>을 입력해주면 된다.

 

그 후 git push heroku master를 해준다. 푸쉬가 다 잘 됐다면, 터미널에

heroku run python manage.py migrate
heroku run python manage.py createsuperuser
heroku run python manage.py collectstatic

을 해준 다음, heroku open을 하면 된다. 끝!!

참고로 터미널에서 heroku run bash를 한 뒤, cd명령어 등을 이용해 작업할 수도 있다.

+ Recent posts