출처: do it 자료구조와 함께 배우는 알고리즘 입문
## 뮤터블과 이뮤터블의 대입
n = 5
print(id(n))
n = 'ABC'
print(id(n)) #변수에 어떤값을 대입하면 값이 아니라 식별번호가 바뀐다
133477962137968
133477960949168
n = 12
print(id(n))
n += 1 #int형 객체가 12에서 13으로 업데이트함
print(id(n))
133477962138192
133477962138224
변경할 수 있는 자료형(mutable) - 리스트, 딕셔너리, 집합
변경할 수 없는 자료형(immutable) - 수, 문자열, 튜플
내포 표기 생성
리스트 numbers의 홀수 원소값을 *2 한 리스트 생성
numbers = [1,2,3,4,5]
twise = [num *2 for num in numbers if num % 2 ==1]
print(twise)
[2, 6, 10]
배열 원소의 최댓값 구하기
def max_of(a):
maximum =a[0]
for i in range(1, len(a)):
if a[i]> maximum:
maximum = a[i]
배열 원소의 최댓값을 구하는 함수 구현하기
from typing import Any, Sequence
def max_of(a: Sequence)->Any: #a의 자료형은 sequence, 반환하는것은 임의의 자료형 any
#시퀀스 a형 원소의 최댓값을 반환
maximum =a[0]
for i in range(1, len(a)):
if a[i]> maximum:
maximum = a[i]
return maximum
if __name__ =='__main__':#name과 main이 같은지 확인
print('배열의 최댓값을 구합니다')
num = int(input('원소 수를 입력하세요.: '))
x = [None] * num #원소 수가 num인 리스트 생성
for i in range(num):
x[i] = int(input(f'x[{i}]값을 입력하세요.:'))
print(f'최댓값은 {max_of(x)} 입니다.')
배열의 최댓값을 구합니다
원소 수를 입력하세요.: 5
x[0]값을 입력하세요.:172
x[1]값을 입력하세요.:153
x[2]값을 입력하세요.:192
x[3]값을 입력하세요.:140
x[4]값을 입력하세요.:165
최댓값은 192 입니다.
Any는 제약이 없는 임의의 자료형,Sequence는 시퀀스형이다
시퀀스형에는 list str tuple bytes bytearry형이 있다
max_of() 함수의 특성:
- 함수 안에서는 배열 a의 원솟값을 변경하지 않음
- 호출하는 쪽이 넘겨주는 실제 인수의 자료형은 뮤터블, 이뮤텨블 이든 시퀀스 자료형이면 상관없다
- 인수의 원소를 비교 연산자 > 로 값을 비교할 수 있다면 다른형(int,float)이 섞여 있어도 된다
- 최댓값의 원소가 int형이면 int, float이면 float을 반환함.
스크립트가 임포트 될 때 __name__은 원래의 모듈 이름이다.
if문은 max.py를 직접시작한경우에만 참이 되어 실행할 수 있다. 만약 다른 스크림트에서 임포트한 경우에는 if문이 실행되지 않음
모듈 테스트 하기
from max import max_of
print('배열의 최댓값을 구합니다')
print('주의: "End"를 입력하면 종료합니다')
number = 0
x =[]#빈 리스트
while True:
s = input(f'x[{number}]값을 입력하세요.:')
if s == 'End':
break
x.append(int(s))#배열의 맨 끝에 추가
number += 1
print(f'{number}개를 입력했습니다')
print(f'최댓값은 {max_of(x)}입니다')
배열의 최댓값을 구합니다
주의: "End"를 입력하면 종료합니다
x[0]값을 입력하세요.:125
x[1]값을 입력하세요.:34
x[2]값을 입력하세요.:65
x[3]값을 입력하세요.:23
x[4]값을 입력하세요.:1
x[5]값을 입력하세요.:2
x[6]값을 입력하세요.:3
x[7]값을 입력하세요.:End
7개를 입력했습니다
최댓값은 125입니다
변수 number은 0으로 초기화한 뒤 정수를 입력받을 때마다 1씩 증가, 입력받은 정수의 개수는 배열x의 원소 수와 일치
배열의 원솟값을 난수로 설정하기
import random
from max import max_of
print('난수의 최댓값을 구합니다')
num = int(input('난수의 개수를 입력하세요: '))
lo = int(input('난수의 개수를 입력하세요: '))
hi = int(input('난수의 개수를 입력하세요: '))
x= [None] *num #원소수가 num인 리스트 생성
for i in range(num):
x[i] = random.randint(lo,hi) #lo이상 hi 이하인 정수 난수를 반환
print(f'{(x)}')
print(f'이 가운데 최댓값은 {max_of(x)} 입니다.')
배열 원소를 역순으로 정렬하기
교환횟수 원소수 //2
from typing import Any, MutableSequence
def reverse_array(a: MutableSequence) -> None:
#뮤터블 시퀀스 a의 원소를 역순으로 정렬
n = len(a)
for i in range(n//2):
a[i] ,a[n-i-1] = a[n-i-1],a[i]
if __name__ == '__main__':
print('배열 원소를 역순으로 정렬합니다')
nx = int(input("원소수를 입력하세요: "))
x = [None] *nx #원소수가 nx인 리스트를 생성
for i in range(nx):
x[i] = int(input(f'x[{i}]값을 입력하세요.: '))
reverse_array(x) #x를 역순으로 정렬
print('배열을 역순으로 정렬했습니다.')
for i in range(nx):
print(f'x[{i}]= {x[i]}')
배열 원소를 역순으로 정렬합니다
원소수를 입력하세요: 7
x[0]값을 입력하세요.: 2
x[1]값을 입력하세요.: 5
x[2]값을 입력하세요.: 1
x[3]값을 입력하세요.: 3
x[4]값을 입력하세요.: 9
x[5]값을 입력하세요.: 6
x[6]값을 입력하세요.: 7
배열을 역순으로 정렬했습니다. x[0]= 7
x[1]= 6
x[2]= 9
x[3]= 3
x[4]= 1
x[5]= 5
x[6]= 2
n진수 구하기
10진수 정숫값을 입력받아 2~36진수로 변환하여 출력하기
def card_cov(x:int,r:int)-> str:
#정숫값 x를 r진수로 변환한 뒤 그 수를 나타내는 문자열을 반환
d = '' # 변환 후의 문자열, d를 빈 문자열로 초기화
dchar = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
while x>0:
d += dchar[x % r] #해당하는 문자를 꺼내 결합, x를 r로 나눈 나머지를 인덱스로 하는 문자,x가 0이 될때까지 반환
x //=r #x를 r로 나눈 몫을 다시 x에 할당, 0이 될때 종료
return d[::-1]# 역순으로 변환
card_cov(59,16)
3B
59를 16으로 나눴을 때 몫이 3, 나머지가 11이다. 인덱스 11번째에 해당하는 문자 B를 가져오고, 몫이 3인 값을 16으로 나눠주면 나머지가 3이다. 인덱스 3에 해당하는 숫자3을 가져오면 'B3"이 되고, 이를 역순으로 반환하면 '3B'가 된다
함수 사이에 인수 주고받기
def sum_1ton(n):
#1부터 n까지 정수의 합
s = 0
while n >0:
s += n
n -=1
return s
x = int(input('x의 값을 입력하세요.: '))
print(f'1부터 {x}까지 정수의 합은 {sum_1ton(x)} 입니다')
x의 값을 입력하세요.: 5
1부터 5까지 정수의 합은 15 입니다
리스트에서 임의의 원소값 업데이트하기
def change(lst,idx,val):
#lst[idx]의 값을 val로 업데이트
lst[idx] = val
x= [11,22,33,44,55]
print('x = ',x)
index = int(input('업데이트할 인덱스를 선택하세요.: '))
value = int(input('새로운 값을 입력하세요.: '))
change(x,index,value)
print(f'x = {x}')
x = [11, 22, 33, 44, 55]
업데이트할 인덱스를 선택하세요.: 2
새로운 값을 입력하세요.: 99
x = [11, 22, 99, 44, 55]
20이하 소수 나열하기
counter = 0 #나눗셈 횟수 카운트
for n in range(2,20):
for i in range(2,n):
counter +=1
if n % i ==0:#나누어 떨어지는 소수가 아님
break #반복은 더 이상 불필요하여 중단
else: #끝까지 나누어 떨어지지 않으면 다음 수행
print(n)
print(f'나눗셈을 실행한 함수: {counter}')
2
3
5
7
11
13
17
19
나눗셈을 실행한 함수: 73
100이하 소수 나열하기(알고리즘 개선 1)
counter = 0 #나눗셈 횟수 카운트
ptr = 0 #이미 찾은 소수의 개수
prime = [None] *500 #소수를 저장하는 배열
prime[ptr]=2 #2는 소수이므로 초깃값으로 지정
ptr +=1
for n in range(3,101,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): #ptr의 소수 출력
print(prime[i])
print(f'나눗셈을 실행한 횟수: {counter}')
100이하 소수 나열하기(알고리즘 개선 2)
100의 약수를 생각할때, 직사각형을 생각하면 (2*50), (4*25), (5*20), (10*10), (20*5), (25*4), (50*2) 로 대칭구조를 이룬다.
만약 100이 5로 나누어 떨어지지 않으면 20으로도 나누어 떨어지지 않는다. 한변의 길이만 나눗셈을 시도해서 나눠떨어지지 않으면 소수라고 판단할 수 있다.
counter = 0 #나눗셈 횟수 카운트
ptr = 0 #이미 찾은 소수의 개수
prime = [None] *500 #소수를 저장하는 배열
prime[ptr]=2 #2는 소수
ptr +=1
prime[ptr]=3
ptr +=1
for n in range(5,101,2):
i = 1
while prime[i]* prime[i] <= n:
counter +=2
if n % prime[i]==0:
break
else:
prime[ptr] = n
ptr += 1
counter +=1
for i in range(ptr): #ptr의 소수 출력
print(prime[i])
print(f'나눗셈을 실행한 횟수: {counter}')
counter를 두번 갱신하는 이유는 prime[i]* prime[i], n % prime[i] 이 두번의 연산 실행횟수가 카운트 되기 때문이다.
while 문이 성립하지 않으면 곱셈 횟수는 계산되지 않고 else문에서 1을 증가시킨다.
리스트 원소 복사
얕은 복사
x= [[1,2,3],[4,5,6]]
y = x.copy()
x[0][1]=9
x #[[1, 9, 3], [4, 5, 6]]
y #[[1, 9, 3], [4, 5, 6]]
깊은 복사- y 배열은 영향을 받지 않는다
import copy
x = [[1, 2, 3], [4, 5, 6]]
y = copy.deepcopy(x)
x[0][1]=9
x #[[1, 9, 3], [4, 5, 6]]
y #[[1, 2, 3], [4, 5, 6]]