Python답게

Gyeongjae Ham·2023년 5월 18일
0
post-thumbnail

이 포스트는 알고리즘을 풀면서 Python 언어의 장점을 극대화해서 효율적으로 해결하기 위해서 학습한 내용을 모아놓은 포스트입니다

몫과 나머지

print(a // b, a % b)
==>
print(*divmod(a, b))

무조건 divmod를 사용하는 게 좋은 방법은 아닙니다.

divmod는 작은 숫자를 다룰 때는 a//b, a%b 보다 느립니다. 대신, 큰 숫자를 다룰 때는 더 빠릅니다

n진법으로 표기된 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))

2차원 배열 회전하기

  1. 시계 방향으로 90도 회전
mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist[::-1])))
  1. 반시계 방향으로 90도 회전
mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist)))[::-1]

map - 모든 멤버의 type 변환하기

map 기능을 활용하지 않으면 for문을 사용해서 풀 것이다

list1 = ['1', '100', '33']
list2 = []
for value in list1:
    list2.append(int(value))

==>

list1 = ['1', '100', '33']
list2 = list(map(int, list1))

join - 멤버를 하나로 이어 붙이기

my_list = ['1', '100', '33']
answer = ''.join(my_list)

product - 곱집합(cartesian product) 구하기

예시) 두 스트링 '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)))

2차원 리스트를 1차원 리스트로 만드는 방법들

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))

순열과 조합 - permutations, combinations

순열 - permutations

import itertools

pool = ['A', 'B', 'C']
print(list(map(''.join, itertools.permutations(pool)))) # 3개의 원소로 순열 만들기
print(list(map(''.join, itertools.permutations(pool, 2)))) # 2개의 원소로 순열 만들기

조합 - combinations

l = [1,2,3]

for i in combinations(l,2):
    print(i)

'''
출력 결과:
(1, 2)
(1, 3)
(2, 3)
'''

조합(중복 허용) - combinations_with_replacement

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에서 가장 많이 등장하는 알파벳만을 사전 순으로 출력하는 코드를 작성해주세요.

inputoutput
'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 comprehensionif문 - 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 구문을 이용하면 코드를 더 간결하게 짤 수 있습니다. 코드를 아래와 같이 쓰면 다음과 같은 장점이 있습니다.

  1. 파일을 close 하지 않아도 됩니다: with - as 블록이 종료되면 파일이 자동으로 close 됩니다.
  2. readlinesEOF까지만 읽으므로, while 문 안에서 EOF를 체크할 필요가 없습니다.
with open('myfile.txt') as file:
    for line in file.readlines():
        print(line.strip().split('\t'))
profile
Always be happy 😀

0개의 댓글

관련 채용 정보