본문으로 건너뛰기

가장 큰 값 찾기

파이썬 목차리스트와 튜플레슨 27 / 59

목차

가장 큰 값 찾기는 첫 값을 지금까지 가장 큰 값으로 두고, 값을 하나씩 꺼내 그보다 크면 바꿔 가는 틀입니다. 다 돌고 나면 이름 하나에 가장 큰 값이 남습니다.

메뉴 가운데 가장 비싼 값, 한 주 가운데 가장 많이 판 날의 잔 수처럼 '가장 ○○한 값'을 찾는 일은 자주 나옵니다. 사람은 눈으로 한꺼번에 훑지만 파이썬은 값을 하나씩 견줄 수 있을 뿐입니다. 그래서 지금까지 본 값 가운데 가장 큰 값에 이름 하나를 붙여 두고, 새 값을 꺼낼 때마다 그것과 견줍니다. 이 레슨은 가장 큰 값을 찾는 코드를 직접 쓰는 틀 레슨입니다. 풀이 예제를 하위 목표 셋으로 나눠 읽고, 빈칸을 채우며 쓰기로 넘어갑니다.

13단계 중 1단계. 가격 셋 가운데 가장 큰 값을 하위 목표 셋으로 찾습니다.

1가장 큰 값 찾기의 세 하위 목표

가격 셋 가운데 가장 큰 값을 찾는 풀이 예제이고, 그림의 코드입니다.

prices = [4000, 4500, 3500]
# 1. 첫 값을 최고로
best = prices[0]
# 2. 하나씩 꺼내 견주어 바꾸기
for price in prices:
    if price > best:
        best = price
# 3. 끝나고 쓰기
print(best)
실행 결과
4500
  • 1. 첫 값을 최고로: 값을 하나만 봤다면 그 값이 지금까지 가장 큰 값입니다. 3번 줄이 best를 첫 값 prices[0], 곧 4000에 붙입니다.
  • 2. 하나씩 꺼내 견주어 바꾸기: 5번 줄의 for는 문자열에서 글자를 꺼냈듯 리스트에서 칸 값을 하나씩 꺼내 그 값에 price를 붙입니다. 6번 줄이 꺼낸 값과 지금의 best를 견주어, 더 크면 7번 줄이 best를 그 값에 다시 붙입니다.
  • 3. 끝나고 쓰기: 반복이 다 끝난 뒤 한 번 찍습니다.

추적 표로 따라가면 best가 언제 바뀌는지 보입니다.

줄바뀐 이름값출력
1prices① [4000, 4500, 3500]
3best4000
5price4000
6조건 price > bestFalse
5price4500
6조건 price > bestTrue
7best4500
5price3500
6조건 price > bestFalse
5꺼낼 수 없음 — 반복 끝
94500

첫 바퀴는 4000과 4000을 견줍니다. 같은 값은 더 크지 않아 best가 바뀌지 않습니다. best처럼 지금까지 본 값 가운데 가장 좋은 값을 붙들어 두는 이름을 가장 좋은 값지기라고 부릅니다. price는 합 모으기의 n처럼 꺼낸 값을 차례로 받는 걸음꾼입니다.

2무엇과 견주는가

한 주 동안 날마다 판 잔 수에서 가장 많은 값을 찾습니다. best가 바뀔 때마다 찍게 했습니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.

cups = [12, 20, 9, 15]
best = cups[0]
for n in cups:
    if n > best:
        best = n
        print(best)
실행 결과 보기
실행 결과
20

예상과 다르면 그곳이 배울 곳입니다. 첫 바퀴의 12는 best와 같아 바뀌지 않고, 둘째 바퀴의 20에서 한 번 바뀝니다. 넷째 바퀴의 15는 바로 앞 값 9보다 크지만 지금의 best 20보다 작아 바뀌지 않습니다. 꺼낸 값은 바로 앞 값이 아니라 지금까지 가장 큰 값과 견줍니다. 그래서 best가 바뀌는 횟수는 바퀴 수보다 적습니다.

3max()와 견주기

파이썬에는 가장 큰 값을 돌려주는 max()가 있습니다. 가장 작은 값은 min()이 돌려줍니다.

prices = [4000, 4500, 3500]
print(max(prices))
print(min(prices))
실행 결과
4500
3500

틀로 찾은 4500과 같습니다. 값 하나만 필요하면 max()로 충분합니다. 틀은 best가 바뀐 횟수를 세거나 조건을 더하는 것처럼 max() 하나로는 안 되는 일로 넓혀 씁니다.

예제

빈 리스트에서 찾으면

리스트가 비어 있으면 가장 큰 값이 없습니다.

prices = []
print(max(prices))
실행 결과
Traceback (most recent call last):  File "main.py", line 2, in <module>    print(max(prices))          ~~~^^^^^^^^ValueError: max() iterable argument is empty

파이썬 3.11에서는 맨 아래 줄의 설명이 max() arg is an empty sequence⁠로 조금 다르게 찍히지만 오류 이름과 뜻은 같습니다.

맨 아래 줄은 'max()에 넘긴 것이 비어 있다'는 뜻입니다. 틀로 쓴 코드도 best = prices[0]에서 꺼낼 첫 값이 없어 IndexError로 멈춥니다. 비어 있을 수 있는 리스트라면 찾기 전에 len(prices)가 0인지 먼저 봅니다.

자주 틀리는 곳

틀린 생각: 가장 큰 값을 찾을 때도 합 모으기처럼 best를 0에서 시작하면 된다.

합은 아무것도 더하지 않았을 때가 0이라 0에서 시작했습니다. 가장 큰 값은 다릅니다. 값이 모두 0보다 작으면 0이 끝까지 가장 큰 값으로 남습니다.

temps = [-5, -2, -8]
best = 0
for temp in temps:
    if temp > best:
        best = temp
print(best)
실행 결과
0

아침 기온 셋 가운데 가장 높은 값은 -2인데, 리스트에 없는 0이 찍혔습니다.

맞는 규칙: best는 지금까지 본 값 가운데 가장 큰 값이라, 리스트에 없는 0이 아니라 첫 값에서 시작합니다. 그러면 값이 모두 음수여도 맞습니다.

틀린 생각: 첫 값을 최고로 두는 줄은 반복 안에 둬도 된다.

처음에 한 번 정하는 값이라 어디에 두든 같아 보이지만, 덩어리 안의 줄은 바퀴마다 실행됩니다.

prices = [4000, 4500, 3500]
for price in prices:
    best = prices[0]
    if price > best:
        best = price
print(best)
실행 결과
4000

바퀴마다 best를 첫 값 4000에 다시 붙여서, 둘째 바퀴에 찾은 4500을 셋째 바퀴에 잊습니다.

맞는 규칙: 덩어리 안의 줄은 바퀴마다 실행되어, 그 안에서 best를 첫 값에 다시 붙이면 앞에서 찾은 최고를 잊습니다. 1번 하위 목표는 반복 앞에 한 번 둡니다(규칙 4).

확인 문제

1. 1절 풀이 예제의 1번 줄을 prices = [4500, 4000, 3500]⁠으로 바꿨습니다. 무엇이 찍힐까요?

prices = [4500, 4000, 3500]
# 1. 첫 값을 최고로
best = prices[0]
# 2. 하나씩 꺼내 견주어 바꾸기
for price in prices:
    if price > best:
        best = price
# 3. 끝나고 쓰기
print(best)
힌트

바퀴마다 6번 줄 조건의 값을 추적 표에 적어 봅니다.

정답
실행 결과
4500

best가 첫 값 4500에 붙은 뒤, 세 바퀴 모두 6번 줄 조건이 False라 한 번도 바뀌지 않습니다.

흔한 오답은 3500입니다. 마지막에 꺼낸 값이 best에 남는다고 본 것입니다. best는 6번 줄 조건이 True일 때만 바뀝니다.

2. 빈칸을 채워 코드를 완성하세요.

(가) 4000이 찍히도록 한 줄의 빈칸을 채우세요.

prices = [3500, 4000, 2000]
# 1. 첫 값을 최고로
best = prices[0]
# 2. 하나씩 꺼내 견주어 바꾸기
for price in prices:
    if price > best:
        ________
# 3. 끝나고 쓰기
print(best)
힌트

2번 하위 목표 '하나씩 꺼내 견주어 바꾸기'에서 바꾸는 줄입니다.

정답

best = price입니다.

prices = [3500, 4000, 2000]
# 1. 첫 값을 최고로
best = prices[0]
# 2. 하나씩 꺼내 견주어 바꾸기
for price in prices:
    if price > best:
        best = price
# 3. 끝나고 쓰기
print(best)
실행 결과
4000

다르게 써도 되는 곳: 3절의 max()로 best = max(prices)를 써도 4000이 찍힙니다. 빈칸에 best = 4000을 바로 써도 4000이 찍히지만, 리스트의 값을 바꾸면 따라 바뀌지 않습니다.

흔한 오답은 price = best입니다. 이름 price를 best가 붙은 값에 붙일 뿐 best는 그대로라 3500이 찍힙니다. =를 '같다'로 읽어 양쪽을 바꿔 써도 된다고 본 것입니다. =는 왼쪽 이름을 오른쪽 값에 붙입니다(규칙 2).

(나) 날마다 판 잔 수 가운데 가장 많은 값을 찾습니다. 2번 하위 목표를 통째로 채우세요. 다 채운 코드는 15를 찍어야 하고, 1번 줄을 cups = [3, 8, 5]로 바꾸면 8을 찍어야 합니다.

cups = [9, 15, 12]
# 1. 첫 값을 최고로
best = cups[0]
# 2. 하나씩 꺼내 견주어 바꾸기

# 3. 끝나고 쓰기
print(best)
힌트

1절 풀이 예제의 2번 하위 목표와 같은 세 줄입니다. 꺼낸 값의 이름만 정하면 됩니다.

정답
cups = [9, 15, 12]
# 1. 첫 값을 최고로
best = cups[0]
# 2. 하나씩 꺼내 견주어 바꾸기
for n in cups:
    if n > best:
        best = n
# 3. 끝나고 쓰기
print(best)
실행 결과
15

다르게 써도 되는 곳: 꺼낸 값의 이름은 n 말고 cup처럼 지어도 됩니다. 조건을 n >= best로 써도 두 시험 값 모두 같은 값이 찍힙니다.

흔한 오답은 if 줄을 빼고 바퀴마다 best = n으로 붙이는 것입니다. 그러면 마지막 값 12가 찍히고, 둘째 시험 값에서도 8이 아니라 5가 찍힙니다. 견주지 않고 붙이기만 해도 가장 큰 값이 남는다고 본 것입니다.

3. 시험 점수에서 가장 높은 점수와, 가장 높은 점수가 바뀐 횟수를 찍습니다. 무엇이 찍힐까요?

scores = [80, 95, 95, 70]
best = scores[0]
count = 0
for score in scores:
    if score > best:
        best = score
        count = count + 1
print(best, count)
힌트

바퀴마다 5번 줄 조건이 True인지 False인지 추적 표에 적어 봅니다.

정답
실행 결과
95 1

80은 처음 best와 같고, 첫 95에서 한 번 바뀝니다. 둘째 95는 지금의 best와 같아서, 70은 작아서 바뀌지 않습니다.

흔한 오답은 95 3입니다. 같은 값이어도 바꾼다고 본 것입니다(>= 연산자로 읽은 것). > 연산자는 같으면 False입니다.

아래 코드 3번 줄을 best = 0으로, 6번 줄의 > 기호를 < 기호로 바꿔 가장 싼 값을 찾게 하면 무엇이 찍히는지 봅니다.

처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

파이썬 목차로