Preface
이번 장에선 지난 포스팅에 이어 배열을 공부했다.
내용 면에선 크게 어려운 부분이 없었지만, 이를 알고리즘을 통해 실제 코드로 구현하는 실습 과정이 생각보다 복잡했다.
코드를 한 줄 한 줄 읽어보면 분명 이해는 할 수 있지만, 막상 풀이 과정을 보지 않고 혼자 해결하려 하면 어떻게 구현해야 할 것인지 감이 오지 않았다.
다시 말해 개별적인 함수의 사용법은 어느정도 숙지했지만, 이 함수들을 사용하여 문제를 해결할 방법이 잘 떠오르지 않는다.
당분간은 특정 문제가 주어졌을 때 이를 해결하기 위해 어떤 접근 방법을 취해야 할 것인지에 초점을 맞춰 차근차근 코드를 작성하는 연습을 할 계획이다.
소프트웨어 공학에서 공부했던 것처럼 추상화 단계를 점차 낮추며 코드를 작성하자!
1. 배열이란?
- 스캔(주사, 트래버스) : 배열 원소를 하나씩 차례로 주목하여 살펴보는 방식
- 배열의 최댓값을 구하는 코드
def max_of(a):
maximum = a[0]
for i in range(1, len(a)):
if a[i] > maximum:
maximum = a[i]
return maximum
if __name__ == '__main__':
print('배열의 최댓값을 구합니다.')
num = int(input('원소 수를 입력하세요: '))
x = [None] * num # 원소 수가 num 인 리스트를 생성
for i in range(num):
x[i] = int(input(f'x[{i}]값을 입력하세요: '))
print(x)
print(f'최댓값은 {max_of(x)}입니다.')
- Any : 제약이 없는 임의의 자료형
- Sequence(시퀀스형) : 데이터를 순서대로 하나씩 나열하여 나타낸 데이터 구조
→ 리스트형, 바이트 배열형, 문자열형, 튜플형, 바이트열형 등
- 어노테이션(annotation, 주석 달기) : 강제성이 없으며, 코드에 영향을 주지 않음
from typing import Any, Sequence
def max_of(a: Sequence) -> Any:
- 모듈 : 하나의 스크립트 프로그램
1) 확장자를 포함하지 않는 파일의 이름 자체를 모듈 이름으로 한다.
2) 스크립트 프로그램이 직접 실행될 때 변수 __ name__은 '__main__'이다.
3) 스크립트 프로그램이 임포트 될 때 변수 _ name__은 원래의 모듈 이름이다.
- 리터럴(고정된 값)이 아니면 원소 값이 같아도 실체는 다르다.
list1 = [1, 2, 3, 4]
list2 = list1[:]
list2[1] = 8
print(list1)
print(list2)
- enmerate( ) 함수 사용
x = ['a', 'b', 'c']
for i, name in enumerate(x, 1):
print(f'x[{i}] = {name}')
# 몇 번째부터 시작할 지 정할 수 있음
- 이터레이터(iterator)는 데이터의 나열을 표현하는 객체이다.
it = iter(range(3))
print(next(it))
print(next(it))
print(next(it))
# iter() 는 그 객체에 대한 이터레이터(반복자)를 반환한다.
# next() 함수에 이터레이터를 전달하면 원소를 순차적으로 꺼낸다.
# 꺼낼 원소가 더 이상 없을 땐 StopIteration 으로 예외를 발생시킨다.
- 의사 코드(pseudo code) : 컴퓨터에서 바로 실행할 순 없지만, 알고리즘을 간단하고 분명하게 나타내는 코드
- 0~9까지의 숫자 10개와 A~Z까지의 알파벳 26개를 사용하여 36진수까지 표현할 수 있다.
- 기수와 서수
1) 기수 : 수를 나타내는 데 기초가 되는 수
→ 0, 1, 2, 3...
2) 서수 : 사물의 순서를 나타내는 수
→ 첫째, 둘째, 셋째...
- 진수의 종류
1) 10진수(decimal) : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9의 숫자를 사용
2) 8진수(octal) : 0, 1, 2, 3, 4, 5, 6, 7의 숫자를 사용
3) 16진수(hexadecimal) : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F의 숫자를 사용
- 10진수를 2~36진수로 변환하는 코드
# 10진수 값을 입력받아 2~36진수로 변환하여 출력
def card_conv(x: int, r: int) -> str:
d = ''
dchar = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
while x > 0:
d += dchar[x % r]
x //= r
return d[::-1]
if __name__ == '__main__':
print('10진수를 n진수로 변환합니다.')
while True:
while True:
no = int(input('변환할 값으로 음이 아닌 정수를 입력하세요.: '))
if no > 0:
break
while True:
cd = int(input('어떤 진수로 변환할까요?: '))
if cd <= 2 <= 36:
break
print(f'{cd}진수로는 {card_conv(no, cd)}입니다.')
retry = input('한 번 더 변환할까요?(Y: 예 / N: 아니요): ')
if retry in {'N', 'n'}:
break
- 1000이하의 소수를 나열하는 코드
counter = 0
ptr = 0
prime = [None] * 500
prime[ptr] = 2
ptr += 1
for n in range(3, 1001, 2):
for i in range(1, ptr):
counter += 1
if n % prime[i] == 0:
break
else:
prime[ptr] = n
ptr += 1
for i in range(ptr):
print(prime[i])
print(f'나눗셈을 실행한 횟수: {counter}')
- 복사
1) 얕은 복사 : 리스트 안의 모든 원소가 참조하는 곳까지 복사
2) 깊은 복사 : 구성 원소 수준으로 복사
import copy
x = [[1, 2, 3], [4, 5, 6]]
y = x.copy() # 얕은 복사
x[0][1] = 9
print(x)
print(y)
a = [[1, 2, 3], [4, 5, 6]]
b = copy.deepcopy(a) # 깊은 복사
a[0][1] = 9
print(a)
print(b)