unit 19. 계단식으로 별 출력하기
-
중첩 루프 사용하기
반복문 안에 반복문이 들어가는 형태를 중첩 루프(다중 루프)라고 한다.
중첩 루프의 형식은 보통 다음과 같다.
for i in range(5): # 5번 반복. 바깥쪽 루프는 세로 방향
for j in range(5): # 5번 반복. 안쪽 루프는 가로 방향
print('j:', j, sep='', end=' ') # j값 출력. end에 ' '를 지정하여 줄바꿈 대신 한 칸 띄움
print('i:', i, '\\n', sep='') # i값 출력, 개행 문자 모양도 출력
# 가로 방향으로 숫자를 모두 출력한 뒤 다음 줄로 넘어감
# (print는 기본적으로 출력 후 다음 줄로 넘어감)
위 소스코드의 실행 결과는 다음과 같다.
j:0 j:1 j:2 j:3 j:4 i:0\n
j:0 j:1 j:2 j:3 j:4 i:1\n
j:0 j:1 j:2 j:3 j:4 i:2\n
j:0 j:1 j:2 j:3 j:4 i:3\n
j:0 j:1 j:2 j:3 j:4 i:4\n
즉, i를 사용하는 바깥쪽 루프는 세로 방향을 처리하고, j를 사용하는 안쪽 루프는 가로 방향을 처리한다.
sep : print 내에 , 에 대한 표시 형식을 지정하는 것이다.
end : 줄바꿈 대신 한 칸 뛰우는 것이다.
-
사각형으로 별 출력하기
이번엔 중첩된 반복문을 사용하여 5×5 사각형 형태로 별을 그려보겠다.
for i in range(5): # 5번 반복. 바깥쪽 루프는 세로 방향
for j in range(5): # 5번 반복. 안쪽 루프는 가로 방향
print('*', end='') # 별 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
print() # 가로 방향으로 별을 다 그린 뒤 다음 줄로 넘어감
# (print는 출력 후 기본적으로 다음 줄로 넘어감)
실행 결과는 다음과 같다.
*****
*****
*****
*****
*****
먼저 안쪽의 for j in range(5): 반복문에서 print로 별을 그리면 다음과 같이 가로 방향으로 별이 나열되는데, 이를 바깥의 for i in range(5) 반복문을 통해 5개씩 5줄로 쌓아 나간다.
이는 print에 end=''를 지정했을 때 줄바꿈이 되지 않고 오른쪽 방향으로 문자가 계속 붙는 특성을 이용한 것이다.
* 사각형 모양 바꾸기
for i in range(3): # 3번 반복. 세로 방향
for j in range(7): # 7번 반복. 가로 방향
print('*', end='') # 별 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
print() # 가로 방향으로 별을 다 그린 뒤 다음 줄로 넘어감
# (print는 출력 후 기본적으로 다음 줄로 넘어감)
이번엔 for 반복문의 조건식을 수정하여 사각형의 모양을 바꿔보겠다. 실행결과는 다음과 같다.
*******
*******
*******
안쪽 반복문은 7번 반복하고, 바깥쪽 반복문은 3번 반복한다. 즉, 7×3 크기의 사각형을 그린다.
-
계단식으로 별 출력하기
다음과 같이 계단식으로 별이 하나씩 증가하게 출력하려면 어떻게 해야 할까?
*
**
***
****
*****
첫 번째 줄에는 별이 한 개, 두 번째 줄에는 별이 두 개, 세 번째 줄에는 별이 세 개, 네 번째 줄에는 별이 네 개, 다섯 번째 줄에는 별이 다섯 개이다.
즉, 별의 개수는 세로 방향인 줄의 위치에 비례하므로 조건식도 세로 방향 변수 i에 맞추어 작성해야 한다.
if j <= i: # 세로 방향 변수 i만큼
print('*', end='') # 별 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
이렇게 if 조건문을 if j <= i:와 같이 작성하여 가로 방향(j)으로 별을 출력할 때는 세로 방향(i)의 변수만큼 출력하도록 만들면된다.
최종 소스코드는 다음과 같다.
for i in range(5): # 0부터 4까지 5번 반복. 세로 방향
for j in range(5): # 0부터 4까지 5번 반복. 가로 방향
if j <= i: # 세로 방향 변수 i만큼
print('*', end='') # 별 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
print() # 가로 방향으로 별을 다 그린 뒤 다음 줄로 넘어감
# (print는 출력 후 기본적으로 다음 줄로 넘어감)
* 대각선으로 별 출력하기
이번에는 출력 부분을 수정하여 별을 대각선으로 그려보겠다.
다음과 같이 가로 방향과 세로 방향의 변수 값이 같을 때 별을 출력하고, 같지 않을 때는 공백을 출력을 출력하면 된다.
for i in range(5): # 0부터 4까지 5번 반복. 세로 방향
for j in range(5): # 0부터 4까지 5번 반복. 가로 방향
if j == i: # 세로 방향 변수와 같을 때
print('*', end='') # 별 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
else: # 세로 방향 변수와 다를 때
print(' ', end='') # 공백 출력. end에 ''를 지정하여 줄바꿈을 하지 않음
print() # 가로 방향으로 별을 다 그린 뒤 다음 줄로 넘어감
# (print는 출력 후 기본적으로 다음 줄로 넘어감)
실행 결과는 다음과 같다.
*
*
*
*
*
실행 하면 별이 왼쪽 위에서 오른쪽 아래 방향인 대각선 모양으로 그려진다.
unit 20. FizeBuzz 문제
-
1부터 100까지 숫자 숫자 출력하기
FizzBuzz 문제는 다음과 같은 규칙을 갖는다.
- 1에서 100까지 출력
- 3의 배수는 Fizz 출력
- 5의 배수는 Buzz 출력
- 3과 5의 공배수는 FizzBuzz 출력
즉, 간단하게 1부터 100까지 숫자를 출력하면서 3의 배수는 숫자 대신 'Fizz', 5의 배수는 숫자 대신 'Buzz', 3과 5의 공배수는 숫자 대신 'FizzBuzz'를 출력하면 된다.
* 1부터 100까지 숫자 출력하기
for i in range(1, 101): # 1부터 100까지 100번 반복
print(i)
for와 range로 1부터 100까지 100번 반복하면서 print로 변수의 값을 출력하면 된다.
-
3의 배수일때와 5의 배수일때 처리하기
이제 3의 배수와 5의 배수일 때 숫자 대신 'Fizz', 'Buzz'를 출력해보겠다.
for i in range(1, 101): # 1부터 100까지 100번 반복
if i % 3 == 0: # 3의 배수일 때
print('Fizz') # Fizz 출력
elif i % 5 == 0: # 5의 배수일 때
print('Buzz') # Buzz 출력
else:
print(i) # 아무것도 해당되지 않을 때 숫자 출력
실행 결과는 다음과 같다.
1
2
Fizz
... (생략)
97
98
Fizz
Buzz
for 반복문에서 i를 3으로 나눴을 때 나머지가 0이면 3의 배수, 5로 나눴을 때 나머지가 0이면 5의 배수이다.
따라서 if로 3의 배수일 때 'Fizz'를 출력해주고, elif로 5의 배수일 때 'Buzz'를 출력한다.
-
3과 5의 공배수 처리하기
3과 5의 공배수는 다음과 같이 논리 연산자 and를 사용하면 된다.
for i in range(1, 101): # 1부터 100까지 100번 반복
if i % 3 == 0 and i % 5 == 0: # 3과 5의 공배수일 때
print('FizzBuzz') # FizzBuzz 출력
elif i % 3 == 0: # 3의 배수일 때
print('Fizz') # Fizz 출력
elif i % 5 == 0: # 5의 배수일 때
print('Buzz') # Buzz 출력
else:
print(i) # 아무것도 해당되지 않을 때 숫자 출력
실행 결과는 다음과 같다.
1
2
Fizz
... (생략)
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
i % 3 == 0 and i % 5 == 0처럼 i를 3으로 나눴을 때 나머지가 0이면서 5로 나눴을 때도 나머지가 0이면 3과 5의 공배수이다. 그러므로 이때는 print로 'FizzBuzz'를 출력해준다.
※ 참고 : 3과 5의 공배수를 먼저 검사한 뒤 elif로 3의 배수, 5의 배수를 검사해야 한다.
만약 i가 30인데 if에서 3의 배수를 먼저 검사하면 3과 5의 공배수는 검사를 하지 않고 그냥 넘어가버리므로 주의해야 한다.
-
논리연산자를 사용하지 않고 3과 5의 공배수 처리하기
논리 연산자 and를 사용하지 않고 3과 5의 공배수를 검사하려면 어떻게 해야 할까?
3 * 5 = 15는 3과 5의 최소공배수이므로 15의 배수일 때 FizzBuzz를 출력하면 될 것이다.
for i in range(1, 101): # 1부터 100까지 100번 반복
if i % 15 == 0: # 15의 배수(3과 5의 공배수)일 때
print('FizzBuzz') # FizzBuzz 출력
elif i % 3 == 0: # 3의 배수일 때
print('Fizz') # Fizz 출력
elif i % 5 == 0: # 5의 배수일 때
print('Buzz') # Buzz 출력
else:
print(i) # 아무것도 해당되지 않을 때 숫자 출력
-
코드 단축하기
다음은 코드를 매우 단축시킨 FizzBuzz 문제 코드이다.
for i in range(1, 101):
print('Fizz' * (i % 3 == 0) + 'Buzz' * (i % 5 == 0) or i)
# 문자열 곱셈과 덧셈을 이용하여 print 안에서 처리
우선 다음은 문자열에 True를 곱하면 문자열이 그대로 나오고, False를 곱하면 문자열이 출력되지 않는 점을 이용했다. (True는 1, False는 0으로 연산).
'Fizz' * (i % 3 == 0)
즉, i가 3의 배수이면 i % 3 == 0은 True이므로 'Fizz'가 출력되고, 3의 배수가 아니면 False이므로 'Fizz'가 출력되지 않는다.
마찬가지로 'Buzz'도 문자열 곱셈을 이용하여 5의 배수일 때 출력한다.
'Fizz' * (i % 3 == 0) + 'Buzz' * (i % 5 == 0)
3과 5의 공배수일 때는 'FizzBuzz'를 출력해야 하는데 이때는 문자열 덧셈을 이용한다. 즉, 3과 5의 공배수이면 'Fizz' * True + 'Buzz' * True가 되므로 'Fizz' + 'Buzz'로 'FizzBuzz'를 출력한다.
print('Fizz' * (i % 3 == 0) + 'Buzz' * (i % 5 == 0) or i)
3 또는 5의 배수가 아닐 때는 'Fizz' * False + 'Buzz' * False가 되고 결과는 빈 문자열 ''이 되는데, 이때는 or 연산자를 사용한다. 즉, 3 또는 5의 배수가 아닐 때 or로 연산하면 i만 남게 되어 숫자가 그대로 출력된다.
* 참고 : 코드의 문자 수를 얼마나 줄일 수 있는냐보다도 코드를 읽을 때 가독성이 중요하다. 따라서 위와 같은 코드 단축하기는 주의할 필요가 있다.
unit 21. 터틀 그래픽스로 그림 그리기
-
사각형 그리기
터틀 그래픽스(Turtle graphics) 모듈은 그림을 그리는 모듈이다.
IDLE을 실행하고 파이썬 셸에서 다음과 같이 입력하면 된다.
>>> import turtle as t
>>> t.shape('turtle')
t.shape('turtle')까지 입력하면 파이썬 터틀 그래픽스(Python Turtle Graphics) 창이 표시되고 오른쪽을 바라보는 거북이가 나온다.
터틀 모듈의 대표적 기능은 다음과 같다.
- 앞으로 이동: forward, fd
- 뒤로 이동: backward, bk, back
- 왼쪽으로 회전: left, lt
- 오른쪽으로 회전: right, rt
따라서 사각형을 그려주려면 다음과 같이 앞으로 이동하는 forward와 오른쪽으로 회전하는 right을 번갈아 반복하면 된다.
t.fd(100)
t.rt(90)
t.fd(100)
t.rt(90)
t.fd(100)
t.rt(90)
t.fd(100)
사각형이 될때까지 오른쪽으로 90도 바꾸기, 앞으로 100픽셀 이동을 반복해주면 다음과 같은 모양을 얻을 수 있다.
-
다각형 그리기
* 반복문을 사용해서 사각형 그리기
import turtle as t
t.shape('turtle')
for i in range(4): # 사각형이므로 4번 반복
t.forward(100)
t.right(90)
forward와 right를 반복문을 이용해 4번 반복하면 사각형이 그려진다.
* 오각형 그리기
import turtle as t
t.shape('turtle')
for i in range(5): # 오각형이므로 5번 반복
t.forward(100)
t.right(360 / 5) # 360을 5로 나누어서 외각을 구함
오각형이므로 forward와 right을 5번 반복해주면 된다.
이때 right의 각도를 잘 생각해주어야 하는데, 오각형은 360을 5로 나누었을 때 각만큼 이동해야 할 것이다.
* 다각형 그리기
import turtle as t
n = int(input()) # 사용자의 입력을 받음
t.shape('turtle')
for i in range(n): # n번 반복
t.forward(100)
t.right(360 / n) # 360을 n으로 나누어서 외각을 구함
소스코드를 일반화해서 n각형을 그리고 싶을 땐, 먼저 n에 대한 입력을 받는다.
그리고 n번 만큼 forward와 right를 반복하는데, 이때 right의 각도는 360 / n이어야 할 것이다.
* 다각형 색칠하기
import turtle as t
n = 6 # 육각형
t.shape('turtle')
t.color('red') # 펜의 색을 빨간색으로 설정
t.begin_fill() # 색칠할 영역 시작
for i in range(n): # n번 반복
t.forward(100)
t.right(360 / n) # 360을 n으로 나누어서 외각을 구함
t.end_fill() # 색칠할 영역 끝
먼저 color는 펜의 색을 설정한다. 그리고 도형을 그리기 전에 t.begin_fill()와 t.end_fill로 어디서부터 어디까지 그릴 것인지를 정해줘야 하는데, 사이에 for 반복문을 넣으므로써 육각형에 빨강을 색칠하게 된다.
※ RGB 색상
#으로 시작하며 빨강(R), 초록(G), 파랑(B)에 해당하는 두 자리 16진수 세 쌍으로 구성되어 있다.
즉, 색상의 범위는 00부터 FF까지 사용할 수 있으며 빨강, 초록, 파랑을 조합해서 색상을 만든다.
t.color('#FF69B4') # 핫핑크(hotpink)
-
복잡한 도형 그리기
원을 그릴 때는 circle을 사용한다.
>>> import turtle as t
>>> t.shape('turtle')
>>> t.circle(120)
t.circle에 120을 지정하면 반지름이 120인 원을 그린다.
* 원을 반복해서 그리기
import turtle as t
n = 60 # 원을 60번 그림
t.shape('turtle')
t.speed('fastest') # 거북이 속도를 가장 빠르게 설정
for i in range(n):
t.circle(120) # 반지름이 120인 원을 그림
t.right(360 / n) # 오른쪽으로 6도 회전
소스 코드를 실행해보면 그물망 모양이 나온다.
360 / 60을 계산하면 6인데 오른쪽으로 6도씩 회전하면서 원을 그리면 이렇게 원이 겹쳐서 나온다.
* 선으로 복잡한 무늬 그리기
import turtle as t
t.shape('turtle')
t.speed('fastest') # 거북이 속도를 가장 빠르게 설정
for i in range(300): # 300번 반복
t.forward(i) # i만큼 앞으로 이동. 반복할 때마다 선이 길어짐
t.right(91) # 오른쪽으로 91도 회전
소스 코드를 실행해보면 복잡한 무늬가 그려진다.
먼저 for로 i가 0부터 299까지 반복하는데 forward로 i만큼 앞으로 이동하도록 만들었다. 즉, 반복할 때마다 선이 길어지며 right로 91도 회전한다. 이렇게 하면 미세하게 틀어진 사각형이 그려지게 된다.
'Programming Languages > Python' 카테고리의 다른 글
[P4C] 파이썬 코딩 도장 : 문제 풀이2 (0) | 2021.01.27 |
---|---|
[P4C] 파이썬 코딩 도장 : UNIT 22 ~ UNIT 24 (0) | 2021.01.26 |
[P4C] 파이썬 코딩 도장 : UNIT 16 ~ UNIT 18 (0) | 2021.01.23 |
[P4C] 파이썬 코딩 도장 : UNIT 13 ~ UNIT 15 (0) | 2021.01.22 |
[P4C] 파이썬 코딩 도장 : UNIT 8 ~ UNIT 12 (0) | 2021.01.21 |