알고리즘 입문
개념 배우기직접 풀어보기
놀면 뭐 하니,
그냥 하는거야.

쌓아서 만든다! 반복과 누적

코딩냥

안녕, 나 코딩냥이다냥! 지금까지 두 번 다 "상자를 만들고 훑으면서 쌓는" 뼈대를 썼지? 오늘은 그 상자를 제대로 다루는 법을 판다냥. 별거 아닌 것 같은데, 여기서 실수하면 답이 통째로 틀린다냥.

오늘의 학습 목표

  • range() 를 세 가지 형태로 자유롭게 쓴다.
  • 누적 상자의 시작값을 왜 그렇게 고르는지 설명할 수 있다.
  • % 와 // 로 숫자를 자릿수로 쪼갠다.
  • 값 두 개를 동시에 기억하는 반복을 만든다.

1단계 · range 를 제대로 알자냥 (7분)

코딩냥

리스트가 없어도 반복할 수 있다냥. range() 가 숫자를 순서대로 만들어준다냥.

for i in range(5):
    print(i)          # 0 1 2 3 4

for i in range(2, 6):
    print(i)          # 2 3 4 5

for i in range(10, 0, -2):
    print(i)          # 10 8 6 4 2

세 가지 형태

쓰는 법뜻결과
range(5)0부터 5 직전까지0 1 2 3 4
range(2, 6)2부터 6 직전까지2 3 4 5
range(10, 0, -2)10부터 0 직전까지 2씩 빼며10 8 6 4 2

문자열 슬라이싱이랑 똑같다냥 — 뒤 숫자는 "직전까지" 라냥.

1부터 n까지 더하고 싶은데 range(n) 이라고 쓰면 안 된다냥.

range(n) 은 0부터 n-1까지라서 n이 빠진다냥. 1부터 n까지는 range(1, n + 1) 이라고 써야 한다냥. 여기서 +1 을 빠뜨리는 실수가 정말 많다냥.

2단계 · 시작값을 잘못 고르면 답이 틀린다냥 (10분)

코딩냥

첫 시간에 최댓값 상자를 0 으로 두면 안 된다고 했지? 기억하냥? 오늘은 그 이야기의 완성판이라냥.

더할 때는 0, 곱할 때는 1

# 합계
total = 0
for i in range(1, 6):
    total = total + i
print(total)          # 15

# 곱셈 (팩토리얼)
result = 1
for i in range(1, 6):
    result = result * i
print(result)         # 120

곱셈 상자를 0 으로 시작하면 어떻게 되냥?

0 * 1 * 2 * 3 * ... 은 무조건 0 이라냥. 아무리 곱해도 0에서 못 벗어난다냥. 그래서 곱셈은 반드시 1 로 시작해야 한다냥.

원리시작값은 '아직 아무것도 안 했을 때의 답'

왜 합은 0이고 곱은 1이냥? 규칙을 외우지 말고 이렇게 생각하자냥.

  • 아무것도 안 더했을 때 합은? → 0
  • 아무것도 안 곱했을 때 곱은? → 1
  • 아무것도 안 봤을 때 최댓값은? → 없다. 그래서 첫 원소로 시작한다냥

이 질문 하나로 세 경우가 전부 설명된다냥.

3단계 · 숫자를 자릿수로 쪼개기 (10분)

코딩냥

1234 의 각 자리를 더해서 1+2+3+4 를 구하려면 어떻게 하냥? 문자열로 바꿔도 되지만, 숫자인 채로 쪼개는 법을 알아두면 두고두고 쓴다냥.

무기는 두 개라냥.

print(1234 % 10)     # 4    나머지 = 맨 뒤 자리
print(1234 // 10)    # 123  몫 = 맨 뒤 자리를 떼어낸 나머지

비유로 이해하기 — 사탕 꺼내기

% 10 은 맨 뒤 사탕을 꺼내 보는 것이고, // 10 은 그 사탕을 버리는 것이라냥. 둘을 번갈아 하면 사탕을 하나씩 다 꺼낼 수 있다냥.

n = 1234
total = 0

while n > 0:
    total = total + n % 10    # 맨 뒤 자리를 더하고
    n = n // 10               # 맨 뒤 자리를 버린다냥

print(total)                  # 10
추적한 바퀴씩 따라가보자냥
바퀴nn % 10total다음 n
1123444123
21233712
312291
411100

n 이 0이 되면 반복이 끝난다냥. 표로 한 줄씩 따라가보는 습관을 들이면 머릿속에서 코드가 굴러가기 시작한다냥.

여기서는 for 가 아니라 while 을 썼다냥. 몇 번 도는지 미리 모르기 때문이라냥.

  • 횟수를 아는 반복 → for
  • 조건이 만족되는 동안 도는 반복 → while

자릿수는 숫자마다 다르니까 while 이 맞다냥.

4단계 · 두 개를 동시에 기억하기 (8분)

코딩냥

마지막이자 오늘 제일 어려운 부분이라냥. 지금까지는 상자가 하나였는데, 두 개가 필요한 경우가 있다냥. 피보나치라냥.

피보나치는 앞의 두 수를 더해서 다음 수를 만든다냥.

1 1 2 3 5 8 13 ...

그러니까 항상 직전 두 개를 기억하고 있어야 한다냥.

a, b = 1, 1              # 상자 두 개

for _ in range(5):
    a, b = b, a + b      # 동시에 갱신한다냥

print(a)

a, b = b, a + b 를 두 줄로 쪼개면 틀린다냥.

a = b          # a 가 먼저 바뀌어버리고
b = a + b      # 바뀐 a 를 쓰게 된다냥. 망했다냥

파이썬은 a, b = b, a + b 를 쓸 때 오른쪽을 먼저 다 계산한 다음 왼쪽에 넣는다냥. 그래서 한 줄로 써야 안전하다냥.

추적a, b 가 어떻게 굴러가냥
바퀴 전ab계산 후 a계산 후 b
11112
21223
32335
43558

a 가 한 칸씩 뒤로 따라가는 게 보이냥? 이 패턴은 나중에 배울 알고리즘에도 자주 나온다냥.

오늘 배운 내용 정리

코딩냥

먼저 스스로 답해보고, "정답 보기"를 눌러서 맞는지 확인해보자냥!

Q1.1부터 n까지 더하려면 range 를 어떻게 써야 하냥?
Q2.곱셈 누적 상자를 0으로 시작하면 왜 안 되냥?
Q3.1234 에서 맨 뒤 자리 4 를 꺼내고, 그 다음 123 을 만들려면?
Q4.for 와 while 중 어느 걸 쓸지 어떻게 정하냥?
Q5.a, b = b, a + b 를 두 줄로 나눠 쓰면 왜 틀리냥?

이제 직접 풀어볼 차례다냥

코딩냥

오늘 문제는 다섯 개라냥. 앞의 셋은 오늘 배운 걸 하나씩 확인하는 것이고, 뒤의 둘은 엮어야 풀린다냥. 특히 마지막 피보나치는 위의 표를 손으로 한 번 따라 그려보고 시작하는 걸 추천한다냥. 가보자냥~