my_list = [2, 3,5 ,7 ,11]
for number in my_list: # number는 아무거나 바꿀 수 있음
print(number)
2
3
5
7
11
간편함 , 깔끔함, 메모리 효율성
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 여러 리스트 값을 적어야 하는 불편함 존재
print(i)
# start부터 stop-1까지의 범위
for i in range(start, stop):
print(i)
# 예시
for i in range(3, 11): # 3 ~ 10까지의 범위를 뜻함
print(i)
3
4
5
6
7
8
9
10
# 0부터 stop-1까지의 범위
for i in range(stop):
print(i)
# 예시
for i in range(10): # 0 ~ 9까지의 범위를 뜻함
print(i)
0
1
2
3
4
5
6
7
8
9
# start부터 stop-1까지의 범위, 간격 step
for i in range(start, stop, step):
print(i)
# 예시
for i in range(3, 17, 3): # 3 ~ 16까지의 범위, 간격은 3
print(i)
3
6
9
12
15
numbers
라는 리스트가 주어졌습니다.for
문과 range
함수를 사용하여, numbers
의 인덱스와 원소를 출력해 보세요. numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
# 인덱스와 원소 출력
# 코드를 입력하세요.
0 2
1 3
2 5
3 7
4 11
5 13
6 17
7 19
8 23
9 29
10 31
numbers
의 인덱스만 모두 출력하는 코드를 공개하겠습니다.for i in range(len(numbers)):
print(i)
인덱스와 원소를 함께 출력하려면 어떻게 해야 할까요?numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
# 인덱스와 원소 출력
for i in range(len(numbers)):
print(i, numbers[i])
거기서 나온 '피타고라스 삼조'라는 개념이 있는데요. 피타고라스 삼조란, 피타고라스 정리(a^2 + b^2 = c^2a2+b2=c2 )를 만족하는 세 자연수 쌍 (a, b, c)(a,b,c)입니다.
예를 들어, 3^2 + 4^2 = 5^232+42=52이기 때문에 (3, 4, 5)(3,4,5)는 피타고라스 삼조입니다.
**a < b < c*a*<*b*<*c***
라고 가정할 때, **a+b+c=400 *a*+*b*+*c***=400
을 만족하는 피타고라스 삼조 (a, b, c)(a,b,c)는 단 하나인데요. 이 경우, a b ca∗b∗c는 얼마인가요?
2040000
가장 단순하게 코드를 짜면 이렇습니다.
for a in range(1, 400):
for b in range(1, 400):
for c in range(1, 400):
if a * a + b * b == c * c and a < b < c and a + b + c == 400:
print(a * b * c)
이 코드를 막상 실행해 보면, 꽤 오랜 시간이 걸릴 것입니다. 논리적으로 봤을 때 언젠가는 올바른 정답을 찾아 주는 코드입니다. 하지만 400 대신 더 큰 숫자가 들어갈 수도 있는 걸 감안하면, 너무 오래 걸려서 사실상 사용할 수 없다고 보시면 되는데요. 이런 걸 "비효율적인 알고리즘"이라고 합니다.
알고리즘이 비효율적인 이유를 간단히만 설명드리겠습니다.
a
가 가능한 경우는 1
부터 399
까지, b
가 가능한 경우는 1
부터 399
까지, c
가 가능한 경우는 1
부터 399
까지인데요. 그러면,
if a * a + b * b == c * c and a < b < c and a + b + c == 400:
print(a * b * c)
위 코드가 총 63,521,199번 실행됩니다. 6천만 번 이상 실행되는 거죠.
for a in range(1, 400):
for b in range(1, 400):
c = 400 - a - b
if a * a + b * b == c * c and a < b < c:
print(a * b * c)
이렇게 하면 정답인 2040000
를 구할 수 있습니다.리스트 원소들의 순서를 거꾸로 뒤집으려고 합니다.
numbers
라는 리스트가 주어졌을 때, for
문을 사용하여 리스트를 거꾸로 뒤집어 보세요!
numbers = [2, 3, 5, 7, 11, 13, 17, 19]
# 리스트 뒤집기# 코드를 입력하세요.print("뒤집어진 리스트: " + str(numbers))
뒤집어진 리스트: [19, 17, 13, 11, 7, 5, 3, 2]
인덱스 0
과 대칭되는 위치는 인덱스 len(numbers) - 1
입니다.
인덱스 1
과 대칭되는 위치는 인덱스 len(numbers) - 2
입니다.
인덱스 2
와 대칭되는 위치는 인덱스 len(numbers) - 3
입니다.
대칭되는 두 인덱스를 left
와 right
라고 합시다.
right = len(numbers) - left - 1
로 관계를 표현할 수 있습니다.
반복문을 돌면서 left
요소와 right
요소의 위치를 바꿔 줘야 합니다.
그러기 위해서는 이렇게 할 수 있는데요.
numbers = [2, 3, 5, 7, 11, 13, 17, 19]
# 리스트 뒤집기for left in range(len(numbers)):
# 인덱스 left와 대칭인 인덱스 right 계산
right = len(numbers) - left - 1
# 위치 바꾸기
temp = numbers[left]
numbers[left] = numbers[right]
numbers[right] = temp
print("뒤집어진 리스트: " + str(numbers))
뒤집어진 리스트: [2, 3, 5, 7, 11, 13, 17, 19]
이렇게 하면 리스트가 뒤집히지 않은 상태로 출력됩니다. 왜 그런 걸까요?
우리는 for
문을 left
가 0
일 때부터 left
가 len(numbers) - 1
일 때까지 반복하는데요. 사실 left
가 그렇게 끝까지 돌 필요가 없습니다. 그냥 리스트 길이의 반만 돌아도 리스트를 뒤집을 수 있기 때문이죠!
오히려 리스트 길이의 반을 넘게 돌면, 잘 바꿔 놨던 위치를 다시 원상 복구하는 셈입니다. 이미 바뀐 위치에 다시 위치 바꾸기 코드를 적용하게 되니까요. 그래서 리스트 길이의 반만 돌 수 있도록 아래와 같이 작성해주셔야 합니다.
numbers = [2, 3, 5, 7, 11, 13, 17, 19]
# 리스트 뒤집기for left in range(len(numbers) // 2):
# 인덱스 left와 대칭인 인덱스 right 계산
right = len(numbers) - left - 1
# 위치 바꾸기
temp = numbers[left]
numbers[left] = numbers[right]
numbers[right] = temp
print("뒤집어진 리스트: " + str(numbers))
위치 바꾸기를 쉽게 할 수 있는 방법도 알아보겠습니다. 피보나치 수열
과제에서 언급한 방법 기억나시나요? 강의에서 배우지는 않지만, 튜플(tuple)
이라는 자료형을 이용해서 할당하는 겁니다. 튜플은 아래와 같이 표현합니다.
korean_names = ('효선', '유신')
english_names = 'hyoseon', 'yusin'
print(type(korean_names))
print(type(english_names))
<class 'tuple'>
<class 'tuple'>
위처럼 괄호를 통해 표현할 수도 있지만 ,
로만 각 요소를 구분해도 튜플로 인식이 됩니다.
그럼 어떻게 위치를 쉽게 바꿀 수 있는지 코드를 보겠습니다.
numbers = [2, 3, 5, 7, 11, 13, 17, 19]
# 리스트 뒤집기for left in range(len(numbers) // 2):
# 인덱스 left와 대칭인 인덱스 right 계산
right = len(numbers) - left - 1
# 위치 바꾸기
numbers[right], numbers[left] = numbers[left], numbers[right]
print("뒤집어진 리스트: " + str(numbers))
위와 같이 쓰게 되면 지정 연산자(=) 의 오른쪽에 있는 튜플이 위치가 바뀌기 전의 numbers[left]
, numbers[right]
의 값을 보관하게 됩니다. 그리고 numbers[right]
, numbers[left]
에 해당하는 요소에 값을 각각 할당하게 되면서 이전 코드처럼 임시 변수를 만들지 않고도 값을 교환할 수 있는 것입니다.
어느 접근법을 이용하여 해결하셔도 좋습니다. 두번째 접근법은 파이썬스러운(Pythonic) 방법으로 다른 코드에서 보실 수도 있으니 참고로 알아두세요!
(값1, 값2, 값3...)
위처럼 괄호와 comma 를 이용해 표기하게 되어요. 그런데 이 괄호를 쓰지 않고값1, 값2
와 같이 쓰더라도 튜플로 인식을 하게 됩니다. 즉 아래와 같습니다.numbers1 = (1, 2)
print(type(numbers1)) # <class 'tuple'>
numbers2 = 1, 2
print(type(numbers2)) # <class 'tuple'>
그럼 =
을 기준으로 우측의 numbers[left]
, numbers[right]
가 튜플이 된다는 것은 위로써 설명이 될 것입니다. 그리고 또 설명해야 할 것은 unpacking 입니다.numbers = [1, 2, 3]
a, b, c, = numbers
print(a, b, c) # 1, 2, 3
위 코드를 보시게 되면 numbers 의 각 요소들이 하나씩 a, b, c 에 할당되게 되는데 이런걸 unpacking 이라고 부릅니다. 마찬가지로 numbers[right], numbers[left] = numbers[left], numbers[right]
도 unpacking 과 같습니다. numbers[right]
에 numbers[left]
를 할당하고 numbers[left]
에 numbers[right]
를 할당하는 Unpacking 을 진행하는 것이에요. 이렇게 unpacking 을 하게 되면 결국 자리바꿈을 한 것과 동일한 결과가 나오는 것입니다.