숫자형 리스트를 단일 값으로 병합하기 a = [1, 2, 3, 4, 5]처럼 숫자형으로 이루어진 리스트가 있을 때 이를 하나로 합치는 좀 더 우아한 코드를 만들어 보자. >>> ''.join(str(e) for e in a) '12345' 이 방식의 코드는 아무래도 가독성이 떨어지고 영 보기가 좋지 않다. 좀 더 깔끔한 방법은 없을까? >>> ''.join(map(str, a)) '12345' 이 경우 임시 변수 e를 사용하지 않아 깔끔하며, map(str,로 이어지는 부분이 문자열로 변환을 암시하는 듯하여 가독성도 좋다. 코드 크기가 줄어듦은 물론이다. >>> functools.reduce(lambda x, y: 10 * x + y, a, 0) 12345 이런 식으로 처리할 수 있을 것 같다. func..
두 수의 덧셈 문제 문제링크 역순으로 저장된 연결 리스트의 숫자를 더하라 입력 (2 → 4 → 3) + (5 → 6 → 4) 출력 7 → 0 → 8 코드 class ListNode: def __init__(self, x): self.val = x self.next = None class Solution(): def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: root = head = ListNode(0) carry = 0 while l1 or l2 or carry: sum = 0 if l1: sum += l1.val l1 = l1.next if l2: sum += l2.val l2 = l2.next carry, val = divmod(sum..
두 정렬 리스트의 병합 problem 문제링크 정렬되어 있는 두 연결 리스트를 합쳐라 입력 1→2→4 1→3→4 출력 1→1→2→3→4→4 solution 리트코드 정답 class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: if (not l1) or (l2 and l1.val > l2.val): l1, l2 = l2, l1 if l1: l1.next = self.mergeTwoLists(l1.next, l2) return l1 풀이용 코드 class ListNode: def __init__(s..
유니코드와 UTF-8 초기에 문자를 표현하던 대표적인 방식은 ASCⅡ 인코딩 방식으로, 1바이트에 모든 문자를 표현했다. 게다가 1비트는 체크섬으로 제외하여 7비트, 즉 128글자로 문자를 표현했다. 그러다 보니 한글이나 한자 같은 문자는 2개 이상의 특수 문자를 합쳐서 표현하곤 했는데, 당연히 이런 방식은 비정상적이며, 경우에 따라서는 깨지거나 제대로 표현되지 않는 경우가 잦았다. 이런 문제를 해결하기 위해 2~4 바이트의 공간에 여유 있게 문자를 할당하고자 등장한 방식이 바로 유니코드다. 그러나 유니코드 자체는 1바이트로 표현이 가능한 영문자도 2바이트 이상의 공간을 사용하기 때문에 이를 그대로 사용하면 메모리 낭비가 심하고 따라서 이를 가변 길이 문자 인코딩 방식으로 효율적으로 인코딩하는 대표적인 ..
리트코드 Group Anagrams from typing import List import collections class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: anagrams = collections.defaultdict(list) for word in strs: anagrams[''.join(sorted(word))].append(word) print(anagrams) return anagrams.values() if __name__ == '__main__': s = Solution() print(s.groupAnagrams(["eat","tea","tan","ate","nat","bat"])) sorted()는..
re 모듈 sub 함수 정규식과 매치되는 부분을 다른 문자로 바꾸어준다. sub 메서드의 첫 번째 매개변수는 바꿀 문자열이 되고, 두 번째 매개 변수는 대상 문자열이 된다. 그런데 딱 한 번만 바꾸고 싶은 경우도 있다. 이렇게 바꾸기 횟수를 제어하려면 다음과 같이 세 번째 매개변수로 count값을 넘기면 된다. import re s = "A man, a plan, a canal: Panama" s = re.sub('[^0-9a-z]', '', s) # 영어 소문자, 숫자 빼고 나머지 다 없앰. print(s) # s = "manaplanacanalanama" s = "A man, a plan, a canal: Panama" s = re.sub('[^0-9a-z]', '', s, count=1) print..
isalnum 함수 isalnum()는 영문자, 숫자 여부를 판별하는 함수 lower 함수 모두 소문자로 변환한다. class Solution: def isPalindrome(self, s: str) -> bool: strs: Deque = collections.deque() for char in s: if char.isalnum(): #영문자, 숫자 여부를 판별 strs.append(char.lower()) # 모두 소문자 변환 while len(strs) > 1: if strs.popleft() != strs.pop(): return False return True 출처 파이썬 알고리즘 인터뷰 (글 : 박상길 그림 : 정진호) [책만]
typing 모듈 타입 어노테이션을 사용하다 보면 리스트, 사전, 터플, 세트와 같은 파이썬 내장 자료 구조에 대한 타입을 명시해야 할 때가 있습니다. 이럴 때는 typing 모듈에서 제공하는 List, Dict, Tuple, Set를 사용하여 타입 어노테이션을 추가한다. from typing import Deque class Solution: def isPalindrome(self, s: str) -> bool: strs: Deque = collections.deque() for char in s: if char.isalnum(): strs.append(char.lower()) while len(strs) > 1: if strs.popleft() != strs.pop(): return False ret..
제너레이터 제너레이터는 루프의 반복 동작을 제어할 수 있는 루틴 형태를 말한다. 예를 들어 임의의 조건으로 숫자 1억 개를 만들어내 계산하는 프로그램을 작성한다고 가정해보자. 이 경우 제너레이터가 없다면 메모리 어딘가에 만들어낸 숫자 1억 개를 보관하고 있어야 하낟. 그러나 제너레이터를 이용하면, 단순히 제너레이터만 생성해두고 필요할 때 언제든 숫자를 만들어낼 수 있다. 이때 yield 구문을 사용하면 제너레이터를 리턴할 수 있다. 기조느이 함수는 return 구문을 맞닥뜨리면 값을 리턴하고 모든 함수의 동작을 종료한다. 그러나 yield는 제너레이터가 여기까지 실행 중이던 값을 내보낸다는 의미로, 중간 값을 리턴한 다음 함수는 종료되지 않고 계속해서 맨 끝에 도달할 때까지 실행된다. yield의 값을 ..
locals locals()는 로컬 심볼 테이블 딕셔너리를 가져오는 메소드로 업데이트 또한 가능하다. 여기서는 딕셔너리를 가져오는 부분에 집중해 살펴보자면, 로컬에 선언된 모든 변수를 조회할 수 있는 강력한 명령이므로 디버깅에 도움이 된다. 변수명을 일일이 찾아낼 필요 없이 로컬 스코프에 정의된 모든 변수를 출력하기 떄문에 편리하다. import pprint pprint.pprint(locals()) """ {'__annotations__': {}, '__builtins__': , '__cached__': None, '__doc__': None, '__file__': '3.py', '__loader__': , '__name__': '__main__', '__package__': None, '__spec_..
sort + ramda 람다 표현식이란 식별자 없이 실행 가능한 함수를 말하며, 함수 선언 없이도 하나의 식으로 함수를 단순하게 표현할 수 있다. letters = ['let1 art can', 'let2 own kit dig', 'let3 art zero'] letters.sort(key=lambda x : (x.split()[1:], x.split()[0])) # 출력 : ['let1 art can', 'let3 art zero', 'let2 own kit dig'] 식별자를 제외한 문자열 [1:]을 키로 하여 정렬하며, 동일한 경우 후순위로 식별자 [0]를 지정해 정렬되도록, 람다 표현식을 이용해 정렬할 수 있다. 출처 파이썬 알고리즘 인터뷰 (글 : 박상길 그림 : 정진호) [책만]
print 리스트를 출력할 떄는 join()으로 묶어서 처리한다. a = ['A', 'B'] print(' '.join(a)) # A B 다음과 같이 idx와 fruit이 정의되 있을 때 가장 선호되는 print() 방법은 f-string이다. 변수를 뒤에 별도로 부여할 필요 없이 마치 템플릿을 사용하듯 인라인으로 삽입할 수 있어 편리하게 사용할 수 있다. idx = 1 fruit = "Apple" print(f'{idx +1}: {fruit}') # 2: Apple 출처 : 파이썬 알고리즘 인터뷰 (글 : 박상길 그림 : 정진호)
타입 힌트 오류 확인 mypy를 사용하면 타입 힌트에 오류가 없는지 자동으로 확인 할 수 있으므로 이를 통해 수정 할 수 있다. 타입 힌트가 잘못 지정된 코드는 다음과 같이 InCompatible return value type 오류가 발생하므로 확인 후 직접 코드를 수정할 수 있다. $ mypy solution.py 출처 : 파이썬 알고리즘 인터뷰 (글 : 박상길 그림 : 정진호)
카멜 케이스와 스네이크 케이스 카멜 케이스 단어를 대소문자로 구분하여 섞어서 작명하는 방식으로, 자바의 대표적인 표기 방식이기도 하다. 스네이크 케이스 각 단어를 언더스코어로 구분한다. 일반적으로 모두 소문자로 표기하지만 경우에 따라 시작 문자는 대문자로 표기하기도 한다. 연구 결과에 따르면 스네이크 케이스가 카멜 케이스보다 훨씬 더 인지하기 쉽다고 한다. 파이썬은 PEP8을 통해 스네이크 케이스 방식의 네이밍 컨벤션을 권장한다. camelCase: int = 1 snake_case: int = 1 네이밍 컨벤션 파이썬의 변수명 네이밍 컨벤션은 자바와 달리 각 단어를 밑줄(_)로 구분하여 표기하는 스네이크 케이스를 따른다. 이는 함수명도 마찬가지다. 특히 파이썬은 파이썬다운 방식에 굉장한 자부심이 있어서..
제네릭 프로그래밍 제네릭이란 파라미터의 타입이 나중에 지어되게 해서 재활용성을 높일 수 있는 프로그래밍 스타일이다. 파이썬은 동적 타이핑 언어이기 때문에 제네릭이 필요 없다. 하지만 동적 타이핑의 장점이자 단점은 얼핏 사용하기엔 매우 편하지만 코드의 복잡도가 높아질수록 혼란을 가중시킨다는 점이다. 타입을 아예 명시하지 않으면 가독성을 낮추고 버그 발생 확률이 높아진다. 따라서 다음과 같이 타입을 명시할 수 있다. from typing import TypeVar T = TypeVar('T') U = TypeVar('U') def are_equal(a: T, b: U) -> bool: return a == b are_equal(10, 10.0) 파이썬은 동적 타이핑 언어지만 이처럼 타입을 명시하게 되면 가독..
Pandas 특징 Easy-to-use data structure and data analysis tools Relational 하거나 labeled data에 대한 쉬운 접근 및 data manipulation 관련 기능 제공 효율적인 연산이 가능한 다차원 array 자료형 제공 Pandas에서 주로 다루는 데이터 테이블 형태의 데이터(주로 SQL table, csv) Time series 데이터 주요기능 결측치(missing data) 처리 간편한 slicing 및 indexing 여러 개의 데이터를 하나로 병합하는 join/merge 그룹화 기능 Pandas vs Numpy Pandas는 Numpy의 기능을 확장한 패키지 1-d array, 2-d array를 각각 Series와 DataFrame이..
Numpy Numpy Array 한 array 객체에는 모두 동일한 타입의 elements들이 포함됨 dtype array 객체에 포함된 elements의 타입을 설명하는 객체 ndim 차원의 수, 축의 수 import numpy as np a = np.array([[0, 1], [5, 6]]) print(a.ndim) # 2 shape 각 차원의 크기를 나타내는 integer들의 tuple tuple 객체의 length는 ndim과 동일함 import numpy as np a = np.array([[0, 1], [5, 6]]) print(a.shape) size 행렬의 모든 원소 갯수 shape의 elements들을 모두 곱한 결과와 같음 import numpy as np a = np.array([[0..
리스트 리스트의 특징 리스트는 여러 데이터 타입이 섞여 있을 수 있다. 리스트 인덱싱 및 슬라이싱 sequence[start_index:end_index:step] : 시퀀스 내에서 start_index와 end_index 사이의 구간에 포함되며, start_index로부터 step 만큼씩 index를 증가시켜 가며 슬라이싱. list1 = [11, 33, 55, 22, 44, 89] print(list[2:6:2]) # 55, 44 print(list[::2]) # 11, 55, 44 리스트 클래스 내장 함수 extend(sequence) : 시퀀스 타입 데이터를 현재 리스트의 뒤에 추가. list object를 expend 하면 liset안에 있는 item 개별로 append. index(item) ..
경사하강법 그래디언트 (편)미분값이다. 최고 값, 최솟 값을 찾기 위해서 그래프의 증감방향으로 점진적으로 접근하는 방법이다. 경사하강법, 경사 상승법 경사 하강법은 Local(범위가 정해진) minimum을 찾는 방법이다. 반대로 경사 상승법은 Local maximum을 찾는 방법이다. 경사 하강법에서 부호만 반대로 하면 경사 상승법 적용이 가능하다. 경사하강법 현재 x 값의 미분값(기울기)에 따라 기울기가 음수이면 x 값을 양의 방향으로 이동하고, 기울기가 양수이면 x 값을 음의 방향으로 이동한다. 경사상승법 현재 x 값의 미분값(기울기)에 따라 기울기가 음수이면 x 값을 음의 방향으로 이동하고, 기울기가 양수이면 x 값을 양의 방향으로 이동한다. 그래디언트 계산하기 sum of squares 최저점 ..
선형대수 벡터 유한차원공간에 존재하는 점으로 표현한다. ex) (키, 몸무게, 나이), (국어점수, 수학점수, 영어점수) typing 모듈 타입에 대한 힌트(주석)를 IDE등의 써드파티 등에 주기 위한 용도이다. 단, 파이썬 인터프리터는 주어진 힌트를 강제하지 않는다. 함수주석 함수의 매개변수와 반환값에 주석작성이 가능하다 강제성이 없어 무시하고 사용도 가능하다. 콜론(:)을 사용해 매개변수에 할당되어야 하는 타입을 할당하고, 화살표를 사용해 반환값에 할당되어야 하는 형식을 할당한다. def func(a: str, b: float = 3.5) -> int: return a+b value = func(3) print(value) 벡터의 연산 [1,2] + [2,1] = [1+2, 2+1] = [3, 3] ..
simple line chart from matplotlib import pyplot as plt years = [1950, 1960, 1970, 1980, 1990, 2000, 2010] gdp = [300.2, 543.3, 1075.9, 2862.5, 5979.6, 10289.7, 14958.3] # fixme create a line chart, years on x-axis, gdp on plt.plot(years, gdp, color='green', marker='o', linestyle='solid') plt.title("Nominal GDP") # fixme add a label to the y-axis plt.ylabel("Billions of $") # fixme save the file ..
all all(x)는 반복 가능한(iterable) 자료형 x를 입력 인수로 받으며 이 x의 요소가 모두 참이면 True, 거짓이 하나라도 있으면 False를 돌려준다. (반복 가능한 자료형의 예 : 리스트, 튜플, 문자열, 딕셔너리, 집합) all([1, 2, 3]) // True all([1, 2, 3, 0]) // False all([]) // True all의 입력 인수가 빈 값인 경우에는 True를 리턴 any any(x)는 반복 가능한(iterable)자료형 x를 입력 인수로 받으며 이 x의 요소 중 하나라도 참이 있으면 True를 돌려주고, x가 모두 거짓일 때에만 False를 돌려준다. all(x)의 반대이다. any([1, 2, 3, 0]) // True any([0, ""]) // Fa..