반복하는 알고리즘
Preface
이번 장은 내용이 많아 이틀에 걸쳐 조금씩 공부했다.
코드를 한 줄 한 줄 분석하며 이해하다 보니 시간은 조금 오래 걸렸지만, 그동안 파이썬으로 별 생각 없이 작성하던 코드들이 어떤 방식으로 작동하는 것인지 생각해 볼 수 있었다.
또, 단일 대입문과 비교 연산자의 연속적인 사용 방법, 가우스의 덧셈, 드모르간의 법칙 등 새로운 내용들도 배울 수 있었으며, 다양한 방식(내가 그동안 생각치 못했던 방식)으로 작성된 코드를 접하자 알고리즘을 통해 코드를 작성하는 방법은 정말 무궁무진하다는 것을 다시 한 번 느낄 수 있었다.
물론 중간 중간 내가 생각하는 방식대로 코드를 작성해 보기도 했다.
마지막으로 이번 장을 공부하며 코드를 작성할 땐 계산(반복)을 최대한 줄여 복잡성을 감소시키는 것이 중요한 것 같다는 생각을 했다.
1. 반복하는 알고리즘
- 반복 구조(루프) : 특정 조건이 성립한는 동안 반복에서 명령어를 처리하는 것
- 사전 판단 반복 구조 : 명령을 실행하기 전 반복을 계속할 것인지를 판단하는 구조
→ ex) while 문
- 루프 본문 : 반복 대상이 되는 명령문
- 카운터용 변수 : 반복을 제어할 때 사용하는 변수
- 가우스(gauss)의 덧셈 : 1부터 n까지 정수의 합을 구하는 수학 식
→ sum = n * (n + 1) // 2
- 이터러블(iterable) 객체 : 반복할 수 있는 객체
→ list, str, tuple etc.
- 단일 대입문 : a와 b의 값을 교환할 때 사용
→ a, b = b, a
- 정수의 합을 구하는 코드
print('a부터 b까지 정수의 합을 구합니다.')
a = int(input('정수 a를 입력하세요.: '))
b = int(input('정수 b를 입력하세요.: '))
if a > b:
a, b = b, a
sum = 0
for i in range(a, b + 1):
if i < b:
print(f'{i} + ', end='')
else:
print(f'{i} = ', end='')
sum += i
print(sum)
→ 알고리즘의 효율을 높여 재작성한 코드
print('a부터 b까지 정수의 합을 구합니다.')
a = int(input('정수 a를 입력하세요.: '))
b = int(input('정수 b를 입력하세요.: '))
if a > b:
a, b = b, a
sum = 0
for i in range(a, b):
print(f'{i} + ', end='')
sum += i
print(f'{b} = ', end='')
sum += b
print(sum)
- 연산자를 출력하는 코드를 리스트를 사용해서 작성해 보았다.
n = int(input('몇 개를 출력할까요?: '))
result = []
for i in range(n):
if i % 2:
result.append('-')
else:
result.append('+')
a = ''.join(result)
print(a)
→ 알고리즘의 효율을 높여 재작성한 코드
n = int(input('몇 개를 출력할까요?: '))
for _ in range(n // 2):
print('+-', end='')
if n % 2:
print('+', end='')
print()
- 언더스코어(_) : 무시하고 싶은 값을 표현할 때 사용
- for 문에서 리스트를 연속으로 출력하는 코드
for i in list(range(1, 8)) + list(range(9, 13)):
print(i, end=' ')
print()
- 줄바꿈 코드
n = int(input('몇 개 출력하시겠습니까?: '))
m = int(input('몇 개마다 줄바꿈 하시겠습니까?: '))
for _ in range(n // m):
print('*' * m)
rest = n % m
if rest:
print('*' * rest)
→ for 문을 반복할 때마다 if 문을 실행하는 것은 비효율적이므로 효율성을 높여 리팩토링 한 코드
- 무한 루프 : while 문이 무한 반복되도록 만든 것
- 사후 판단 반복분 : 루프 본문을 한 번 실행한 후 계속 반복할지 판단
→ python에선 이를 지원하지 않으므로 beak 문으로 탈출!
- 반복문
1) continue 문 : 루프 본문의 나머지 부분을 건너뛰고 처음 조건식으로 돌아간다.
2) break 문 : else 문을 포함하여 while 문을 강제로 종료한다.
3) else 문 : break 문이 실행되지 않았을 때만 실행된다.
- else 문이 뒤따르는 for 문
import random
n = int(input('난수의 개수를 입력하세요.: '))
for _ in range(n):
r = random.randint(10, 99)
print(r, end=' ')
if r == 13:
print('\n프로그램을 종료합니다.')
break
else:
print('\n난수 생성을 종료합니다.')
- 비교연산자 사용 방법
1) 연속으로 사용한 비교 연산자는 'and 결합'으로 취급한다.
n >= 10 and n <= 99
# 기존 코드
if 10 <= n <= 99:
# n >= 10 and n <= 99 와 같은 코드
2) 드모르간의 법칙 : 각 조건을 부정하고 논리곱을 논리합으로, 논리합을 논리곱으로 바꾼 후 전체를 부정하면 원래의 조건과 같다.
if not(n < 10 or n > 99):
# n >= 10 and n <= 99 와 같은 코드
- 구조적 프로그래밍 : 입력과 출력으로 이루어진 구성 요소를 계층으로 배치하여 프로그램을 구성하는 방법
→ 순차, 선택, 반복의 세 가지 제어 흐름을 사용
- 다중 루프 : 반복문 안에서 다시 반복문을 사용한 것
- 구구단 곱셈표
for i in range(1, 10):
for j in range(1, 10):
print(f'{i * j:3}', end='')
print()
→ ':3'은 포매팅 한 부분이 3자리를 차지함을 나타내는 것 같다.
- 파이썬에서 변수는 객체를 참조하는 객체에 연결된 이름에 불과하다.
→ n = 17 이라는 코드에서 정수 리터럴 17의 식별 번호와 n의 식별 번호가 같다.
- 리터럴(literal) : 문자 자체에 의해 값이 주어지는 문자열 (값 자체를 의미, 고정된 값)