Statistics/Coding Test

코딩테스트_기초문법.ipynb

해쨔니 2022. 10. 6. 23:08

https://github.com/BeBrave-BeHumble/Coding_test/blob/main/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8_%EA%B8%B0%EC%B4%88%EB%AC%B8%EB%B2%95.ipynb

 

GitHub - BeBrave-BeHumble/Coding_test

Contribute to BeBrave-BeHumble/Coding_test development by creating an account on GitHub.

github.com

https://www.youtube.com/watch?v=m-9pAwq1o3w&t=5367s

나동빈의 코딩테스트 기초 문법 유튜브 참고

알고리즘 문제 해결 과정

  1. 지문 읽기 및 컴퓨터적 사고
  2. 요구사항(복잡도) 분석
  3. 문제 해결을 위한 아이디어 찾기
  4. 소스코드 설계 및 코딩
  • 일반적으로 대부분의 문제는 핵심 아이디어를 캐치한다면, 간결하게 소스코드를 작성할 수 있는 형태로 출제함. 따라서 문제를 온전히 이해하고 어떻게 코드를 설계할 지 생각하고 풀 것.
  • 주 출제 유형
    • 그리디 (쉬운 난이도)
    • 구현
    • DFS/BFS를 활용한 탐색

복잡도

  • 시간 복잡도
  • 특정한 크기의 입력에 대하여 알고리즘의 수행 시간 분석
  • 공간 복잡도
  • 특정한 크기의 입력에 대하여 알고리즘의 메모리 사용량 분석

빅오 표기법

가장 빠르게 증가하는 항만을 고려한다. 연산 횟수가 3N^3 + 5N^2 + 1,000,000 인 알고리즘이 있다면 빅오 표기법에서는 차수가 가장 큰 항만 남기므로 O(N^3)으로 표현된다.

O(1) > O(logN) > O(N) > O(NlogN) > O(N^2) > O(N^3) > O(2^n)

알고리즘 설계 Tip

  • 연산 횟수가 5억을 넘어가는 경우:
    • python기준 5~15초 걸림. C언어보다 오래걸림. pypy가 가장 빠름
    • 우선 python으로 제출하고 시간초과 되면 동일한 코드를 pypy로 제출해보기
  • 코딩 테스트에서 문제의 시간제한은 통상 1~5초임. 문제에 명시되어 있지 않은 경우 대략 5초라고 생각하기.
  • 요구 사항에 따라 적절한 알고리즘 설계하기
    • 문제에서 가장 먼저 확인해야 하는 내용은 '시간제한'
    • 시간제한이 1초인 문제를 만났을 때, 일반적인 기준
      • N의 범위가 500인 경우: 시간 복잡도가 O(N^3)인 알고리즘을 설계
      • N의 범위가 2000인 경우: 시간 복잡도가 O(N^2)인 알고리즘을 설계
      • N의 범위가 100,000인 경우: 시간 복잡도가 O(NlogN)인 알고리즘을 설계
      • N의 범위가 10,000,000인 경우: 시간 복잡도가 O(N)인 알고리즘을 설계
In [1]:
# 시간 복잡도 계산해보기 (1)

array = [3,5,1,2,4] # (N=5)
sum = 0 # 합계 저장할 변수

# 모든 데이터 하나씩 확인하며 합계 계산
for x in array:
    sum += x

print(sum)
15
  • 수행 시간은 데이터 개수 N에 비례함
    • 시간복잡도 : 0(N)
  • 시간제한이 1초인 문제를 만났을 때 일반적인 기준
    • N의 범위가 500인 경우 : 시간 복잡도가 O(N^3)인 알고리즘을 설계해야 한다.
    • N의 범위가 2000인 경우 : 시간 복잡도가 O(N^2)인 알고리즘을 설계해야 한다.
    • N의 범위가 100,000인 경우 : 시간 복잡도가 O(NlogN)인 알고리즘을 설계해야 한다.
    • N의 범위가 10,000,000인 경우 : 시간 복잡도가 O(N)인 알고리즘을 설계해야 한다.
In [2]:
# 시간 복잡도 계산해보기 (2)
# 2중 for문 이용

array = [3,5,1,2,4] # (N=5)

for i in array:
    for j in array:
      temp = i * j
      print(temp)
9
15
3
6
12
15
25
5
10
20
3
5
1
2
4
6
10
2
4
8
12
20
4
8
16
  • 시간복잡도 : 0(N^2)
  • 모든 2중 반복문의 시간 복잡도가 N^2인 것은 아님
    • 소스코드 내부의 함수의 복잡도까지 고려해야함

수행시간 측청

In [5]:
import time
start_time = time.time()

end_time = time.time()
print('Running time:', end_time - start_time)
Running time: 2.7179718017578125e-05

자료형

정수형(integer)

  • 양의 정수, 음의 정수, 0
  • 코딩테스트에서 출제되는 많은 문제들은 주로 정수형을 다룸
In [6]:
# 양의 정수
a = 1000
print(a)

# 음의 정수
a = -7
print(a)

# 0
a = 0
print(a)
1000
-7
0

실수형(Real Number)

  • float
  • 변수에 소수점을 붙인 수를 대입하면 실수형 변수로 처리됨
In [12]:
# 양의 실수
a = 127.56
print(a)

# 음의 실수
a = -127.99
print(a)

# 소수부가 0일 때는 0 생략 가능
a = 408.
print(a)
print(type(a))

# 정수부가 0일 때 0 생략 가능
a = -.408
print(a)
127.56
-127.99
408.0
<class 'float'>
-0.408

지수e 표현 방식

  • 유효숫자e지수
  • 1e9 = 10^9
  • 최단 경로 알고리즘에서는 도달할 수 없는 노드에 대하여 최단 거리를 inf로 설정하곤 함
  • 이 때 가능한 최댓값이 10억 미만이라면 inf 값으로 1e9를 사용할 수 있음
In [14]:
a = 1e9
print(a)

a = 75.25e1
print(a)
print(type(a)) # 실수임을 알 수 있음
print(int(a)) # 정수로 하려면 이렇게

a = 345e-8
print(a)

a = 345e8
print(a)
1000000000.0
752.5
<class 'float'>
752
3.45e-06
34500000000.0

실수형 더 알아보기

  • 이진수는 0.9같은 값을 실제로 표현하지 못 함
  • round 사용하기
    • 셋째 자리에서 반올림: round(123.456, 2) = 123.46
In [15]:
a = 0.3+0.6
print(a) # 0.9가 아님을 알 수 있음

if a == 0.9:
    print('True')
else: 
    print('False')
0.8999999999999999
False
In [16]:
round(a, 2) # 둘째자리에서 반올림
Out[16]:
0.9

수 자료형 연산

  • 파이썬에서 나누기 연산자(/)는 나눠진 '실수형'으로 반환함!!
  • 다양한 로직 설계할 때 나머지 연산자(%) 많이 사용됨
    • 예시: a가 홀수인지 체크
  • 몫 연산지 (//)
  • 거듭제곱 연산자(**)
In [18]:
a = 6
b = 3

# 나누기
print(a / b)

# 나머지
print(a % b)

# 몫
print(a // b)
2.0
0
2
In [23]:
# 거듭제곱
print(a ** b)

# 제곱근 (1)
print(a ** 0.5)

# 제곱근 (2): math 라이브러리 사용
import math
print(math.sqrt(a))

# 제곱근 (3): 세제곱근
print(a ** (1/3))
216
2.449489742783178
2.449489742783178
1.8171205928321397

리스트(List)

  • 여러 개의 데이터를 연속적으로 담아 처리하는 자료형
  • array랑 비슷하다고 생각하면 됨
  • 리스트 초기화
    • [] 안에 원소를 넣으면 됨
    • 비어있는 인덱스는 list() 혹은 []로 선언
    • 리스트의 원소에 접근할 때는 index 사용. (0부터 시작)
In [1]:
# 데이터 직접 넣어 초기화
a = [1, 2, 3, 4]
print(a)

# 네 번째 원소 출력
print(a[3])

# 크기가 N이고, 모든 값이 0인 1차원 리스트
n = 10
a = [0] * n
print(a)
[1, 2, 3, 4]
4
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
In [2]:
# 특정 위치 값 바꾸기
a = [1, 2, 3, 4]
a[2] = 7
print(a)
[1, 2, 7, 4]

리스트의 인덱싱과 슬라이싱

  • 연속적인 위치를 갖는 원소들을 가져와야 할 때는 슬라이싱 사용
  • 끝 인덱스는 실제 인덱스보다 1을 더 크게 설정
In [3]:
# 뒤에서 첫 번째 원소 
print(a[-1])

# 뒤에서 세 번째
print(a[-3])
4
2
In [5]:
# 연속적인 위치를 갖는 원소들을 가져와야 할 때는 슬라이싱 사용
# 끝 인덱스는 실제 인덱스보다 1을 더 크게 설정

# 두 번째 원소부터 세 번째 원소까지
print(a)
print(a[1:3])
[1, 2, 7, 4]
[2, 7]

리스트 컴프리헨션

  • 리스트를 초기화 하는 방법
    • 대괄호 안에 조건문과 반복문을 적용하여 리스트 초기화 할 수 있음
In [6]:
# 0부터 9까지의 수를 포함하는 리스트
a = [i for i in range(10)]
print(a)
print(type(a))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
<class 'list'>
In [7]:
# 0부터 19까지 수 중에서 홀수만 포함하는 리스트
a = [i for i in range(20) if i % 2 == 1]
print(a)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
In [10]:
# 컴프리헨션 안 쓴 경우
a = [] # 리스트 초기화

for i in range(20):
    if i % 2 == 1:
        a.append(i)

print(a)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
In [9]:
# 1부터 9까지 수들의 제곱 값을 포함하는 리스트
a = [i**2 for i in range(1, 10)]
print(a)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 2차원 리스트 초기화할 때 효과적으로 사용 가능
  • 특히 코딩테스트에서 n*m 크기의 2차원 리스트를 한 번에 초기화 할 때 매우 유용
In [13]:
m = 3
n = 5

array = [[0] * m for _ in range(n)] # _ 대신 알파벳 넣어도 됨~
print(array)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
In [18]:
# 잘못된 예시 1
a = [[0, 0, 0]*3]
print(a)

# 잘못된 예시 2
a = [[0]*m]*n
print(a)
# 생긴 건 컴프리헨션 사용한 거랑 똑같지만 내부 값들의 id가 다 똑같이 생성됨
# 따라서 전체 리스트 안에 포함된 각 리스트가 모두 같은 객체로 인식됨

a[1] = [7]
print(a)
[[0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [7], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
  • 컴프리헨션 좋은 예시
In [20]:
m = 3
n = 4
array = [[0] * m for _ in range(n)]
print(array)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

리스트 컴프리헨션 나쁜 예시

In [21]:
array = [[0] * m ] * n
print(array)
# 4x3 행렬 모양은 제대로 만들어졌지만
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
In [22]:
array[1][1] = 5 # 2행 2열을 5로 변경
print(array) # 2열 전부 5로 변경됨
[[0, 5, 0], [0, 5, 0], [0, 5, 0], [0, 5, 0]]
In [23]:
array[2][0] = 7
print(array) # 3행 1열만 바꾸려 했는데 1열 전부 다 바뀜
[[7, 5, 0], [7, 5, 0], [7, 5, 0], [7, 5, 0]]
  • 언더바는 언제 사용하나요?
    • 반복문을 수행하되 반복을 위한 변수의 값을 무시하고자 할 때!!
In [28]:
# 1부터 9까지 자연수 더하기
sum = 0
for i in range(1, 10):
    sum += i


print(sum)
45
In [30]:
# Hello world! 5번 출력하기
for _ in  range(5):
  print("hellowordl!")
hellowordl!
hellowordl!
hellowordl!
hellowordl!
hellowordl!
  • 리스트 관련 기타 메소드
In [2]:
a = [1, 2, 7]

# 리스트에 원소 삽입
a.append(2)
print('삽입:', a)

# 오름치순 정렬
a.sort()
print('오름차순:', a)

# 내림차순 정렬
a.sort(reverse=True)
print('내림차순:', a)

# 원소 뒤집기
a.reverse()
print('뒤집기:', a)

# 특정 인덱스에 데이터 추가
a.insert(2, 3)
print('인덱스 2에 3추가:', a)

# 특정 값인 데이터 개수 세기
print("값이 3인 데이터 개수:", a.count(a))

# 특정 값 데이터 삭제
a.remove(1)
print('1인 값 삭제:', a)
삽입: [1, 2, 7, 2]
오름차순: [1, 2, 2, 7]
내림차순: [7, 2, 2, 1]
뒤집기: [1, 2, 2, 7]
인덱스 2에 3추가: [1, 2, 3, 2, 7]
값이 3인 데이터 개수: 0
1인 값 삭제: [2, 3, 2, 7]
  • 리스트에서 특정 값을 가지는 원소 모두 제거
In [3]:
a = [1, 2, 3 ,4, 5, 5, 5]
remove_set = {3, 5} # 집합 자료형

# remove_set에 포함되지 않은 값만 저장
result = [ i for i in a if i not in remove_set ]
print(result)

# remove는 단순히 원소 하나만을 지우므로 전부를 지울 땐 집합 자료형 이용해야함
[1, 2, 4]

문자열 자료형

  • 큰 따옴표나 작은 따옴표 이용
In [4]:
data  = 'Hello world!'
print(data)

data = "Don't you know \"Python\"?"
print(data)
Hello world!
Don't you know "Python"?
  • 문자열 연산
    • 덧셈을 이용하면 문자열이 concat됨
    • 양의 정수를 곱하면 문자열이 그 값만큼 여러번 반복됨
    • 인덱싱과 슬라이싱 가능하나, 문자열 변경은 불가능
In [7]:
a = "Be Brave"
b = "Be Humble"
print(a + " " + b)

print(a * 3)

print(b[1:5])
Be Brave Be Humble
Be BraveBe BraveBe Brave
e Hu

튜플 자료형

  • 리스트와 유사하지만 문법적 차이가 있음
    • 한번 선언된 값은 변경 불가능
    • 튜플은 소괄호
  • 리스트에 비해 상대적으로 기능이 제한적이므로 '공간 효율적' (메모리 작음)
In [8]:
a = (1, 2, 3 ,4 ,5 ,6)
print('네번째 원소:', a[3])

print('슬라이싱:', a[1:4])
네번째 원소: 4
슬라이싱: (2, 3, 4)
In [9]:
a[2] = 7

# 변환 불가능이라 오류
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-e6a6e41c76c7> in <module>
----> 1 a[2] = 7
      2 
      3 # 변환 불가능이라 오류

TypeError: 'tuple' object does not support item assignment

튜플을 사용하면 좋은 경우

  • 서로 다른 성질의 데이터를 묶어서 관리할 때
    • 최단 경로 알고리즘에서 (비용, 노드 번호)의 형태로 튜플 사용
    • (이름, 학번) 등
  • 데이터의 나열을 해싱(Hashing)의 키 값으로 사용해야 할 때
    • 튜플은 변경이 불가능하므로 리스트와 다르게 키 값으로 사용될 수 있음
  • 리스트보다 메모리 효율적으로 사용해야 할 때

사전 자료형

  • key와 value의 쌍을 데이터로 가지는 자료형
    • 앞서 다루었던 리스트나 튜플이 값을 순차적으로 저장하는 것과 대비됨
  • key:value를 쌍으로 가지며, 원하는 '변경 불가능한 자료형'을 key로 사용할 수 있음 ex.tuple!!!
  • 파이썬에서 자료형은 해시 테이블(Hash Table)을 이용하므로 '데이터 조회 및 수정에 있어서 O(1)의 시간에 처리'할 수 있음
    • 문자가 같은 키를 이용하여 데이터를 저장하고 관리할 때 리스트보다 훨씬 효율적으로 조회를 빠르게 수행함
  • 키 데이터만 뽑아서 리스트로 이용할 땐 keys() 함수 사용
  • 값 데이터만 뽑아서 리스트로 사용할 땐 values() 함수 사용
In [13]:
data = dict() # dict()로 초기화

data['사과'] = 'Apple'
data['바나나'] = 'Banana'
data['코코넛'] = 'Coconut'

print(data)

if '사과' in data: # 특정 키가 있는지 존재하려면 if & in 사용!!!!!!!!
    print('"사과"를 키로 가지는 데이터가 존재한다')
{'사과': 'Apple', '바나나': 'Banana', '코코넛': 'Coconut'}
"사과"를 키로 가지는 데이터가 존재한다
In [14]:
# key list
key_list = data.keys()
print(key_list)

value_list = data.values()
print(value_list)
dict_keys(['사과', '바나나', '코코넛'])
dict_values(['Apple', 'Banana', 'Coconut'])
In [17]:
list(data.keys()) # 리스트로 접근하기
Out[17]:
['사과', '바나나', '코코넛']
In [16]:
# 각 키에 따른 값을 하나씩 출력
for key in key_list :
    print(data[key])
Apple
Banana
Coconut

집합 자료형

  • 중복 허용X
  • 순서 없음
  • 리스트나 문자열을 이용하여 초기화 가능. set( [] )
  • 중괄호 안에 각 원소를 콤마로 구분하여 삽입
  • 집합 연산
    • 합집합/ 교집합/ 차집합
In [18]:
# 집합 자료형 초기화 방법1
data = set([1,1,1,2,2,2,3,4,5,6,4,2,4,7,8])
print(data)

# 중복 허용 X이므로 한 번씩만 출력됨
{1, 2, 3, 4, 5, 6, 7, 8}
In [19]:
# 집합 자료형 초기화 방법2
data = {1,1,2,3,4,4,5}
print(data)
{1, 2, 3, 4, 5}
In [20]:
a = set([1,2,3,4,5])
b = set([3,4,5,3,1])

# 합집합
print(a|b)

# 교집합
print(a&b)

# 차집합
print(a-b)
{1, 2, 3, 4, 5}
{1, 3, 4, 5}
{2}
In [21]:
# 새로운 원소 추가 : add
data.add(4)
print(data)

# 새로운 원소 여러개 추가: update
data.update([10,11])
print(data)

# 특정한 값을 갖는 원소 삭제
data.remove(3)
print(data)
{1, 2, 3, 4, 5}
{1, 2, 3, 4, 5, 10, 11}
{1, 2, 4, 5, 10, 11}

사전 자료형과 집합 자료형 특징

  1. 리스트나 튜플과 달리 순서가 없기 때문에 인덱싱으로 값 얻을 수 x
  2. 사전의 key 혹은 집합의 원소를 이용해 O(1)의 시간 복잡도

기본 입출력

  • input 함수는 한 줄의 문자열을 입력받는 함수
  • map함수는 리스트의 모든 원소에 각각 특정한 함수를 적용하고자 할 때 사용
  • 예시) 공백 기준으로 구분된 데이터 입력 받을 때
    • list( map( int, input().split() ) )
  • 예시) 공백 기준으로 구분된 데이터 수가 많지 않다면 다음처럼 사용
    • a, b, c = map( int, input().split() )

입력을 위한 전형적인 소스코드 1

In [ ]:
# 데이터의 개수 입력
n = int(input())

# 각 데이터를 공백 기준으로 구분하여 입력
data = list( map( int, input().split() ))

data.sort(reverse=True) # 내림차순
print(data)
In [23]:
# 실습

n = int(input()) # 데이터 수 입력
data = input() # 데이터 값 입력

print(n)
print(data)
5
78 94 32 85 43
5
In [25]:
n = int(input())
data = input().split() # 공백기준으로 분리하겠다

print(n)
print(data) # 공백 기준으로 문자열이 분리됨
5
87 23 11 56 77
5
['87', '23', '11', '56', '77']
In [26]:
# 실제 코테에선 이렇게 가장 많이 씀!!!!
# 문제 초반부 입력 받는 부분에 이렇게 할 것~!~!

n = int(input())
data = list(map( int, input().split() )) # 정수형 함수 적용하여 리스트에 넣기

print(n)
print(data)
5
22 34 54 11 66
5
[22, 34, 54, 11, 66]
In [27]:
# 반드시 데이터가 세개가 들어온다고 정해져있다면

a, b, c = map(int, input().split()) # 언패킹 = 패킹
print(a,b,c)
44 92 77
44 92 77

빠르게 입력 받기

  • 입력의 수가 많은 경우, 최대한 빠르게 받아서 씀
    • 이진탐색, 정렬, 그래프 문제에서 씀
  • 파이썬의 경우 sys라이브러리에 정의된 sys.stdin.readline() 메서드 이용
    • 단, 입력 후 엔터가 줄 바꿈 기호로 입력되므로 'rstrip()' 함께 써야함!!!
In [28]:
import sys

# 문자열 입력받기
data = sys.stdin.readline().rstrip()
print(data)
 

출력을 위한 전형적인 소스코드

In [29]:
a = 1
b = 2
print(a, b) # print 후에는 자동으로 줄바꿈 됨

print(7, end=" ") # 줄바꿈 대신 스페이스 사용하면 밑의 8과 한줄로 붙어서 공백으로 분리되어 출력됨
print(8, end=" ")

dd = 7
print("정답은 " + str(dd) +"입니다.")
1 2
7 8 정답은 7입니다.

f-string 예제

  • 문자열 앞에 f를 붙여 사용함
  • 중괄호 안에 변수명 기입하여 간단히 문자열과 정수 함께 넣을 수 있음
In [30]:
# 문자열 앞에 f를 붙여 사용함

dd = 7
print(f"정답은 {dd}입니다.")
정답은 7입니다.

조건문

  • 프로그램의 흐름을 제어
In [32]:
a = 5

if a >= 0:
    print("a>=0")
elif a >= -10:
    print("0> a> -10")
else:
    print("-10>a")

print("종료.")
a>=0
종료.

조건문 간소화

  • 조건문에서 실행할 소스코드가 한 줄인 경우 사용
In [41]:
score = 85

if score >= 80: result = "success"
else: result = "fail"

print(result)
success
  • 조건부 표현식은 if~else 문을 한 줄에 작성할 것!
In [42]:
score = 85
result = "success" if score >= 80 else "fail" # if 기준 참일 때가 왼쪽 거짓일 때가 오른쪽

print(result)
success

논리 연산자

  • A and B
  • A or B
  • not A
In [35]:
a = 15

if a <= 20 and a >= 0:
    print("yes")
yes
In [36]:
# 조건문 내부에서는 수학 부등식 사용 가능
if 0 <= a <= 20: 
    print("yes")
yes

기타 연산자

  • 리스트, 튜플, 문자열, 딕셔너리 모두 사용 가능
    • x in 리스트
    • x not in 문자열

pass 키워드

  • 아무것도 처리하고 싶지 않을 때 사용
  • 일단 조건문 형태만 만들고 조건문 처리 과정 비우고 싶은 경우 사용
In [39]:
score = 85

if score >= 80:
    pass # 나중에 처리할 부분
else:
    print("a<30")

반복문

  • 특정한 소스코드 반복 실행
  • while, for 아무거나 사용 가능하나 보통 코테에서는 for가 더 간결함

while

1부터 9까지 모든 정수 합 구하는 예제

In [44]:
i = 1
result = 0

while i <= 9:
    result += i
    i += 1

print(result)
45

1부터 9까지 홀수 합 구하기

In [48]:
i = 1
result = 0 

while i < 10:
    if i % 2 == 1:
        result += i
    i += 1

print(result)
25

for

In [49]:
array = [1, 23, 4, 56]

for x in array:
    print(x)
1
23
4
56

continue 키워드

  • 남은 코드의 실행을 건너뛰고, 다음 반복 진행할 때 사용
In [51]:
# 1부터 9까지 홀수의 합

result = 0

for i in range(1, 10):

      if i % 2 == 0:
          continue
          # result -= 1
      result += i

print(result)
25

break 키워드

  • 반복문 즉시 탈출
In [53]:
# 1부터 5까지 정수 차례로 입력

i = 1

while True:
    print("현재 i 값", i)
    if i >= 5:
        break
    i += 1
현재 i 값 1
현재 i 값 2
현재 i 값 3
현재 i 값 4
현재 i 값 5

반복문 예제

In [54]:
# 1) 학생들의 점수가 80점 넘으면 합격

score = [90, 85, 77, 65, 97]

for i in score:
    if i >= 80:
        print(f"{i}점 이므로 합격")
    else:
        print(f"{i}점 이므로 불합격")
90점 이므로 합격
85점 이므로 합격
77점 이므로 불합격
65점 이므로 불합격
97점 이므로 합격
In [57]:
aa = [print(i+1, "번 학생 합격") for i in range(5) if score[i]>80]
1 번 학생 합격
2 번 학생 합격
5 번 학생 합격
In [58]:
# 2) 부정학생 제외하기
cheating_list = {2, 4}

for i in range(5):
    if i+1 in cheating_list:
        continue
    if score[i] >= 80:
        print(i+1, "번 학생은 합격입니다")
1 번 학생은 합격입니다
5 번 학생은 합격입니다
In [62]:
# 2) 이중포문: 구구단 예제

for i in range(2, 10):
    for j in range(1, 10):
        print(i, '*', j, "=", i*j )
    print()
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18

3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27

4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36

5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25
5 * 6 = 30
5 * 7 = 35
5 * 8 = 40
5 * 9 = 45

6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54

7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63

8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 48
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72

9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81

함수

  • 매개변수: 함수 내부에서 쓸 변수
  • 반환 값: 처리된 결과 반환
def 함수명(매개변수):

    실행할 소스코드
    return 반환값
  • 더하기 함수 예시 1)
In [63]:
def add(a,b):
   return a+b

print(add(3,7)) # 함수 안에 넣는 값은 arguments, 인자라고 함
10
  • 더하기 함수 예시 2)
In [65]:
def add(a,b):
    print('함수 결과:', a+b)

add(3,6)
# 이렇게 꼭 return이 없어도 됨
함수 결과: 9

파라미터 지정하기

In [66]:
def add(a,b):
   return a+b

print(add(b=3,a=7))
10

global 키워드

  • global 키워드로 변수를 지정하면 해당 함수에서는 지역 변수를 만들지 않고, 함수 바깥에 선언된 변수를 바로 참조함
  • 하지만 함수 안에 지역변수 선언하면 지역변수 우선임
In [ ]:
a = 0

def func():
    global a
    a += 1

for i in range(10):
    func()

print(a)
In [69]:
a = 10

def func():
    global a 
    a += 1 # 가져온 값을 바꾸려면 위에 global 선언해야함 
    print(a)

func()
11
In [70]:
a = 10

def func():
    print(a) # 함수에 변환 안 할거면 선언 안 해도 됨

func()
10
In [72]:
array = [1,2,3,4,5] # 리스트도 전역 변수로 사용 가능

def func():
    array.append(99) # 그러나 리스트의 경우 따로 global 선언 안 해도 값 바꿀 수 있음
    print(array)

func()
[1, 2, 3, 4, 5, 99]
In [73]:
array = [1,2,3,4,5] # 리스트도 전역 변수로 사용 가능

def func():
    global array
    array = [3, 4, 5] # 글로벌 선언 해놓고 내부에서 값을 바꾸면
    array.append(99) 
    print(array)

func()
print(array) # 전역변수 또한 내부에서 선언한대로 바뀜
[3, 4, 5, 99]
[3, 4, 5, 99]

여러개의 반환값

  • 컴마로 구분지어서 반환값을 여러개 리턴할 수 있음 => 패킹
In [75]:
def operator(a, b):
    add_var = a + b
    substract_var = a - b
    multiply_var = a * b
    divide_Var = a / b
    
    return add_var, substract_var, multiply_var, divide_Var # 패킹하여 반환

print(operator(7,3))

a, b, c, d = operator(7,3) # 언패킹하여 반환
print(a, b, c, d)
(10, 4, 21, 2.3333333333333335)
10 4 21 2.3333333333333335

람다 표현식

  • 람다 표현식 이용하면 함수 간단 작성 가능
  • 특정한 기능을 수행하는 함수를 한 줄에 작성할 수 있음
  • 함수의 이름을 요구하지 않음
  • 매개변수를 차례로 입력하고, 콜론, 함수
  • 함수 자체를 입력으로 받는 또 다른 함수에서 유용함 (내장함수)
In [76]:
# 람다로 구현한 add

print( (lambda a, b : a + b)(3, 7))
10
  • 람다 표현식 예시: 내장 함수에서 자주 사용되는 람다 함수
In [77]:
array = [('해찬', 00), ('도영', 96), ('재현', 97)]

def my_key(x):
    return x[1] # 두 번째 원소

print(sorted(array, key = my_key)) # sorted(정렬할 리스트, 기준)

print(sorted(array, key = lambda x: x[1]))
[('해찬', 0), ('도영', 96), ('재현', 97)]
[('해찬', 0), ('도영', 96), ('재현', 97)]
  • 람다 표현식 예시: 여러 개의 리스트에 적용
In [82]:
# 여러개의 리스트에 동일한 규칙 적용할 때
list1 = [1, 2, 3, 4, 5]
list2 = [6, 7, 8, 9, 10]

# map: 각 원소에 어떤 함수 적용할 때.
# 첫 번째 원소끼리/ 두 번째 원소 끼리,,,, 를 더한 결과를 리스트에 담을 때

result = map(lambda a, b: a + b, list1, list2) # 람다함수 정의, 각 원소를 뽑아낼 리스트 정의

print(list(result))
print(result)
[7, 9, 11, 13, 15]
<map object at 0x7f72225e70d0>

실전에서 유용한 표준 라이브러리

  • 내장함수: 기본 입출력부터 정렬까지
  • itertools: 파이썬에서 반복되는 형태의 데이터 처리하기 위한 기능 제공
    • 특히 순열과 조합 라이브러리는 코딩 테스트에 자주 사용됨. (모든 경우를 탐색해야 하는 경우)
  • heapq: 힙(Heap) 자료구조 제공
    • 일반적으로 우선순위 큐 기능 구현하기 위해 사용됨. 최단 경로에 응용
  • bisect: 이진탐색 (binary search) 기능 제공
  • collections: 덱(deque), 카운터(counter) 등의 유용한 자료 구조를 포함함
  • math: 필수적인 수학 기능 제공
    • 팩토리얼, 제곱근, 최대공약수(GCD), 삼각함수, 파이(pi)

내장함수

In [86]:
array = [1, 2, 3, 4, 5]
# sum
print(sum(array))

# min, max
print(min(array), max(array))

# eval() : 수식을 계산한 결과를 수 형태로 반환
result = eval("(3+5)*7")
print(result)
15
1 5
56
  • 새로운 정렬된 리스트를 반환하는 함수는 sorted 함수
  • 리스트 자체를 정렬 시키는 것은 sort 함수
In [94]:
# sorted
print(sorted(array))
print(sorted(array, reverse=True))

import math
array.sort
print(array) # 원본 값이 바뀜
array.sort(reverse=True)
print(array)
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
In [95]:
# sorted with key
array = [('해찬', 00), ('도영', 96), ('재현', 97)]

result = sorted(array, key = lambda x: x[1], reverse = True)
print(result)
[('재현', 97), ('도영', 96), ('해찬', 0)]

순열과 조합

  • 순열: nPr 일렬로 나열. 순서를 고려함
  • 조합: nCr 순서에 상관없이 서로 다른 r개 뽑기
In [98]:
# 순열

from itertools import permutations

data = ['해찬', '도영', '재현']

result = list(permutations(data, 3))  # 세개 뽑아서 모든 순열 구하기
print(result)
[('해찬', '도영', '재현'), ('해찬', '재현', '도영'), ('도영', '해찬', '재현'), ('도영', '재현', '해찬'), ('재현', '해찬', '도영'), ('재현', '도영', '해찬')]
In [100]:
# 조합

from itertools import combinations

data = ['해찬', '도영', '재현']

result = list(combinations(data, 2))
print(result)
[('해찬', '도영'), ('해찬', '재현'), ('도영', '재현')]

중복순열과 중복조합

In [102]:
from itertools import product

data = ['해찬', '도영', '재현']

result = list(product(data, repeat=2)) # 2개 뽑는 모든 순열 구하기 (중복 허용)
print(result)

from itertools import combinations_with_replacement

result = list(combinations_with_replacement(data, 2)) # 중복 허용하여 2개 뽑기
print(result)
[('해찬', '해찬'), ('해찬', '도영'), ('해찬', '재현'), ('도영', '해찬'), ('도영', '도영'), ('도영', '재현'), ('재현', '해찬'), ('재현', '도영'), ('재현', '재현')]
[('해찬', '해찬'), ('해찬', '도영'), ('해찬', '재현'), ('도영', '도영'), ('도영', '재현'), ('재현', '재현')]

Counter

  • 각 원소의 등장 횟수를 세는 기능!!!!!!!!!!!!!!
  • 리스트와 같은 반복 가능한 객체 주어졌을 때 내부 원소가 몇 번 등장했는지 알려줌
In [103]:
from collections import Counter

counter = Counter(['red', 'blue', 'red', 'green', 'blue', 'blue'])

print(counter['blue']) 
print(counter['green'])
print(dict(counter)) # 사전 자료형으로 반환
3
1
{'red': 2, 'blue': 3, 'green': 1}

최대공약수와 최소공배수

In [104]:
import math

# 최소공배수(LCM)
def lcm(a, b):
    return a * b // math.gcd(a, b) # 최소공배수 공식에 따라 최대공약수로 나눈 결과값 리턴
  
a = 21
b = 14

print(math.gcd(21, 14)) # 최대 공약수
print(lcm(21, 14)) # 최소 공배수
7
42
In [ ]:
In [ ]:
In [ ]:
In [ ]: