이 포스트는 알고리즘을 풀면서 Python
언어의 장점을 극대화해서 효율적으로 해결하기 위해서 학습한 내용을 모아놓은 포스트입니다
print(a // b, a % b)
==>
print(*divmod(a, b))
무조건 divmod
를 사용하는 게 좋은 방법은 아닙니다.
divmod
는 작은 숫자를 다룰 때는 a//b, a%b
보다 느립니다. 대신, 큰 숫자를 다룰 때는 더 빠릅니다
string
을 10진법 숫자로 변환하기int(x, base=진법)
# ex)
num = '3212'
base = 5
ans = int(num, base)
s = '가나다라'
n = 7
s.ljust(n) # n의 크기 안에서 좌측 정렬
s.center(n) # n의 크기 안에서 가운데 정렬
s.rjust(n) # n의 크기 안에서 오른쪽 정렬
파이썬에서는 알파벳과 숫자 모음을 상수로 정의해놓았습니다
import string # import 하셔야 합니다
string.ascii_lowercase # 소문자 알파벳 모음 abcdefghijklmnopqrstuvwxyz
string.ascii_uppercase # 대문자 알파벳 모음 ABCDEFGHIJKLMNOPQRSTUVWXYZ
string.ascii_letters # 대소문자 모음 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
string.digits # 숫자 모음 0123456789
list1 = [3, 2, 5, 1]
list2 = sorted(list1)
ZIP
함수잘 이용하면 복잡한 코드 없이 효율적으로 코드를 짤 수 있게 해주는 함수이다
zip(*iterables)
는 각 iterable
의 요소들을 모으는 이터레이터를 만든다
사용 예 1
mylist = [1, 2, 3]
new_list = [40, 50, 60]
for i in zip(mylist, new_list):
print (i)
(1, 40)
(2, 50)
(3, 60)
사용 예 2 - 여러 개의 iterable
을 순회할 때
list1 = [1, 2, 3, 4]
list2 = [100, 120, 30, 300]
list3 = [392, 2, 33, 1]
answer = []
for number1, number2, number3 in zip(list1, list2, list3):
print(number1, number2, number3)
print(number1 + number2 + number3)
print("===========")
1 100 392
493
===========
2 120 2
124
===========
3 30 33
66
===========
4 300 1
305
===========
사용 예제 3 - key 리스트와 Value 리스트로 딕셔너리 생성하기
animals = ['cat', 'dog', 'lion']
sounds = ['meow', 'woof', 'roar']
answer = dict(zip(animals, sounds)) # {'cat': 'meow', 'dog': 'woof', 'lion': 'roar'}
zip
- 2차원 리스트 뒤집기mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist)))
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
*mylist
를 하면 안의 원소들인 리스트 인 [1, 2, 3], [4, 5, 6], [7, 8, 9]
가 값으로 나오는데 그 값들을 zip
으로 묶어서 map
함수로 다시 리스트로 묶어주고 그 리스트들을 다시 하나의 리스트로 묶어서 반환해준다
zip
- i번째 원소와 i+i번째 원소보통의 풀이는 이중 for
문을 사용해서 해결할 것이다
def solution(mylist):
answer = []
for i in range(len(mylist)-1):
answer.append(abs(mylist[i] - mylist[i+1]))
return answer
if __name__ == '__main__':
mylist = [83, 48, 13, 4, 71, 11]
print(solution(mylist))
하지만 zip
함수를 이용하면 한번의 for
문으로 해결할 수 있다
def solution(mylist):
answer = []
for number1, number2 in zip(mylist, mylist[1:]):
answer.append(abs(number1 - number2))
return answer
if __name__ == '__main__':
mylist = [83, 48, 13, 4, 71, 11]
print(solution(mylist))
mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist[::-1])))
mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist)))[::-1]
map
기능을 활용하지 않으면 for
문을 사용해서 풀 것이다
list1 = ['1', '100', '33']
list2 = []
for value in list1:
list2.append(int(value))
==>
list1 = ['1', '100', '33']
list2 = list(map(int, list1))
my_list = ['1', '100', '33']
answer = ''.join(my_list)
예시) 두 스트링 'ABCD', 'xy' 의 곱집합은 Ax Ay Bx By Cx Cy Dx Dy 입니다.
itertools.product
를 이용하면, for 문을 사용하지 않고도 곱집합을 구할 수 있습니다.
import itertools # import 필요
iterable1 = 'ABCD'
iterable2 = 'xy'
iterable3 = '1234'
print(list(itertools.product(iterable1, iterable2, iterable3)))
my_list = [[1, 2], [3, 4], [5, 6]]
# 방법 1 - sum 함수
answer = sum(my_list, [])
# 방법 2 - itertools.chain
import itertools
list(itertools.chain.from_iterable(my_list))
# 방법 3 - itertools와 unpacking
import itertools
list(itertools.chain(*my_list))
# 방법 4 - list comprehension 이용
[element for array in my_list for element in array]
# 방법 5 - reduce 함수 이용 1
from functools import reduce
list(reduce(lambda x, y: x+y, my_list))
# 방법 6 - reduce 함수 이용 2
from functools import reduce
import operator
list(reduce(operator.add, my_list))
import itertools
pool = ['A', 'B', 'C']
print(list(map(''.join, itertools.permutations(pool)))) # 3개의 원소로 순열 만들기
print(list(map(''.join, itertools.permutations(pool, 2)))) # 2개의 원소로 순열 만들기
l = [1,2,3]
for i in combinations(l,2):
print(i)
'''
출력 결과:
(1, 2)
(1, 3)
(2, 3)
'''
from itertools import combinations_with_replacement
l = ['A', 'B', 'C']
for i in combinations_with_replacement(l,2):
print(i)
'''
출력결과:
('A', 'A')
('A', 'B')
('A', 'C')
('B', 'B')
('B', 'C')
('C', 'C')
'''
Counter
- 가장 많이 등장하는 알파벳 찾기알고리즘 문제를 풀다 보면 어떤 원소 x가 주어진 시퀀스타입에 몇 번이나 등장하는지 세야 할 때가 있습니다. 이 때 사용하면 좋은 클래스가 바로 Counter
입니다
import collections
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 7, 9, 1, 2, 3, 3, 5, 2, 6, 8, 9, 0, 1, 1, 4, 7, 0]
answer = collections.Counter(my_list)
print(answer)
# Counter({1: 4, 2: 3, 3: 3, 7: 3, 4: 2, 5: 2, 6: 2, 8: 2, 9: 2, 0: 2})
print(answer[1]) # = 4
print(answer[3]) # = 3
print(answer[100]) # = 0
사용법에 대해서 궁금할 수 있을거라 생각합니다 문제 하나를 같이 풀어보면 좀 더 와닿을 거라 생각됩니다
이 문제에는 표준 입력으로 문자열, mystr이 주어집니다.
mystr에서 가장 많이 등장하는 알파벳만을 사전 순으로 출력하는 코드를 작성해주세요.
input | output |
---|---|
'aab' | 'a' |
'dfdefdgf' | 'df' |
'bbaa' | 'ab' |
import collections # import
my_list = input().strip() # 입력값 초기화
# 들어온 string 값의 각 알파벳의 Counter를 구해준다
answer = collections.Counter(my_list)
# 딕셔너리 형태의 answer에서 values(나온 횟수)만 모아서 리스트를 만든다
values = [i for i in answer.values()]
# 내림차순으로 정렬해준다
values.sort(reverse=True)
# 가장 자주 나온 횟수를 저장해준다
big = values[0]
# 딕셔너리 형태의 answer를 for문으로 k(키), v(값)으로 돌면서
# v(값) == 나온 횟수가 big(가장 자주 나온 횟수)랑 같은 k(키) == 알파벳을 찾아서 리스트에 담는다
result = [k for k, v in answer.items() if big == v]
# join 함수로 나온 알파벳들을 묶어준다
result = ''.join(sorted(result))
print(result)
List comprehension
의 if
문 - for
문과 if
문을 한번에mylist = [3, 2, 6, 7]
answer = [number**2 for number in mylist if number % 2 == 0]
flag
변수를 활용하는 대신 for-else
문 사용하기알고리즘을 풀 때, 어떤 조건에서 for
문을 돌고 해당하면 flag
변수의 값을 True
로 변환하고 그렇지 않으면 False
로 지정해서 후처리를 하곤 한다
하지만 for-else
문법을 사용하면 더 간단하게 처리할 수 있다
flag
변수를 사용해서 풀 때
import math
if __name__ == '__main__':
numbers = [int(input()) for _ in range(5)]
multiplied = 1
flag = True
for number in numbers:
multiplied *= number
if math.sqrt(multiplied) == int(math.sqrt(multiplied)):
flag = False
print('found')
break
if flag:
print('not found')
for-else
로 풀 때
import math
if __name__ == '__main__':
numbers = [int(input()) for _ in range(5)]
multiplied = 1
for number in numbers:
multiplied *= number
if math.sqrt(multiplied) == int(math.sqrt(multiplied)):
print('found')
break
# for문을 다 돌았을 때 조건에 해당하지 않으면 else를 실행
else:
print('not found')
a = 3
b = 'abc'
a, b = b, a
binary search
- 이진 탐색하기파이썬에서는 이진 탐색 알고리즘을 구현한 모듈이 있습니다
import bisect
mylist = [1, 2, 3, 7, 9, 11, 33]
print(bisect.bisect(mylist, 3))
파이썬에서는 __str__
메소드를 사용해 class 내부에서 출력 format을 지정할 수 있습니다.
class Coord(object):
def __init__ (self, x, y):
self.x, self.y = x, y
def __str__ (self):
return '({}, {})'.format(self.x, self.y)
point = Coord(1, 2)
print(point)
'''
(1, 2)
'''
inf
- 가장 큰 수inf
는 어떤 숫자와 비교해도 무조건 크다고 판정됩니다.
무한수는 float
형에만 적용 가능합니다. int
형에는 적용 불가능합니다.
min_val = float('inf')
min_val > 10000000000
# 음수 기호를 붙여서 가장 작은 값도 가능합니다
max_val = float('-inf')
파이썬의 with - as
구문을 이용하면 코드를 더 간결하게 짤 수 있습니다. 코드를 아래와 같이 쓰면 다음과 같은 장점이 있습니다.
close
하지 않아도 됩니다: with - as
블록이 종료되면 파일이 자동으로 close
됩니다.readlines
가 EOF
까지만 읽으므로, while
문 안에서 EOF
를 체크할 필요가 없습니다.with open('myfile.txt') as file:
for line in file.readlines():
print(line.strip().split('\t'))