[ 알고리즘 ]/알고리즘

[알고리즘] 0. Python 기본 문법

불주먹고양이 2021. 12. 21. 12:45

/* '이것이 취업을 위한 코딩 테스트다' 책의 저자이신 나동빈 님의 예시와 제가 학교 수업에서 배운 내용을 바탕으로 정리했습니다. */

 

 

1. 자료형 (Data Type)

 

(1) 정수형

x = 5
print("type() : ", type(x))
print("x : ", x)

< 출력 >

type() :  <class 'int'>
x :  5

 

x = 5
print("x : ", x)

x += 10
print("x : ", x)

< 출력 >

x :  5
x :  15

 

 

(2) 실수형

fl = 15.111
print("type() : ", type(fl))
print("fl : ", fl)

< 출력 >

type() :  <class 'float'>
fl :  15.111

 

fll = 5.
print("fll : ", fll)

exp = int(1e9)
print("exp : ", exp)

exp의 값은 e 다음에 오는 숫자의 거듭제곱으로 10을 곱한다. (1 * (10)^9)

 

< 출력 >

fll :  5.0
exp :  1000000000

 

 

※ 컴퓨터는 모든 정보를 0과 1 (이진법)으로 다루기 때문에 오류가 발생할 수 있다.

a = 0.3 + 0.6
print("a : ", a)

if a == 0.9:
    print("a == 0.9")
else:
    print("a != 0.9")

우리는 a의 값이 당연히 0.9라고 생각하지만, 컴퓨터는 그렇게 받아들이지 않기 때문에...!

round() 함수가 필요하다.

 

< 출력 >

a :  0.8999999999999999
a != 0.9

 

a = 0.3 + 0.6
print("a : ", a)

a = round(a, 2)
print("a : ", a)

if a == 0.9:
    print("a == 0.9")
else:
    print("a != 0.9")

round(숫자, 소숫점 아래 몇번째인지)

위의 예시에서는 소숫점 아래 두번째에서 반올림한다.

 

< 출력 >

a :  0.8999999999999999
a :  0.9
a == 0.9

 

 

(3) 수 자료형의 연산

a = 7
b = 3

print("a / b = ", a/b)
print("a % b = ", a % b)
print("a // b = ", a//b)
print("a ** b = ", a**b)

< 출력 >

a / b =  2.3333333333333335
a % b =  1
a // b =  2
a ** b =  343

 

 

(4) 리스트 자료형

- 리스트 초기화 : [], list()

lst = [7, 5, 7, 4, 3, 6, 5]
print("type() : ", type(lst))
print("lst : ", lst)

print("lst[:4] : ", lst[:4])

< 출력 >

type() :  <class 'list'>
lst :  [7, 5, 7, 4, 3, 6, 5]
lst[:4] :  [7, 5, 7, 4]

 

 

- list comprehension (리스트 컴프리헨션)

: 리스트를 더 간결하게 작성하는 방법!

com_lst = [i for i in range(10)]
print(com_lst)

com_lst2 = [i*2 for i in range(5)]
print(com_lst2)

com_lst3 = [i for i in range(20) if i % 2 == 0]
print(com_lst3)

com_lst는 range(10)의 원소 값들로 만든 리스트이고,

com_lst2는 range(5)의 원소를 2배해서 만든 리스트이며,

com_lst3는 range(20)의 원소 중에서 2의 배수인 수들로 만든 리스트이다.

(for문으로 리스트를 만들고 그 안에 if문을 넣어주는 것보다 훨씬 짧아서 보기도 좋은 것 같다..ㅎ!)

 

< 출력 >

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

 

 

※ list comprehension은 특히 2차원 리스트를 초기화할 때 효과적이다!

일단, 파이썬에서의 언더바(_)는 반복을 수행하되, 반복을 위한 변수의 값을 무시하고자 할 때 사용한다.

for _ in range(5):
    print("Hello World")

< 출력 >

Hello World
Hello World
Hello World
Hello World
Hello World

 

row = 5
column = 4

array = [[0]*column for _ in range(row)]
print(array)

모든 원소의 값을 0으로 초기화 한 5x4 2차원 배열이 만들어졌다.

 

< 출력 >

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

 

 

- 리스트 유용한 함수

a = [4, 3, 2, 1]
print(a)

a.reverse()
print(a)

a.insert(2, 10)
print(a)

print(a.count(2))

a.remove(1)
print(a)

< 출력 >

[4, 3, 2, 1]
[1, 2, 3, 4]
[1, 2, 10, 3, 4]
1
[2, 10, 3, 4]

 

 

- 리스트에서 특정 값을 가지는 원소 모두 제거하기

lst = [1, 2, 3, 3, 3, 3, 3, 4, 5, 6, 6, 6]
remove_set = {3, 6}

lst = [i for i in lst if i not in remove_set]
print(lst)

< 출력 >

[1, 2, 4, 5]

 

 

(5) 문자열 자료형

str = "Hello"
print(str)
print("len() : ", len(str))

< 출력 >

Hello
len() :  5

 

 

(6) 튜플 자료형

: unchangeable (추가, 삭제, 수정 다 불가능!!)

 

- 튜플 자료형을 사용하면 좋은 경우 : 서로 다른 성질의 데이터를 묶어서 관리해야 할 때

- 최단 경로 알고리즘 (비용, 노드 번호)의 형태로 튜플 자료형을 자주 관리할 때

- 데이터의 나열을 해싱 (Hashing)의 키 값으로 사용해야 할 때

- 튜플은 변경이 불가능하므로 리스트와 다르게 키 값으로 사용될 수 있음

- 리스트보다 메모리를 더 효율적으로 사용할 수 있음

 

tup = (1, 2, 3, 4, 5, 5, 5, 6)
print(tup)

< 출력 >

(1, 2, 3, 4, 5, 5, 5, 6)

 

 

(6) 사전 자료형

- 해시 테이블을 이용하므로 데이터의 조회 및 수정이 O(1)의 시간에 처리된다.

fruit = dict()
fruit['A'] = 'apple'
fruit['B'] = 'banana'
fruit['M'] = 'mango'
fruit['S'] = 'strawberry'

print(fruit.keys())
print(fruit.values())

< 출력 >

dict_keys(['A', 'B', 'M', 'S'])
dict_values(['apple', 'banana', 'mango', 'strawberry'])

 

 

(7) 집합 자료형

- 중복 허용 안하고 순서 없음

sset = set([1, 1, 1, 1, 5, 5, 3, 5, 6, 6, 2])
print(sset)

< 출력 >

{1, 2, 3, 5, 6}

 

 

 

 

2. 표준 입력 방법

- input() : 한 줄의 문자열을 입력 받는 함수

- map() : 리스트의 모든 원소에 각각 특정한 함수를 적용할 때 사용

map (함수, 반복가능자료형)

lst = [1, 2, 3, 4, 5]

def add_one(n):
    return n+1

result = list(map(add_one, lst))

print(result)

map 함수에 add_one 함수와 lst 리스트를 넣어주었더니

알아서 lst의 모든 원소에 1이 더해진 값을 얻을 수 있었다. 코드가 매우 간결해지고 빨라진 것을 알 수 있다!!

 

num = int(input())
data = list(map(int, input().split()))
data.sort(reverse=True)
print(data)

input()는 입력 받은 값을 하나의 문자열로 인식한다.

그래서 split()으로 공백을 기준으로 하여 숫자들끼리 분리해준다.

 

왜 map 함수가 필요할까?

map 함수 없이 int 함수로 공백 기준으로 자른 문자열 (숫자로 보이는)을 정수로 바꾼다고 해보자.

data = list(int(input().split()))
print(data)

< 출력 >

Traceback (most recent call last):
  File "c:\Users\Kong JiYun\Desktop\Algorithm\ptyhon\practice.py", line 1, in <module>
    data = list(int(input().split()))
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

 

에러가 난다..!

int 함수는 리스트 자료형을 정수로 바꿀 수 없다고 한다.

map 함수를 적극적으로 활용해야겠다.

 

 

- 사용자로부터 입력을 최대한 빠르게 받아야하는 경우

: sys 라이브러리에 정의되어 있는 sys.stdin.readline() 사용!

입력 후 엔터가 줄 바꿈 기호로 입력되므로 rstrip() 메서드를 함께 사용한다.

import sys
a = int(sys.stdin.readline().rstrip())
print(a)

 

- 임의의 정수 나열을 받아서 list에 저장할 경우 (sys 라이브러리 + map 함수)

import sys
num_input = list(map(int, sys.stdin.readline().split()))
print(num_input)

< 출력 >

1 2 3 4 5
[1, 2, 3, 4, 5]

 

 

- f-string

: 문자열 앞에 f를 붙여서 사용한다.

answer = 100
print(f"The answer is {answer}.")

< 출력 >

The answer is 100.

 

 

 

3. 조건문

if True:
    print("Yes")
else:
    print("No")

< 출력 >

Yes

 

 

- 조건부 표현식

score = 85
result = "Success" if score >= 80 else "Fail"
print(result)

< 출력 >

Success

 

 

 

4. 반복문

- while문 보다는 for문을 더 많이 사용한다고 한다.

scores = [90, 85, 77, 65, 97]
cheating_student_list = {2, 4}

for i in range(5):
    if i+1 in cheating_student_list:
        print(i+1, " student is in cheating student list")
    else:
        if scores[i] >= 80:
            print(i+1, " student passed")

< 출력 >

1  student passed
2  student is in cheating student list
4  student is in cheating student list
5  student passed

 

 

 

5. 함수

- 내장 함수 : 파이썬이 기본적으로 제공하는 함수

- 사용자 정의 함수 : 개발자가 직접 정의하여 사용할 수 있는 함수

def add(a, b):
    return a+b

result = add(3,7)
print(result)

< 출력 >

10

 

 

- global 변수 : 전역 변수

a = 10
print(a)


def func():
    global a
    a += 1


func()
print(a)

< 출력 >

10

11

 

 

- array는 global 변수 없이도 함수 내에서 참조 가능하다, 하지만 지역 변수의 우선순위가 더 높다

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


def change_func():
    array[0] = 100


change_func()
print(array)

< 출력 >

[1, 2, 3, 4, 5]
[100, 2, 3, 4, 5]

 

 

- 여러 개의 return 값을 받아올 수 있다.

def operator(a, b):
    add_var = a+b
    min_var = a-b
    mul_var = a*b
    div_var = a/b

    return add_var, min_var, mul_var, div_var


add, min, mul, div = operator(3, 6)
print(add, min, mul, div)

< 출력 >

9 -3 18 0.5

 

 

- 람다 표현식

네 줄의 함수를 람다 함수 표현식으로 간결하게 만들 수 있다.

 

ⓐ 람다 함수에 매개변수를 주고 싶다면

(lambda 변수 : 식)(매개변수)

 

 

ⓑ 람다 함수 내에서는 변수를 만들 수 없다.

윗 줄은 110으로 정확하게 동작하지만, 

아랫 줄은 SyntaxError: invalid syntax로 에러가 난다. 즉, lambda 함수 내에서 새로운 변수인 y를 만들 수 없다는 것이다.

 

 

ⓒ 람다 표현식은 내장 함수에서 자주 사용된다.

cf) sorted(정렬할 데이터, key 파라미터)

array = [('C', 50), ('F', 32), ('A', 74)]


def my_key(x):
    return x[1]


print(sorted(array, key=my_key))

key 값을 x[1]로 주어서 숫자를 기준으로 정렬할 수 있도록 했다.

 

< 출력 >

[('F', 32), ('C', 50), ('A', 74)]

 

array = [('C', 50), ('F', 32), ('A', 74)]

print(sorted(array, key=lambda x: x[1]))

< 출력 >

[('F', 32), ('C', 50), ('A', 74)]

 

 

list1 = [1, 2, 3, 4, 5]
list2 = [6, 7, 8, 9, 10]

result = map(lambda lst1, lst2: lst1+lst2, list1, list2)
print(list(result))

lamda 함수로 두 리스트의 합을 받아오고 map 함수로 리스트를 재 정의 해준다.

 

< 출력 >

[7, 9, 11, 13, 15]

 

 

 

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

(1) 내장 함수 : 기본 입출력 함수부터 정렬 함수까지 기본적인 함수들을 제공(2) itertools : 파이썬에서 반복되는 형태의 데이터를 처리하기 위한 유용한 기능들을 제공 - 순열과 조합(3) heapq : 힙 자료구조를 제공 - 우선순위 큐 기능 구현(4) bisect : 이진 탐색 (binary search) 기능 제공(5) collections : 덱 (deque), 카운터 (counter)(6) math : 필수적인 수학 기능 (팩토리얼, 제곱근, GCD, 삼각함수 관련, 파이)