본문 바로가기

2. 정보영재교육 수업 자료

[430] 2주차 조건문, 반복문

"인간의 욕심은 끝이 없고, 같은 실수를 반복한다."의 순서도

모든 알고리즘은 "순차", "선택", "반복"이라는 세 가지 기본 제어 구조로 구성할 수 있다는 것이 수학적으로 증명되어 있습니다.

그리고 이 증명은 현대 프로그래밍의 기초를 이루는 구조적 프로그래밍(Structured Programming)의 이론적 배경이 되었습니다.

이번 글에서는 이 중 "선택""반복"조건문반복문으로 어떻게 구현하는지 살펴보도록 하겠습니다.

 

1. 조건문

조건문은 조건(참과 거짓)에 따라 서로 다른 동작을 수행하도록 하는 문장입니다.

조건문은 파이썬에서 다음과 같이 사용합니다.

apple = 5
banana = 3

if apple < banana:
	print("사과보다 바나나가 더 많습니다.")
elif apple > banana:
	print("바나나보다 사과가 더 많습니다.")
else:
	print("사과와 바나나 수가 같습니다.")
    
# 바나나보다 사과가 더 많습니다.

 

조건식에는 그 결과가 "참"이나 "거짓"으로만 나오는 변수, 함수, 연산식 등을 사용합니다.

 

이 때, "참"이나 "거짓"을 값으로 가지는 자료형이 등장합니다.

이 자료형은 불리언 자료형 혹은 논리 자료형이라고 합니다.

이 자료형에 속하는 값은 TrueFalse, 단 두 가지만 존재합니다.

print(type(True))
# <class 'bool'>

print(type(False))
# <class 'bool'>

https://ko.wikipedia.org/wiki/불리언_자료형

 

불리언 자료형 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 과학에서 불리언 자료형(Boolean Data Type) 또는 참거짓은 논리 자료형이라고도 하며, 참과 거짓을 나타내는 데 쓰인다. 주로 참은 1, 거짓은 0에 대응하나

ko.wikipedia.org

 


 

가. 관계 연산자(비교 연산자)

참과 거짓을 결과로 반환하는 연산자에는 관계 연산자 논리 연산자가 있습니다.

 

관계 연산자는 두 피연산자의 같음과 다름, 또는 크고 작음의 관계를 나타냅니다.

두 피연산자의 값을 비교하기 때문에 관계 연산자를 프로그래밍에서는 비교 연산자라고 부릅니다.

 

파이썬에는 같음(==), 다름(!=), 크거나 같음(>=), 작거나 같음(<=), 큼(>), 작음(<) 여섯 개의 비교 연산자가 있습니다.

기본적으로 정수형을 많이 비교하지만, 파이썬에서 문자열도 비교가 가능합니다.

문자열의 비교 결과는 사전 순으로 더 뒤에 나오는 문자열이 더 크다고 판단합니다.

 

같음(==)

print(1 == 1)
# True
print(1 == 2)
# False

print("str" == "str")
# True
print("str" == "Str")
# False

a = 1
b = 1
c = 2
print(a == b)
# True
print(a == c)
# False

 

다름(!=)

print(1 != 1)
# False
print(1 != 2)
# True

print("str" != "str")
# False
print("str" != "Str")
# True

a = 1
b = 1
c = 2
print(a != b)
# False
print(a != c)
# True

 

크거나 같음(>=)

print(1 >= 1)
# True
print(2 >= 1)
# True
print(1 >= 2)
# False

print("a" >= "a")
# True
print("a" >= "b")
# False
print("b" >= "a")
# True

print("abcd" >= "ad")
# False
print("ad" >= "abcd")
# True

 

작거나 같음(<=)

print(1 <= 1)
# True
print(2 <= 1)
# False
print(1 <= 2)
# True

print("a" <= "a")
# True
print("a" <= "b")
# True
print("b" <= "a")
# False

print("abcd" <= "ad")
# True
print("ad" <= "abcd")
# False

 

큼(>)

print(1 > 1)
# False
print(2 > 1)
# True
print(1 > 2)
# False

print("a" > "a")
# False
print("a" > "b")
# False
print("b" > "a")
# False

print("abcd" > "ad")
# False
print("ad" > "abcd")
# True

 

작음(<)

print(1 < 1)
# False
print(2 < 1)
# False
print(1 < 2)
# True

print("a" < "a")
# False
print("a" < "b")
# True
print("b" < "a")
# False

print("abcd" < "ad")
# True
print("ad" < "abcd")
# False

 

 

풀어볼 문제

두 수 비교하기 https://www.acmicpc.net/problem/1330

더보기
a, b = map(int, input().split())
if _____:
    print("<")
elif _____:
    print(">")
else:
    print("==")

 

아! https://www.acmicpc.net/problem/4999

더보기

 

a, b = input(), input()
if _____:
    print("go")
else:
    print("no")

 

나. 논리 연산자

조건식에서 사용할 수 있는 두 번째 연산자는 논리 연산자입니다.

논리 연산자를 잘 사용한다면 조건문의 코드를 더 간결하게 작성 할 수 있습니다.

논리 연산자는 참과 거짓(논리 자료형)을 피연산자로 받아, 결과도 참과 거짓으로 나타납니다.

논리 연산자에는 논리합, 논리곱, 부정 등이 있습니다.

 

논리합(or)

피연산자1 피연산자2 연산 결과
거짓
거짓
거짓 거짓 거짓
print(True or True)
# True

print(True or False)
# True

print(False or True)
# True

print(False or False)
# False

https://ko.wikipedia.org/wiki/논리합

 

논리합 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 논리합(disjunction, 論理合, OR)이란 수리 논리학에서 주어진 복수 명제에 적어도 1개 이상의 참이 있는지를 나타내는 논리 연산이다. 두 명제 P, Q에 대하여 논리합

ko.wikipedia.org

 

논리곱(and)

피연산자1 피연산자2 연산 결과
거짓 거짓
거짓 거짓
거짓 거짓 거짓
print(True and True)
# True

print(True and False)
# False

print(False and True)
# False

print(False and False)
# False

https://ko.wikipedia.org/wiki/논리곱

 

논리곱 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. AND 논리 게이트 논리곱(conjunction, AND)이란 수리 논리학에서, 주어진 복수 명제 모두가 참인지를 나타내는 논리 연산이다. 두 명제 P, Q에 대한 논리곱을 (P ∧ Q)라

ko.wikipedia.org

 

부정(not)

피연산자 연산 결과
거짓
거짓
print(not True)
# False

print(not False)
# True

https://ko.wikipedia.org/wiki/부정_(논리학)

 

부정 (논리학) - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 수리 논리학에서 부정(否定)은 명제의 참과 거짓을 반전하는 논리 연산이다. 명제 P에 대한 부정을 ¬P, P ¯ {\displaystyle {\bar {P}}} , ~p, !P등으로 쓰고, ‘P 가 아니

ko.wikipedia.org

 

 

풀어볼 문제

사분면 고르기 https://www.acmicpc.net/problem/14681

더보기
x = int(input())
y = int(input())
if _____ and _____:
    print(1)
elif _____ and _____:
    print(2)
elif _____ and _____:
    print(3)
else:
    print(4)

 

몇개고? https://www.acmicpc.net/problem/27294

더보기
T, S = map(int, input().split())
if _____:
    print(_____)
else:
    print(_____)

 

다. 알쓸몰이

※ 알아두면 쓸모 있지만 몰라도 되는 이야기

 

가끔 아주 단순한 조건문을 사용하고 싶을 때 삼항연산자라는 것을 사용할 수 있습니다.

예를 들어 어떤 사람의 주민등록번호 뒷 자리 첫 번째 숫자를 출력하고 싶을 때가 있습니다.

성별 = "남"
if 성별 == "남":
	print(1)
else:
	print(2)
# 1

성별 = "여"
if 성별 == "남":
    print(1)
else:
    print(2)
# 2

배운대로 한다면 위와 같이 해야하지만, 너무 단순한 동작 치고는 코드가 깁니다.

이 때 삼항연산자를 사용하면 다음과 같이 작성할 수 있습니다.

성별 = "남"
print(1 if 성별 == "남" else 2)
# 1

성별 = "여"
print(1 if 성별 == "남" else 2)
# 2

위와 같이 단순한 조건으로, 다른 값을 출력하거나 변수에 할당할 때 사용할 수 있습니다.

 

파이썬에는 Truthy한 값과 Falsy한 값이 존재합니다.

Truthy한 값은 비교 연산자에서 True로 판단하고, Falsy한 값은 False로 판단합니다.

몰라도 충분히 문제를 풀 수 있지만, 알고 있다면 코드를 직관적이면서도 간결하게 작성할 수 있습니다.

(주의! 잘못 이해하고 사용하다가 해당 부분에서 오류가 발생한다면 오류를 찾아내기 어려워질 수도 있습니다.)

Falsy Truthy
0(0.0) 0을 제외한 정수, 실수
""(빈 문자열) 비어있지 않은 문자열
[], {}, (), set()(비어있는 list, dict, tuple, set) 원소를 가지고 있는 list, dict, tuple, set
None(null 타입) ...(Ellipsis 타입)

 


 

2. 반복문

컴퓨터 프로그램의 가장 큰 장점 중 하나는 어려운 계산들을 빠른 시간 안에 반복적으로 수행할 수 있다는 것입니다.

반복문에서 핵심은 반복을 어떻게 제어할 것인가입니다.

파이썬에서 사용하는 반복문은 이 반복 제어에 따라 크게 for문while문을 사용합니다.

for문은 특정 순서를 가지고 반복을 제어하고, while문은 특정 조건을 가지고 반복을 제어합니다.

 

다만, for문과 while문을 사용하기 좋은 조건을 이야기 한 것이지, 반드시 for문을 사용해야하거나 반드시 while문을 사용해야하는 상황은 없습니다.

모든 for문을 while문으로 만들 수도 있고, 모든 while문을 for문으로 만들 수도 있습니다.

 


 

가. for문

for문은 파이썬에서 다음과 같이 사용합니다.

반복할 수 있는 데이터는 파이썬에서 iterable 하다고 표현합니다.

iterable 한 자료형에는 문자열(str), 리스트(list), 딕셔너리(dict), 집합(set), 튜플(tuple) 등이 해당합니다.

변수 자리에는 새로운 변수명을 쓰고, iterable 한 데이터에서 원소를 하나씩 꺼내 변수에 담아줍니다.

 

https://docs.python.org/3/glossary.html#term-iterable

 

Glossary

>>>, The default Python prompt of the interactive shell. Often seen for code examples which can be executed interactively in the interpreter.,,..., Can refer to:- The default Python prompt of the i...

docs.python.org

 

우리가 알고 있는 문자열을 사용해서 반복문을 사용해봅시다.

for character in "python":
    print(character)
# p
# y
# t
# h
# o
# n

for문의 주어진 문자열에서 character라는 변수에 한 글자 씩 담아print()를 반복 실행시킵니다.

 

만약 1 ~ 10까지 정수를 변수에 차례대로 담아 반복시키고 싶다면 어떻게 할까요?

for i in 10:
    print(i)
# TypeError: 'int' object is not iterable

정수형iterable 하지 않아 에러가 발생합니다.

대신 range()를 사용합니다.

range에 대한 자세한 설명은 이후 함수를 공부하며 알아가기로 하고, 일단은 정수형을 iterable 하게 바꾸어 반환해준다고 이해합시다.

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

우리가 원하는 1 ~ 10이 아닌 0 ~ 9가 출력됩니다.

총 10개로 10번 반복하는 것은 맞으나, 시작 숫자가 1이 아닌 0임을 기억합시다.

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

변수에 1을 더해줌으로써 1 ~ 10을 출력하였습니다.

range()에 넘겨주는 값을 조금 다르게 하여 출력할 수도 있습니다.

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

range()에 값을 두 개 넘겨주면, 하나는 시작값으로, 다른 하나는 종료값으로 사용합니다.

대신 조심해야할 것이 종료값은 그 이전 수까지만 반복한다는 것을 알아야합니다.

반복 횟수는 (두 번째 값 - 첫 번째 값) 만큼 반복합니다.

 

for문을 더 잘 사용하기 위해서는 iterable 한 다양한 자료형에 대해서 알아야 합니다.

차차 더 많은 자료형을 공부하며 for문을 응용하여 사용해봅시다.

 

풀어볼 문제

N 찍기 https://www.acmicpc.net/problem/2741

더보기
N = int(input())
for i in range(_____):
    print(_____)

 

합 https://www.acmicpc.net/problem/8393

더보기
N = int(input())
res = 0
for i in range(_____):
    res = _____
print(res)

 

주사위 https://www.acmicpc.net/problem/9295

더보기
T = int(input())
for i in range(_____):
    a, b = map(int, input().split())
    print(_____)

 

나. 2중 for문, 3중 for문

구구단을 2단에서 9단까지 출력하고 싶다면 어떻게 할까요?

for문 안에 for문을 집어넣어서 만들면 가능합니다.

for i in range(2, 10):
    for j in range(1, 10):
        print(i, "*", j, "=", i*j)
# 2 * 1 = 2
# 2 * 2 = 4
# 2 * 3 = 6
# 2 * 4 = 8
# 2 * 5 = 10
# 2 * 6 = 12
# 2 * 7 = 14
# 2 * 8 = 16
# 2 * 9 = 18
# 3 * 1 = 3
# 3 * 2 = 6
# 3 * 3 = 9
# 3 * 4 = 12
# 3 * 5 = 15
# 3 * 6 = 18
# 3 * 7 = 21
# 3 * 8 = 24
# 3 * 9 = 27
# 4 * 1 = 4
# 4 * 2 = 8
# 4 * 3 = 12
# 4 * 4 = 16
# 4 * 5 = 20
# 4 * 6 = 24
# 4 * 7 = 28
# 4 * 8 = 32
# 4 * 9 = 36
# 5 * 1 = 5
# 5 * 2 = 10
# 5 * 3 = 15
# 5 * 4 = 20
# 5 * 5 = 25
# 5 * 6 = 30
# 5 * 7 = 35
# 5 * 8 = 40
# 5 * 9 = 45
# 6 * 1 = 6
# 6 * 2 = 12
# 6 * 3 = 18
# 6 * 4 = 24
# 6 * 5 = 30
# 6 * 6 = 36
# 6 * 7 = 42
# 6 * 8 = 48
# 6 * 9 = 54
# 7 * 1 = 7
# 7 * 2 = 14
# 7 * 3 = 21
# 7 * 4 = 28
# 7 * 5 = 35
# 7 * 6 = 42
# 7 * 7 = 49
# 7 * 8 = 56
# 7 * 9 = 63
# 8 * 1 = 8
# 8 * 2 = 16
# 8 * 3 = 24
# 8 * 4 = 32
# 8 * 5 = 40
# 8 * 6 = 48
# 8 * 7 = 56
# 8 * 8 = 64
# 8 * 9 = 72
# 9 * 1 = 9
# 9 * 2 = 18
# 9 * 3 = 27
# 9 * 4 = 36
# 9 * 5 = 45
# 9 * 6 = 54
# 9 * 7 = 63
# 9 * 8 = 72
# 9 * 9 = 81

i 변수에 2 ~ 9가 하나씩 담길 때마다, j 변수에 1 ~ 9가 차례대로 담기는 과정이 반복됩니다.

 

응용하여 3중 for문도 작성할 수 있습니다.

for i in range(3):
    for j in range(3):
        for k in range(3):
            print(i, j, k)
# 0 0 0
# 0 0 1
# 0 0 2
# 0 1 0
# 0 1 1
# 0 1 2
# 0 2 0
# 0 2 1
# 0 2 2
# 1 0 0
# 1 0 1
# 1 0 2
# 1 1 0
# 1 1 1
# 1 1 2
# 1 2 0
# 1 2 1
# 1 2 2
# 2 0 0
# 2 0 1
# 2 0 2
# 2 1 0
# 2 1 1
# 2 1 2
# 2 2 0
# 2 2 1
# 2 2 2

 

이렇게 다중 for문을 사용할 때 주의해야할 점은 반복이 겹칠 때마다 반복 횟수가 급격하게 커진다는 점입니다.

아무리 컴퓨터의 계산이 빨라도 연산 횟수가 커지면 그만큼 연산 시간이 많이 걸리게 됩니다.

알고리즘 문제를 풀 때, 보통 1억 번의 연산을 1초로 계산하곤 합니다.

알고리즘 문제에는 시간제한이 항상 존재하므로, 주어진 시간제한을 확인하여 나의 알고리즘이 해당 시간 안에 정답을 구해낼 수 있을지 판단해야 합니다.

 

풀어볼 문제

쉽게 푸는 문제 https://www.acmicpc.net/problem/1292

더보기
A, B = map(int, input().split())
res = 0
cnt = 0
for _____ in range(_____):
    for _____ in range(_____):
        cnt = _____
        if A <= cnt <= B:
            res = _____
print(res)

 

다. while문

파이썬에서 while문은 다음과 같이 사용합니다.

조건식이 참일 경우, 실행할 코드를 한 번 실행합니다.

실행한 후에 다시 조건식을 살펴보고 참일 경우 코드를 또 실행합니다.

조건식이 거짓이 되는 순간 반복이 멈추게 됩니다.

 

while문은 for문 보다 조심히 사용해야 합니다.

만약 조건식이 계속해서 참일 경우 반복이 끝나지 않아, 무한히 반복되는 상황이 생길 수도 있습니다.

 

while문을 사용하는 기본적인 방법은 정수형 변수를 사용하여 해당 변수의 값을 반복문 안에서 변경해가면서 반복하는 방법입니다.

i = 1
while i <= 10:
    print(i)
    i = i + 1 # 조건식의 변수값을 변경
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10

 

반복문이 실행되는 도중 원치 않게 갑자기 반복을 멈춰야하는 순간이 오기도 합니다.

이 때 사용하는 문법이 break 입니다.

i = 0
while True:
    if i > 5:
        break
    print(i)
    i = i + 1
# 0
# 1
# 2
# 3
# 4
# 5

while문의 조건식이 True 이므로 이 코드는 무한 반복하게 됩니다.

그러나 if문의 조건식이 i 가 5 보다 클 때, break 를 동작시키므로 i 값이 6일 때 이 반복문은 멈추게 됩니다.

 

break 는 for문에서도 사용 가능합니다.

for i in range(10):
    if i == 3:
        break
    print(i)
# 0
# 1
# 2

i = 0
while i < 10:
    if i == 3:
        break
    print(i)
    i += 1
# 0
# 1
# 2

원래라면 0 ~ 9 까지 차례대로 출력되어야 하나, 중간에 break 로 인해 0 ~ 2 까지만 출력됩니다.

이렇게 breakif 와 함께 사용됩니다.

 

 

while문은 알고리즘 문제에서 입력값의 갯수가 정해져있지 않을 때, 또는 for문으로 해결하기 어렵거나 변수의 변화를 상황에 따라 다르게 하고 싶을 때 사용합니다.

 

풀어볼 문제

A + B(5) https://www.acmicpc.net/problem/10952

더보기
while True:
    a, b = map(int, stdin.readline().split())
    if _____:
        _____
    print(a + b)

 

더하기 사이클 https://www.acmicpc.net/problem/1110

더보기
N = int(input())
n = N
cnt = 0
while _____:
    a, b = _____, _____
    n = _____
    cnt += 1
print(cnt)

 

라. 알쓸몰이

※ 알아두면 쓸모 있지만 몰라도 되는 이야기

 

할당 연산자는 기본적으로 = 입니다.

변수에 특정 값을 할당할 때 사용됩니다.

그러나 +=-= 등과 같이 산술연산자와 붙여서 사용한다면 기존 할당되어 있던 값에 입력 받은 값을 연산하여 결과를 할당합니다.

a = 10
a += 1 # a = a + 1 과 같이 동작
print(a)
# 11

a -= 5 # a = a - 5 와 같이 동작
print(a)
# 6

변수의 값을 자주 변화시키는 while문에서 자주 사용되니 알아두면 좋습니다.

 

반복문이 실행되는 도중 반복을 한번 건너뛰고 싶을 때가 있습니다.

이 때 사용하는 문법이 countinue 입니다.

for i in range(10):
    if i % 2 == 0:
        continue
    print(i)
# 1
# 3
# 5
# 7
# 9

반복 도중 2로 나누어 떨어지는 값에서는 continue 로 인해 이후 코드가 동작하지 않고, 다음 반복으로 바로 넘어갑니다.

이렇게 continueif 와 함께 사용됩니다.

 

반복문과 함께 else 를 사용하기도 합니다.

else 이후에 작성되는 코드는 반복문이 break 되지 않고 끝까지 실행되었을 경우에 실행됩니다.

for i in range(3):
    print(i)
else:
    print("완료")
# 0
# 1
# 2
# 완료

for i in range(3):
    if i == 2:
        break
    print(i)
else:
    print("완료")
# 0
# 1

i = 0
while i < 3:
    print(i)
    i += 1
else:
    print("완료")
# 0
# 1
# 2
# 완료

i = 0
while i < 3:
    if i == 2:
        break
    print(i)
    i += 1
else:
    print("완료")
# 0
# 1

 


 

더 공부할 내용

iterable 자료형들(리스트, 딕셔너리, 집합, 튜플 등)

내장함수, 내장객체, 객체의 메서드 사용법

비트 연산