2.7 파이썬 for 반복문

다음과 같이 문자열을 반복해서 출력해야 하는 경우를 생각해보자.

print("=1=")
print("=2=")
print("=3=")
print("=4=")
print("=5=")
print("=6=")
print("=7=")
print("=8=")
print("=9=")
=1=
=2=
=3=
=4=
=5=
=6=
=7=
=8=
=9=

for 반복문

파이썬에서는 이렇게 명령이 반복될 수 있게 하는 for 반복문(loop)을 사용할 수 있다. for 반복문은 다음과 같이 사용한다.

for 카운터변수 in range(반복횟수):
    반복해서 실행할 명령

이 때 반복횟수는 10, 100과 같은 양의 정수이어야 한다.

현재 몇 번째 반복인지를 알려주는 변수를 카운터 변수(counter variable)이라고 한다. 카운터 변수의 이름은 아무거나 쓸 수 있다. 하지만 전문 프로그래머들은 보통 i 또는 j 라는 변수 이름을 자주 사용한다.

for i in range(10):
    print("=")
=
=
=
=
=
=
=
=
=
=

카운터 변수는 반복 실행될 때마다 현재의 실행 횟수에 해당하는 숫자가 들어가게 되는데, 가장 처음 실행할 때는 아직 한 번도 실행한 적이 없기 때문에 0이 된다.

for i in range(10):
    print(i)
0
1
2
3
4
5
6
7
8
9

따라서 시작 부분에서 나타낸 프로그램은 반복문을 쓰면 다음과 같이 짧은 프로그램으로 바꿀 수 있다.

for i in range(10):
    print("=" + str(i) + "=")
=0=
=1=
=2=
=3=
=4=
=5=
=6=
=7=
=8=
=9=

그런데 시작이 0이라서 우리가 원하는 결과와 달라졌다. 그래서 프로그램을 다음과 같이 고쳐야 한다.

for i in range(9):
    print("=" + str(i + 1) + "=")
=1=
=2=
=3=
=4=
=5=
=6=
=7=
=8=
=9=

카운터 변수는 항상 0부터 시작하므로 1부터 시작하는 것처럼 보이게 하려면 1을 더해주어야 한다. 또 1부터 9까지 9번만 실행하면 되기 때문에 반복횟수도 10이 아니라 9가 되었다.

연습 문제 2.7.1

for 반복문과 문자열 연산을 사용하여 다음과 같이 출력한다.

*
**
***
****
*****
******
*******
********
*********
**********

연습 문제 2.7.2

for 반복문과 문자열 연산을 사용하여 다음과 같이 출력한다.

**********
*********
********
*******
******
*****
****
***
**
*

연습 문제 2.7.3

for 반복문과 문자열 연산, if 조건문을 사용하여 다음과 같이 출력한다.

*
**
***
****
*****
******
*******
********
*********
**********
*********
********
*******
******
*****
****
***
**
*

연습 문제 2.7.4

for 반복문과 문자열 연산, if 조건문을 사용하여 다음과 같이 출력한다.

     * 
    ***
   *****
  *******
 *********
***********
 *********
  *******
   *****
    ***
     *

중첩 for 반복문

때로는 반복문 안에서 다시 반복문을 실행해야 할 때가 있을 수 있다. 예를 들어 다음과 같이 출력해야 할 때를 생각해 보자.

0 1 2 3 
1 2 3 4 
2 3 4 5 
3 4 5 6 

여러가지 방법이 있을 수 있지만 다음과 같이 for 반복문 안에 다시 for 반복문을 사용하는 중첩 반복문(nested loop)를 사용할 수도 있다.

for i in range(4):
    for j in range(4):
        print(i + j, end=" ")
    print()
0 1 2 3 
1 2 3 4 
2 3 4 5 
3 4 5 6 

중첩 반복문을 사용할 때는 각각의 반복문에서 쓰고 있는 카운터 변수의 이름이 겹치지 않도록 주의해야 한다. 앞의 예에서는 바깥쪽 반복문의 카운터 변수는 i를 사용하였고 안쪽 반복문의 카운터 변수는 j를 사용하여 카운터 변수의 이름이 겹치지 않도록 하였다.

경우의 수를 구하는 데도 중첩 반복문을 사용할 수 있다. 예를 들어 1부터 6까지의 눈금이 있는 주사위를 두 번 던져서 나온 숫자들은 다음과 같이 구한다.

for i in range(6):
    n1 = i + 1
    for j in range(6):
        n2 = j + 1
        print(n1, n2)
1 1
1 2
1 3
1 4
1 5
1 6
2 1
2 2
2 3
2 4
2 5
2 6
3 1
3 2
3 3
3 4
3 5
3 6
4 1
4 2
4 3
4 4
4 5
4 6
5 1
5 2
5 3
5 4
5 5
5 6
6 1
6 2
6 3
6 4
6 5
6 6

만약 주사위를 두 번 던져서 나온 숫자들의 합이 4의 배수가 되는 경우만 구해야 한다면 다음과 같이 if 조건문을 추가한다.

for i in range(6):
    n1 = i + 1
    for j in range(6):
        n2 = j + 1
        n = n1 + n2
        if n % 4 == 0:
            print(n1, n2)
1 3
2 2
2 6
3 1
3 5
4 4
5 3
6 2
6 6

연습 문제 2.7.5

어떤 주식의 가격은 매일 한 번 동전을 던져서 앞면이 나오면 전날 가격의 2배가 되고, 뒷면이 나오면 전날 가격의 절반이 된다. 1일에 주식의 가격이 1,024원이었을 때, 4일 주식의 가격이 나올 수 있는 경우를 모두 구한다. (힌트: for 반복문이 3개 중첩되어야 한다)

연습 문제 2.7.6

프랑스의 수학자 페르마(Ferma)의 마지막 정리는 다음과 같다.

n이 2보다 큰 자연수인 경우에, \(a^n + b^n = c^n\) 이 되는 자연수 \(a\), \(b\), \(c\)는 존재하지 않는다.

n이 3이고 a, b, c 가 1부터 10까지의 자연수일 때 페르마의 마지막 정리가 사실임을 중첩 반복문을 써서 보인다. (힌트: 1부터 10까지 반복되는 for 반복문이 3개 중첩되어야 한다.)

카운터 변수가 변하는 경우

반복문에서 가장 복잡한 형태는 안쪽 반복문의 반복 횟수가 바깥쪽 반복문의 카운터 변수에 따라 변하는 상황이다. 예를 들어 1부터 5까지의 합은 다음과 같이 하나의 반복문으로 구할 수 있다.

n = 5

sum = 0
for i in range(n):
    sum = sum + (i + 1)
print(sum)
15

1부터 1까지의 합, 1부터 2까지의 합, 1부터 3까지의 합, 이런 식으로 1부터 10까지의 합을 모두 구해야 한다면 반복문을 다음과 같이 중첩해야 한다.

for j in range(10):
    sum = 0
    for i in range(j + 1):
        sum = sum + (i + 1)
    print(sum)
1
3
6
10
15
21
28
36
45
55

연습 문제 2.7.7

다음과 같은 수열이 있을 경우에 \(n\)번째 수열의 값을 구한다.

\[ 1 \]
\[ 1 + (1 + 2) \]
\[ 1 + (1 + 2) + (1 + 2 + 3) \]
\[ 1 + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) \]
\[ \vdots \]
\[ 1 + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) + \cdots + (1 + \cdots + n) \]