ํ์ด์ฌ PS 1๋จ๊ณ: ๊ธฐ์ด ๋ฌธ๋ฒ ์์ ์ ๋ณต#
๐ฅ 1. ์
์ถ๋ ฅ ์ฒ๋ฆฌ#
๊ธฐ๋ณธ ์
๋ ฅ#
# ํ ์ค ์
๋ ฅ
n = int(input())
s = input()
a, b = map(int, input().split())
# ์ฌ๋ฌ ์ค ์
๋ ฅ
arr = []
for _ in range(n):
    arr.append(int(input()))
# ๋ฆฌ์คํธ ํ๋ฒ์ ์
๋ ฅ
numbers = list(map(int, input().split()))
๋น ๋ฅธ ์
๋ ฅ (sys.stdin)#
import sys
input = sys.stdin.readline
# ์ฃผ์: readline()์ ๊ฐํ๋ฌธ์๋ฅผ ํฌํจํ๋ฏ๋ก
n = int(input())  # ์ซ์๋ ์๋์ผ๋ก ๊ฐํ๋ฌธ์ ์ ๊ฑฐ
s = input().strip()  # ๋ฌธ์์ด์ strip() ํ์
์ถ๋ ฅ ์ต์ ํ#
# ๊ธฐ๋ณธ ์ถ๋ ฅ
print(result)
print(a, b, c)  # ๊ณต๋ฐฑ์ผ๋ก ๊ตฌ๋ถ
print(a, b, c, sep=', ')  # ๊ตฌ๋ถ์ ์ง์ 
# ๋น ๋ฅธ ์ถ๋ ฅ (๋๋ ๋ฐ์ดํฐ)
import sys
print = sys.stdout.write
# ์ฌ์ฉ ์ ๊ฐํ๋ฌธ์ ์ง์  ์ถ๊ฐ ํ์: print(str(result) + '\n')
# ์ฌ๋ฌ ์ค ์ถ๋ ฅ
results = []
for i in range(n):
    results.append(str(i))
print('\n'.join(results))
๐จ ์
์ถ๋ ฅ ์ฃผ์ ํจ์ #
input().split()์ ๊ฒฐ๊ณผ๋ ๋ฌธ์์ด ๋ฆฌ์คํธ 
sys.stdin.readline()์ ๊ฐํ๋ฌธ์ ํฌํจ 
- ๋๋ ์ถ๋ ฅ ์ 
print() ์ฌ๋ฌ ๋ฒ๋ณด๋ค ํ ๋ฒ์ ์ถ๋ ฅ์ด ๋น ๋ฆ 
๐ค 2. ๋ฌธ์์ด(String) ํต์ฌ ๋ฉ์๋#
๊ธฐ๋ณธ ์กฐ์#
s = "Hello World"
# ๊ธธ์ด์ ์ธ๋ฑ์ฑ
len(s)  # 11
s[0]    # 'H'
s[-1]   # 'd'
s[1:5]  # 'ello'
# ๋์๋ฌธ์ ๋ณํ
s.upper()      # 'HELLO WORLD'
s.lower()      # 'hello world'
s.capitalize() # 'Hello world'
s.title()      # 'Hello World'
# ๊ณต๋ฐฑ ์ฒ๋ฆฌ
s.strip()      # ์์ชฝ ๊ณต๋ฐฑ ์ ๊ฑฐ
s.lstrip()     # ์ผ์ชฝ ๊ณต๋ฐฑ ์ ๊ฑฐ
s.rstrip()     # ์ค๋ฅธ์ชฝ ๊ณต๋ฐฑ ์ ๊ฑฐ
๊ฒ์๊ณผ ๋ถํ #
s = "hello world hello"
# ๊ฒ์
s.find('world')     # 6 (์ฒซ ๋ฒ์งธ ์ธ๋ฑ์ค)
s.find('xyz')       # -1 (์์)
s.index('world')    # 6 (์์ผ๋ฉด ValueError)
s.count('hello')    # 2
# ๋ถํ ๊ณผ ๊ฒฐํฉ
s.split()           # ['hello', 'world', 'hello']
s.split('l')        # ['he', '', 'o wor', 'd he', '', 'o']
' '.join(['a', 'b', 'c'])  # 'a b c'
# ์นํ
s.replace('hello', 'hi')  # 'hi world hi'
s.replace('l', 'L', 2)    # 'heLLo world hello' (์ต๋ 2๊ฐ๋ง)
ํ๋ณ ๋ฉ์๋#
# ๋ฌธ์ ์ข
๋ฅ ํ๋ณ
'123'.isdigit()      # True
'abc'.isalpha()      # True
'abc123'.isalnum()   # True
'   '.isspace()      # True
# ํจํด ํ๋ณ
'hello'.startswith('he')  # True
'world'.endswith('ld')    # True
๐จ ๋ฌธ์์ด ์ฃผ์ ํจ์ #
- ๋ฌธ์์ด์ ๋ถ๋ณ(immutable) โ ์์  ์ ์ ๊ฐ์ฒด ์์ฑ
 
split()๊ณผ split(' ')๋ ๋ค๋ฆ (์ฐ์ ๊ณต๋ฐฑ ์ฒ๋ฆฌ ๋ฐฉ์) 
- ๋๋ ๋ฌธ์์ด ์ฐ๊ฒฐ ์ 
''.join(list)๊ฐ + ์ฐ์ฐ๋ณด๋ค ๋น ๋ฆ 
๐ 3. ๋ฆฌ์คํธ(List) ํต์ฌ ๋ฉ์๋#
๊ธฐ๋ณธ ์์ฑ๊ณผ ์กฐ์#
# ์์ฑ
arr = [1, 2, 3, 4, 5]
arr2 = [0] * n  # ํฌ๊ธฐ n์ธ 0์ผ๋ก ์ด๊ธฐํ๋ ๋ฆฌ์คํธ
matrix = [[0] * m for _ in range(n)]  # 2์ฐจ์ ๋ฆฌ์คํธ
# ์ถ๊ฐ์ ์ญ์ 
arr.append(6)        # ๋์ ์ถ๊ฐ: [1,2,3,4,5,6]
arr.insert(0, 0)     # ์ธ๋ฑ์ค 0์ ์ฝ์
: [0,1,2,3,4,5,6]
arr.extend([7, 8])   # ๋ฆฌ์คํธ ํ์ฅ: [0,1,2,3,4,5,6,7,8]
arr.pop()            # ๋ง์ง๋ง ์์ ์ ๊ฑฐ ํ ๋ฐํ: 8
arr.pop(0)           # ์ธ๋ฑ์ค 0 ์์ ์ ๊ฑฐ ํ ๋ฐํ: 0
arr.remove(3)        # ๊ฐ 3์ธ ์ฒซ ๋ฒ์งธ ์์ ์ ๊ฑฐ
์ ๋ ฌ๊ณผ ๊ฒ์#
arr = [3, 1, 4, 1, 5]
# ์ ๋ ฌ
arr.sort()                    # ์๋ณธ ์์ : [1,1,3,4,5]
sorted_arr = sorted(arr)      # ์ ๋ฆฌ์คํธ ๋ฐํ
arr.sort(reverse=True)        # ๋ด๋ฆผ์ฐจ์: [5,4,3,1,1]
arr.sort(key=len)            # ๋ฌธ์์ด ๊ธธ์ด๋ก ์ ๋ ฌ
# ๊ฒ์
arr.index(4)         # 4์ ์ธ๋ฑ์ค: 2
arr.count(1)         # 1์ ๊ฐ์: 2
4 in arr            # True
์ฌ๋ผ์ด์ฑ๊ณผ ๋ณต์ฌ#
arr = [1, 2, 3, 4, 5]
# ์ฌ๋ผ์ด์ฑ
arr[1:4]        # [2, 3, 4]
arr[:3]         # [1, 2, 3]
arr[2:]         # [3, 4, 5]
arr[::2]        # [1, 3, 5] (2์นธ์ฉ)
arr[::-1]       # [5, 4, 3, 2, 1] (๋ค์ง๊ธฐ)
# ๋ณต์ฌ
shallow = arr[:]           # ์์ ๋ณต์ฌ
deep = [x for x in arr]    # ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์
์ผ๋ก ๋ณต์ฌ
import copy
deep_copy = copy.deepcopy(arr)  # ๊น์ ๋ณต์ฌ
๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์
#
# ๊ธฐ๋ณธ ํํ
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
# ์ค์ฒฉ ๋ฃจํ
pairs = [(x, y) for x in range(3) for y in range(3)]
# ์กฐ๊ฑด๋ถ ํํ์
result = [x if x > 0 else 0 for x in [-1, 2, -3, 4]]
๐จ ๋ฆฌ์คํธ ์ฃผ์ ํจ์ #
[[0] * m] * n์ ๊ฐ์ ๋ฆฌ์คํธ ๊ฐ์ฒด๋ฅผ n๋ฒ ์ฐธ์กฐ (์์ ๋ณต์ฌ) 
sort()๋ ์๋ณธ ์์ , sorted()๋ ์ ๋ฆฌ์คํธ ๋ฐํ 
- ๋ฆฌ์คํธ ์ค๊ฐ ์ฝ์
/์ญ์ ๋ O(n) ์๊ฐ๋ณต์ก๋
 
๐ 4. ๋์
๋๋ฆฌ(Dictionary) ํต์ฌ ๋ฉ์๋#
๊ธฐ๋ณธ ์กฐ์#
# ์์ฑ
d = {'a': 1, 'b': 2}
d2 = dict(a=1, b=2)
d3 = dict([('a', 1), ('b', 2)])
# ์ ๊ทผ๊ณผ ์์ 
d['a']              # 1
d.get('c', 0)       # ํค 'c'๊ฐ ์์ผ๋ฉด 0 ๋ฐํ
d['c'] = 3          # ์ ํค-๊ฐ ์ถ๊ฐ
d.update({'d': 4, 'e': 5})  # ์ฌ๋ฌ ํค-๊ฐ ์ถ๊ฐ
์กฐํ์ ์ํ#
d = {'a': 1, 'b': 2, 'c': 3}
# ํค, ๊ฐ, ํญ๋ชฉ ์กฐํ
d.keys()           # dict_keys(['a', 'b', 'c'])
d.values()         # dict_values([1, 2, 3])
d.items()          # dict_items([('a', 1), ('b', 2), ('c', 3)])
# ์ํ
for key in d:              # ํค ์ํ
    print(key, d[key])
for key, value in d.items():  # ํค-๊ฐ ์ ์ํ
    print(key, value)
# ์กด์ฌ ํ์ธ
'a' in d           # True (ํค ์กด์ฌ ํ์ธ)
1 in d.values()    # True (๊ฐ ์กด์ฌ ํ์ธ)
๊ณ ๊ธ ํ์ฉ#
# defaultdict ํ์ฉ
from collections import defaultdict
dd = defaultdict(int)  # ๊ธฐ๋ณธ๊ฐ 0
dd = defaultdict(list) # ๊ธฐ๋ณธ๊ฐ ๋น ๋ฆฌ์คํธ
# Counter ํ์ฉ
from collections import Counter
counter = Counter([1, 2, 2, 3, 3, 3])
# Counter({3: 3, 2: 2, 1: 1})
counter.most_common(2)  # [(3, 3), (2, 2)]
# ๋์
๋๋ฆฌ ์ปดํ๋ฆฌํจ์
squares = {x: x**2 for x in range(5)}
filtered = {k: v for k, v in d.items() if v > 1}
๐จ ๋์
๋๋ฆฌ ์ฃผ์ ํจ์ #
- ์กด์ฌํ์ง ์๋ ํค ์ ๊ทผ ์ KeyError โ 
get() ์ฌ์ฉ ๊ถ์ฅ 
- Python 3.7+ ์์ ๋์
๋๋ฆฌ๋ ์ฝ์
 ์์ ๋ณด์ฅ
 
- ์ํ ์ค ๋์
๋๋ฆฌ ํฌ๊ธฐ ๋ณ๊ฒฝ ์ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ
 
๐ข 5. ์งํฉ(Set) ํต์ฌ ๋ฉ์๋#
๊ธฐ๋ณธ ์กฐ์#
# ์์ฑ
s = {1, 2, 3, 4, 5}
s2 = set([1, 2, 2, 3, 3])  # {1, 2, 3} (์ค๋ณต ์ ๊ฑฐ)
empty_set = set()          # ๋น ์งํฉ ({}๋ ๋์
๋๋ฆฌ)
# ์ถ๊ฐ์ ์ ๊ฑฐ
s.add(6)           # ์์ ์ถ๊ฐ
s.update([7, 8])   # ์ฌ๋ฌ ์์ ์ถ๊ฐ
s.remove(5)        # ์์ ์ ๊ฑฐ (์์ผ๋ฉด KeyError)
s.discard(5)       # ์์ ์ ๊ฑฐ (์์ด๋ ์ค๋ฅ ์์)
s.pop()            # ์์ ์์ ์ ๊ฑฐ ํ ๋ฐํ
s.clear()          # ๋ชจ๋  ์์ ์ ๊ฑฐ
์งํฉ ์ฐ์ฐ#
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# ํฉ์งํฉ
a | b              # {1, 2, 3, 4, 5, 6}
a.union(b)
# ๊ต์งํฉ
a & b              # {3, 4}
a.intersection(b)
# ์ฐจ์งํฉ
a - b              # {1, 2}
a.difference(b)
# ๋์นญ์ฐจ์งํฉ
a ^ b              # {1, 2, 5, 6}
a.symmetric_difference(b)
# ๋ถ๋ถ์งํฉ ํ๋ณ
{1, 2}.issubset({1, 2, 3})     # True
{1, 2, 3}.issuperset({1, 2})   # True
๐จ ์งํฉ ์ฃผ์ ํจ์ #
- ๋น ์งํฉ์ 
set(), {}๋ ๋น ๋์
๋๋ฆฌ 
- ์งํฉ์ ์์๊ฐ ์์ โ ์ธ๋ฑ์ฑ ๋ถ๊ฐ
 
- ํด์ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ง ์ ์ฅ ๊ฐ๋ฅ (list๋ ๋ถ๊ฐ, tuple์ ๊ฐ๋ฅ)
 
๐ 6. ์กฐ๊ฑด๋ฌธ๊ณผ ๋ฐ๋ณต๋ฌธ ๊ณ ๊ธ ํ์ฉ#
์กฐ๊ฑด๋ฌธ ์ต์ ํ#
# ์ผํญ ์ฐ์ฐ์
result = value if condition else default
# ๋ค์ค ์กฐ๊ฑด
if a < b < c:  # a < b and b < c์ ๋์ผ
    pass
# in ์ฐ์ฐ์ ํ์ฉ
if x in [1, 2, 3, 4, 5]:  # ๋ฆฌ์คํธ๋ณด๋ค ์งํฉ์ด ๋น ๋ฆ
if x in {1, 2, 3, 4, 5}:  # O(1) vs O(n)
๋ฐ๋ณต๋ฌธ ํจํด#
# enumerate๋ก ์ธ๋ฑ์ค์ ๊ฐ ๋์ ์ํ
for i, value in enumerate(arr):
    print(f"Index {i}: {value}")
# zip์ผ๋ก ์ฌ๋ฌ ๋ฆฌ์คํธ ๋์ ์ํ
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")
# range ํ์ฉ
for i in range(10):        # 0~9
for i in range(1, 11):     # 1~10
for i in range(0, 10, 2):  # 0,2,4,6,8
# ์ญ์ ๋ฐ๋ณต
for i in range(n-1, -1, -1):  # n-1๋ถํฐ 0๊น์ง
for i in reversed(range(n)):   # ์์ ๋์ผ
๋ฐ๋ณต ์ ์ด#
# break์ continue
for i in range(10):
    if i == 3:
        continue  # 3์ ๊ฑด๋๋ฐ๊ธฐ
    if i == 7:
        break     # 7์์ ์ข
๋ฃ
    print(i)
# else์  ํ์ฉ (break๋ก ์ข
๋ฃ๋์ง ์์์ ๋๋ง ์คํ)
for i in range(5):
    if i == 10:  # ์ด ์กฐ๊ฑด์ ๋ง์กฑ๋์ง ์์
        break
else:
    print("๋ฐ๋ณต๋ฌธ์ด ์์ ํ ์ข
๋ฃ๋จ")  # ์คํ๋จ
โก 7. ํจ์์ ๋๋ค ํํ์#
ํจ์ ์ ์์ ํ์ฉ#
# ๊ธฐ๋ณธ ํจ์
def gcd(a, b):
    while b:
        a, b = b, a % b
    return a
# ๊ธฐ๋ณธ๊ฐ ๋งค๊ฐ๋ณ์
def power(base, exp=2):
    return base ** exp
# ๊ฐ๋ณ ์ธ์
def sum_all(*args):
    return sum(args)
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")
๋๋ค ํํ์#
# ๊ธฐ๋ณธ ๋๋ค
square = lambda x: x ** 2
add = lambda x, y: x + y
# ์ ๋ ฌ์์ ๋๋ค ํ์ฉ
students = [('Alice', 85), ('Bob', 90), ('Charlie', 78)]
students.sort(key=lambda x: x[1])  # ์ ์๋ก ์ ๋ ฌ
# map, filter, reduce์ ํจ๊ป
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))
from functools import reduce
product = reduce(lambda x, y: x * y, numbers)
๋ด์ฅ ํจ์ ํ์ฉ#
# ์ํ ํจ์
abs(-5)          # 5
min(1, 2, 3)     # 1
max([1, 2, 3])   # 3
sum([1, 2, 3])   # 6
pow(2, 3)        # 8
# ํ๋ณํ
int('123')       # 123
float('3.14')    # 3.14
str(123)         # '123'
bool(0)          # False
# ์ ์ฉํ ํจ์๋ค
len([1, 2, 3])   # 3
type(123)        # <class 'int'>
isinstance(123, int)  # True
๐ก๏ธ 8. ์์ธ์ฒ๋ฆฌ ๊ธฐ๋ณธ#
try-except ํจํด#
# ๊ธฐ๋ณธ ์์ธ์ฒ๋ฆฌ
try:
    result = 10 / 0
except ZeroDivisionError:
    result = 0
# ์ฌ๋ฌ ์์ธ ์ฒ๋ฆฌ
try:
    value = int(input())
    result = 10 / value
except (ValueError, ZeroDivisionError) as e:
    print(f"์ค๋ฅ ๋ฐ์: {e}")
    result = 0
# else์ finally
try:
    file = open('data.txt', 'r')
except FileNotFoundError:
    print("ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค")
else:
    data = file.read()  # ์์ธ๊ฐ ์์ ๋๋ง ์คํ
finally:
    if 'file' in locals():
        file.close()    # ํญ์ ์คํ
PS์์ ์์ฃผ ์ฌ์ฉํ๋ ์์ธ์ฒ๋ฆฌ#
# ์์ ํ ์
๋ ฅ ์ฒ๋ฆฌ
def safe_input():
    try:
        return int(input())
    except:
        return 0
# ๋ฆฌ์คํธ ์ธ๋ฑ์ค ์์  ์ ๊ทผ
def safe_get(lst, index, default=None):
    try:
        return lst[index]
    except IndexError:
        return default
# ๋์
๋๋ฆฌ ์์  ์ ๊ทผ (get() ๋ฉ์๋๊ฐ ๋ ๋์)
def safe_dict_get(d, key, default=0):
    try:
        return d[key]
    except KeyError:
        return default
๐ 1๋จ๊ณ ํต์ฌ ์์ฝ#
๊ผญ ๊ธฐ์ตํด์ผ ํ  ํจํด#
- ๋น ๋ฅธ ์
์ถ๋ ฅ: 
sys.stdin.readline๊ณผ strip() 
- ๋ฌธ์์ด ์ฒ๋ฆฌ: 
split(), join(), replace() 
- ๋ฆฌ์คํธ ์กฐ์: ์ปดํ๋ฆฌํจ์
, ์ฌ๋ผ์ด์ฑ, 
sort() vs sorted() 
- ๋์
๋๋ฆฌ: 
get(), defaultdict, Counter 
- ์งํฉ ์ฐ์ฐ: ์ค๋ณต ์ ๊ฑฐ, ๊ต์งํฉ/ํฉ์งํฉ
 
- ๋ฐ๋ณต๋ฌธ: 
enumerate(), zip(), range() 
์์ฃผ ํ๋ ์ค์๋ค#
- 2์ฐจ์ ๋ฆฌ์คํธ ์์ฑ ์ ์์ ๋ณต์ฌ
 
- ๋ฌธ์์ด ๋ถ๋ณ์ฑ ๋ฌด์
 
- ๋์
๋๋ฆฌ KeyError
 
- ๋น ์งํฉ์ 
{}๋ก ์์ฑ 
input()๊ณผ sys.stdin.readline()์ ์ฐจ์ด์  
ํ์ด์ฌ PS 2๋จ๊ณ: ๋ค๋ฅธ ์ธ์ด ๊ฐ๋ฐ์๋ฅผ ์ํ ํ์ด์ฌ ํนํ ๊ธฐ๋ฒ#
๐ 1. ๋ถ๊ธฐ๋ฌธ๊ณผ ์ ์ด๋ฌธ - ํ์ด์ฌ๋ง์ ํน์ง#
์กฐ๊ฑด๋ฌธ์ ํ์ด์ฌ์ค๋ฌ์ด ํํ#
์ผํญ ์ฐ์ฐ์ (Ternary Operator)#
# ๊ธฐ๋ณธ ํํ
result = value_if_true if condition else value_if_false
# ์ค์ฉ ์์
max_val = a if a > b else b
status = "pass" if score >= 60 else "fail"
sign = 1 if num >= 0 else -1
# ์ค์ฒฉ ์ผํญ ์ฐ์ฐ์ (๊ถ์ฅํ์ง ์์)
grade = "A" if score >= 90 else "B" if score >= 80 else "C"
# Java/C++ ๊ฐ๋ฐ์ ์ฃผ์: ํ์ด์ฌ์ ? : ์ฐ์ฐ์๊ฐ ์์
# Java: int result = condition ? value1 : value2;
# Python: result = value1 if condition else value2
Truthy/Falsy ๊ฐ ํ์ฉ#
# ํ์ด์ฌ์์ False๋ก ํ๊ฐ๋๋ ๊ฐ๋ค
falsy_values = [False, None, 0, 0.0, '', [], {}, set()]
# ์ค์ฉ์ ์ธ ํ์ฉ
def process_data(data):
    if not data:  # ๋น ๋ฆฌ์คํธ, None, ๋น ๋ฌธ์์ด ๋ชจ๋ ์ฒ๋ฆฌ
        return "No data"
    return f"Processing {len(data)} items"
# ๊ธฐ๋ณธ๊ฐ ์ค์  ํจํด
name = input_name or "Anonymous"  # input_name์ด ๋น ๋ฌธ์์ด์ด๋ฉด "Anonymous"
items = user_items or []          # user_items๊ฐ None์ด๋ฉด ๋น ๋ฆฌ์คํธ
# Java/C++๊ณผ ๋ค๋ฅธ ์ : 0, ๋น ์ปฌ๋ ์
๋ False
# Java: if (list.size() > 0) vs Python: if list:
์ฒด์ด๋ ๋น๊ต (Chained Comparisons)#
# ํ์ด์ฌ๋ง์ ๋
ํนํ ๊ธฐ๋ฅ
age = 25
if 18 <= age < 65:  # Java/C++: if (age >= 18 && age < 65)
    print("Working age")
# ์ฌ๋ฌ ์กฐ๊ฑด ์ฒด์ด๋
if a < b < c < d:  # ๋ชจ๋  ๋ถ๋ฑํธ๊ฐ ์ฑ๋ฆฝํด์ผ ํจ
    print("Ascending order")
# ์ค์ฉ ์์
def is_valid_score(score):
    return 0 <= score <= 100
def is_triangle(a, b, c):
    return a + b > c and b + c > a and c + a > b
# ์ฃผ์: ๋ณต์กํ ์ฒด์ด๋์ ๊ฐ๋
์ฑ์ ํด์น  ์ ์์
match-case ๋ฌธ (Python 3.10+)#
# Switch-case์ ํ์ด์ฌ ๋ฒ์ 
def handle_http_status(status):
    match status:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500 | 502 | 503:  # ์ฌ๋ฌ ๊ฐ ๋งค์นญ
            return "Server Error"
        case status if 400 <= status < 500:  # ์กฐ๊ฑด๋ถ ๋งค์นญ
            return "Client Error"
        case _:  # default case
            return "Unknown Status"
# ํจํด ๋งค์นญ ํ์ฉ
def process_data(data):
    match data:
        case []:  # ๋น ๋ฆฌ์คํธ
            return "Empty list"
        case [x]:  # ์์ ํ๋์ธ ๋ฆฌ์คํธ
            return f"Single item: {x}"
        case [x, y]:  # ์์ ๋ ๊ฐ์ธ ๋ฆฌ์คํธ
            return f"Two items: {x}, {y}"
        case [x, *rest]:  # ์ฒซ ๋ฒ์งธ ์์์ ๋๋จธ์ง
            return f"First: {x}, Rest: {rest}"
        case {"type": "user", "name": name}:  # ๋์
๋๋ฆฌ ํจํด
            return f"User: {name}"
        case _:
            return "Unknown pattern"
๐ 2. ๋ฐ๋ณต๋ฌธ - ํ์ด์ฌ์ ๊ฐ๋ ฅํ ์ดํฐ๋ ์ด์
#
for๋ฌธ์ ๋ค์ํ ํ์ฉ#
# ๊ธฐ๋ณธ for๋ฌธ (Java/C++์ ๋ค๋ฅธ ์ )
# Java: for(int i = 0; i < 10; i++)
# Python: for i in range(10)
# ์ธ๋ฑ์ค์ ๊ฐ ๋์ ์ ๊ทผ
fruits = ['apple', 'banana', 'cherry']
for i, fruit in enumerate(fruits):
    print(f"{i}: {fruit}")
# ์์ ์ธ๋ฑ์ค ์ง์ 
for i, fruit in enumerate(fruits, 1):  # 1๋ถํฐ ์์
    print(f"{i}: {fruit}")
# ์ฌ๋ฌ ์ํ์ค ๋์ ์ํ
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")
# ๊ธธ์ด๊ฐ ๋ค๋ฅธ ์ํ์ค ์ฒ๋ฆฌ
from itertools import zip_longest
for name, age in zip_longest(names, ages, fillvalue="Unknown"):
    print(f"{name}: {age}")
range์ ๊ณ ๊ธ ํ์ฉ#
# ๊ธฐ๋ณธ range ํจํด
for i in range(10):        # 0~9
    pass
for i in range(1, 11):     # 1~10
    pass
for i in range(0, 10, 2):  # 0,2,4,6,8 (step=2)
    pass
# ์ญ์ ๋ฐ๋ณต
for i in range(10, 0, -1):    # 10,9,8,...,1
    pass
for i in reversed(range(10)): # 9,8,7,...,0
    pass
# ์ค์ฉ์ ์ธ ํจํด๋ค
# 2์ฐจ์ ๋ฐฐ์ด ์ํ
matrix = 1,2,3], [4,5,6], [7,8,9">1,2,3], [4,5,6], [7,8,9
for i in range(len(matrix)):
    for j in range(len(matrix[i])):
        print(matrix[i][j])
# ๋ ํ์ด์ฌ์ค๋ฌ์ด ๋ฐฉ๋ฒ
for row in matrix:
    for cell in row:
        print(cell)
# ์ธ๋ฑ์ค๊ฐ ํ์ํ ๊ฒฝ์ฐ
for i, row in enumerate(matrix):
    for j, cell in enumerate(row):
        print(f"matrix[{i}][{j}] = {cell}")
while๋ฌธ๊ณผ ์ ์ด#
# while-else ํจํด (๋ค๋ฅธ ์ธ์ด์ ์๋ ๊ธฐ๋ฅ)
def find_factor(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            print(f"Found factor: {i}")
            break
        i += 1
    else:  # break๋ก ๋น ์ ธ๋์ค์ง ์์์ ๋ ์คํ
        print(f"{n} is prime")
# for-else๋ ๋์ผํ๊ฒ ์๋
def search_item(items, target):
    for item in items:
        if item == target:
            print(f"Found {target}")
            break
    else:
        print(f"{target} not found")
# ๋ฌดํ๋ฃจํ ํจํด
while True:
    user_input = input("Enter command (quit to exit): ")
    if user_input == "quit":
        break
    process_command(user_input)
๐ฌ 3. ์๊ฐ ์ ํ์ค (Syntactic Sugar)#
๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์
์ ๊ณ ๊ธ ํ์ฉ#
# ๊ธฐ๋ณธ ์ปดํ๋ฆฌํจ์
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
# ์ค์ฒฉ ๋ฃจํ ์ปดํ๋ฆฌํจ์
matrix = [[i+j for j in range(3)] for i in range(3)]
# ๊ฒฐ๊ณผ: 0,1,2], [1,2,3], [2,3,4
# ์กฐ๊ฑด๋ถ ํํ์๊ณผ ํจ๊ป
result = [x if x > 0 else 0 for x in [-1, 2, -3, 4]]
# ๋ณต์กํ ์กฐ๊ฑด
filtered = [x for x in range(100) 
           if x % 2 == 0 and x % 3 == 0 and x > 10]
# ์ค์ฒฉ ๋ฆฌ์คํธ ํํํ
nested = 1, 2], [3, 4], [5, 6">1, 2], [3, 4], [5, 6
flattened = [item for sublist in nested for item in sublist]
# ๊ฒฐ๊ณผ: [1, 2, 3, 4, 5, 6]
# ๋ฌธ์์ด ์ฒ๋ฆฌ
words = ["hello", "world", "python"]
lengths = [len(word) for word in words]
capitals = [word.upper() for word in words if len(word) > 4]
๋์
๋๋ฆฌ์ ์งํฉ ์ปดํ๋ฆฌํจ์
#
# ๋์
๋๋ฆฌ ์ปดํ๋ฆฌํจ์
squares_dict = {x: x**2 for x in range(5)}
# ๊ฒฐ๊ณผ: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# ์กฐ๊ฑด๋ถ ๋์
๋๋ฆฌ ์ปดํ๋ฆฌํจ์
word_lengths = {word: len(word) for word in words if len(word) > 3}
# ๋์
๋๋ฆฌ ๋ณํ
original = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {v: k for k, v in original.items()}
# ์งํฉ ์ปดํ๋ฆฌํจ์
unique_lengths = {len(word) for word in words}
# ์ค์ฉ์ ์ธ ์์: ๋จ์ด ๋น๋ ๊ณ์ฐ
text = "hello world hello python world"
word_count = {word: text.split().count(word) for word in set(text.split())}
์ธํจํน๊ณผ ํจํน#
# ๊ธฐ๋ณธ ์ธํจํน
point = (3, 4)
x, y = point
# ํ์ฅ ์ธํจํน (Python 3+)
numbers = [1, 2, 3, 4, 5]
first, *middle, last = numbers  # first=1, middle=[2,3,4], last=5
first, second, *rest = numbers  # first=1, second=2, rest=[3,4,5]
# ํจ์ ์ธ์ ์ธํจํน
def greet(name, age, city):
    print(f"Hello {name}, {age} years old from {city}")
person = ("Alice", 25, "Seoul")
greet(*person)  # ํํ ์ธํจํน
person_dict = {"name": "Bob", "age": 30, "city": "Busan"}
greet(**person_dict)  # ๋์
๋๋ฆฌ ์ธํจํน
# ๋ณ์ ๊ตํ
a, b = b, a  # Java/C++: temp = a; a = b; b = temp;
# ์ฌ๋ฌ ๋ณ์ ๋์ ํ ๋น
a = b = c = 0
x, y, z = 1, 2, 3
Walrus ์ฐ์ฐ์ (:=) - Python 3.8+#
# ํ ๋น๊ณผ ๋์์ ์กฐ๊ฑด ๊ฒ์ฌ
if (n := len(some_list)) > 10:
    print(f"List is too long ({n} elements)")
# while ๋ฃจํ์์ ์ ์ฉ
while (line := input("Enter something: ")) != "quit":
    print(f"You entered: {line}")
# ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์
์์ ์ค๋ณต ๊ณ์ฐ ๋ฐฉ์ง
# ๋์ ์: expensive_function์ด ๋ ๋ฒ ํธ์ถ๋จ
results = [expensive_function(x) for x in data if expensive_function(x) > 0]
# ์ข์ ์: walrus ์ฐ์ฐ์๋ก ํ ๋ฒ๋ง ํธ์ถ
results = [y for x in data if (y := expensive_function(x)) > 0]
๐ 4. ํ์ด์ฌ ํน์ง์ ์ธ ๋ถ๋ถ๋ค#
๋์  ํ์ดํ์ ํ์ฉ#
# ๊ฐ์ ๋ณ์์ ๋ค๋ฅธ ํ์
 ํ ๋น ๊ฐ๋ฅ (Java/C++์ ๋ค๋ฆ)
var = 42          # int
var = "hello"     # str
var = [1, 2, 3]   # list
# ํ์
 ํํธ (Python 3.5+) - ์คํ์๋ ์ํฅ ์์
def greet(name: str, age: int) -> str:
    return f"Hello {name}, you are {age} years old"
# isinstance๋ฅผ ์ด์ฉํ ํ์
 ์ฒดํฌ
def process_input(data):
    if isinstance(data, str):
        return data.upper()
    elif isinstance(data, list):
        return len(data)
    elif isinstance(data, (int, float)):  # ์ฌ๋ฌ ํ์
 ์ฒดํฌ
        return data * 2
    else:
        return None
# ๋ ํ์ดํ (Duck Typing)
def print_items(container):
    # ๋ฆฌ์คํธ๋  ํํ์ด๋  ๋ฌธ์์ด์ด๋  ์ดํฐ๋ฌ๋ธ์ด๋ฉด ์๋
    for item in container:
        print(item)
๋ค์ค ํ ๋น๊ณผ ํน์ํ ๊ฐ๋ค#
# None ๊ฐ ์ฒ๋ฆฌ (Java์ null๊ณผ ์ ์ฌํ์ง๋ง ๋ค๋ฆ)
def safe_divide(a, b):
    return a / b if b != 0 else None
result = safe_divide(10, 0)
if result is not None:  # == None์ด ์๋ is๋ฅผ ์ฌ์ฉ
    print(f"Result: {result}")
# ๋ค์ค ํ ๋น์ ํ์ฉ
def get_min_max(numbers):
    return min(numbers), max(numbers)
min_val, max_val = get_min_max([1, 5, 3, 9, 2])
# ์ธ๋์ค์ฝ์ด๋ก ๋ฌด์ํ  ๊ฐ ํ์
_, max_val = get_min_max(numbers)  # ์ต์๊ฐ ๋ฌด์
first, _, third = (1, 2, 3)       # ๋ ๋ฒ์งธ ๊ฐ ๋ฌด์
๋ฉ์๋ ์ฒด์ด๋๊ณผ fluent interface#
# ๋ฌธ์์ด ๋ฉ์๋ ์ฒด์ด๋
text = "  Hello World  "
result = text.strip().lower().replace(" ", "_")
# ๊ฒฐ๊ณผ: "hello_world"
# ๋ฆฌ์คํธ ๋ฉ์๋๋ ์ฒด์ด๋ ๋ถ๊ฐ (๋๋ถ๋ถ None ๋ฐํ)
# ๋์ ์
# numbers = [3, 1, 4, 1, 5].sort().reverse()  # AttributeError!
# ์ฌ๋ฐ๋ฅธ ์
numbers = [3, 1, 4, 1, 5]
numbers.sort()
numbers.reverse()
# ๋๋ ํจ์ํ ์คํ์ผ
numbers = sorted([3, 1, 4, 1, 5], reverse=True)
์ปจํ
์คํธ ๋งค๋์  (with ๋ฌธ)#
# ํ์ผ ์ฒ๋ฆฌ (์๋์ผ๋ก ํ์ผ ๋ซ๊ธฐ)
with open('data.txt', 'r') as f:
    content = f.read()
# ํ์ผ์ด ์๋์ผ๋ก ๋ซํ
# ์ฌ๋ฌ ํ์ผ ๋์ ์ฒ๋ฆฌ
with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    outfile.write(infile.read().upper())
# ์ปค์คํ
 ์ปจํ
์คํธ ๋งค๋์ 
from contextlib import contextmanager
@contextmanager
def timer():
    import time
    start = time.time()
    print("Timer started")
    try:
        yield
    finally:
        end = time.time()
        print(f"Elapsed time: {end - start:.2f}s")
# ์ฌ์ฉ
with timer():
    # ์๊ฐ์ ์ธก์ ํ  ์ฝ๋
    time.sleep(1)
๐ง 5. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ๊ณผ ๋๋ค#
๋๋ค ํจ์์ ๋ค์ํ ํ์ฉ#
# ๊ธฐ๋ณธ ๋๋ค
square = lambda x: x ** 2
add = lambda x, y: x + y
# ์ ๋ ฌ์์ ๋๋ค ํ์ฉ
students = [('Alice', 85), ('Bob', 90), ('Charlie', 78)]
# ์ด๋ฆ์ผ๋ก ์ ๋ ฌ
students.sort(key=lambda student: student[0])
# ์ ์๋ก ์ ๋ ฌ (๋ด๋ฆผ์ฐจ์)
students.sort(key=lambda student: student[1], reverse=True)
# ๋ณต์กํ ์ ๋ ฌ ๊ธฐ์ค
data = [('A', 1, 100), ('B', 2, 85), ('A', 3, 95)]
# ์ฒซ ๋ฒ์งธ ํ๋๋ก ์ ๋ ฌ, ๊ฐ์ผ๋ฉด ์ธ ๋ฒ์งธ ํ๋๋ก ์ ๋ ฌ
data.sort(key=lambda x: (x[0], x[2]))
# ์กฐ๊ฑด๋ถ ๋๋ค
get_grade = lambda score: 'A' if score >= 90 else 'B' if score >= 80 else 'C'
map, filter, reduce ํจ์ํ ํจํด#
# map: ๋ชจ๋  ์์์ ํจ์ ์ ์ฉ
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
# ๊ฒฐ๊ณผ: [1, 4, 9, 16, 25]
# ์ฌ๋ฌ ์ํ์ค์ ์ ์ฉ
nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
sums = list(map(lambda x, y: x + y, nums1, nums2))
# ๊ฒฐ๊ณผ: [5, 7, 9]
# filter: ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์์๋ง ์ ํ
evens = list(filter(lambda x: x % 2 == 0, numbers))
# ๊ฒฐ๊ณผ: [2, 4]
# reduce: ๋์  ์ฐ์ฐ
from functools import reduce
product = reduce(lambda x, y: x * y, numbers)  # 1*2*3*4*5 = 120
max_val = reduce(lambda x, y: x if x > y else y, numbers)
# ์ค์ฉ์ ์ธ ์์: ๋จ์ด์์ ๋ชจ์ ์ ๊ฑฐ
def remove_vowels(text):
    vowels = "aeiouAEIOU"
    return ''.join(filter(lambda char: char not in vowels, text))
# ์ค์ฒฉ ํจ์์ ํด๋ก์ 
def make_multiplier(n):
    return lambda x: x * n
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5))  # 10
print(triple(5))  # 15
๊ณ ์ฐจ ํจ์ ํจํด#
# ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋ ํจ์
def apply_operation(numbers, operation):
    return [operation(x) for x in numbers]
# ์ฌ์ฉ ์์
result1 = apply_operation([1, 2, 3, 4], lambda x: x**2)
result2 = apply_operation([1, 2, 3, 4], lambda x: x * 2)
# ํจ์๋ฅผ ๋ฐํํ๋ ํจ์
def create_validator(min_val, max_val):
    def validator(value):
        return min_val <= value <= max_val
    return validator
age_validator = create_validator(0, 120)
score_validator = create_validator(0, 100)
# ๋ฐ์ฝ๋ ์ดํฐ ๊ธฐ๋ณธ ์ดํด
def timing_decorator(func):
    def wrapper(*args, **kwargs):
        import time
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f}s")
        return result
    return wrapper
@timing_decorator
def slow_function():
    import time
    time.sleep(1)
    return "Done"
๐ 6. ์๋ฃ๊ตฌ์กฐ ์ ์ฉํ ํจํด๋ค#
๋์
๋๋ฆฌ ๊ณ ๊ธ ํจํด#
# ํจํด 1: ํค๊ฐ ์์ผ๋ฉด ๊ฐ ์ฆ๊ฐ, ์์ผ๋ฉด 1๋ก ์ค์ 
# ๋ฐฉ๋ฒ 1: get() ์ฌ์ฉ
count = {}
for item in items:
    count[item] = count.get(item, 0) + 1
# ๋ฐฉ๋ฒ 2: setdefault() ์ฌ์ฉ
count = {}
for item in items:
    count.setdefault(item, 0)
    count[item] += 1
# ๋ฐฉ๋ฒ 3: defaultdict ์ฌ์ฉ (๊ฐ์ฅ ๊น๋)
from collections import defaultdict
count = defaultdict(int)
for item in items:
    count[item] += 1
# ๋ฐฉ๋ฒ 4: Counter ์ฌ์ฉ (๊ฐ์ฅ ํ์ด์ฌ์ค๋ฌ์)
from collections import Counter
count = Counter(items)
# ํจํด 2: ๊ทธ๋ฃนํ
# ํ์๋ค์ ์ฑ์ ๋ณ๋ก ๊ทธ๋ฃนํ
students = [('Alice', 'A'), ('Bob', 'B'), ('Charlie', 'A'), ('David', 'B')]
# defaultdict๋ก ๊ทธ๋ฃนํ
from collections import defaultdict
groups = defaultdict(list)
for name, grade in students:
    groups[grade].append(name)
# ๊ฒฐ๊ณผ: {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'David']}
# itertools.groupby ์ฌ์ฉ (์ ๋ ฌ๋ ๋ฐ์ดํฐ)
from itertools import groupby
students.sort(key=lambda x: x[1])  # ์ฑ์ ์ผ๋ก ์ ๋ ฌ ๋จผ์ 
groups = {grade: [name for name, _ in group] 
          for grade, group in groupby(students, key=lambda x: x[1])}
๋ฆฌ์คํธ์ ํ, ์คํ ํจํด#
# ์คํ ํจํด (LIFO)
stack = []
stack.append(1)    # push
stack.append(2)
item = stack.pop() # pop (2)
# ํ ํจํด (FIFO) - deque ์ฌ์ฉ ๊ถ์ฅ
from collections import deque
queue = deque()
queue.append(1)      # enqueue
queue.append(2)
item = queue.popleft()  # dequeue (1)
# ์ฐ์ ์์ ํ
import heapq
heap = []
heapq.heappush(heap, (priority, item))
priority, item = heapq.heappop(heap)
# ์ต๋ ํ ๊ตฌํ (์์ ์ด์ฉ)
max_heap = []
heapq.heappush(max_heap, -value)
max_value = -heapq.heappop(max_heap)
# ๋ฆฌ์คํธ์ ๊ณ ๊ธ ์กฐ์
# ํน์  ์กฐ๊ฑด์ ๋ชจ๋  ์์ ์ ๊ฑฐ
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# ํ์๋ง ๋จ๊ธฐ๊ธฐ
numbers = [x for x in numbers if x % 2 == 1]
# ๋๋ filter ์ฌ์ฉ
numbers = list(filter(lambda x: x % 2 == 1, numbers))
# ๋ฆฌ์คํธ์์ ์ค๋ณต ์ ๊ฑฐ (์์ ์ ์ง)
def remove_duplicates(lst):
    seen = set()
    result = []
    for item in lst:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result
# ๋๋ dict.fromkeys() ํธ๋ฆญ (Python 3.7+)
unique_list = list(dict.fromkeys(original_list))
์งํฉ ์ฐ์ฐ ๊ณ ๊ธ ํ์ฉ#
# ์งํฉ์ ๊ฐ๋ ฅํ ์ฐ์ฐ๋ค
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# ๊ต์งํฉ: ๊ณตํต ์์
common = set1 & set2  # {4, 5}
# ํฉ์งํฉ: ๋ชจ๋  ์์
all_items = set1 | set2  # {1, 2, 3, 4, 5, 6, 7, 8}
# ์ฐจ์งํฉ: set1์๋ง ์๋ ์์
only_in_set1 = set1 - set2  # {1, 2, 3}
# ๋์นญ์ฐจ์งํฉ: ๋ ์ค ํ๋์๋ง ์๋ ์์
symmetric_diff = set1 ^ set2  # {1, 2, 3, 6, 7, 8}
# ์ค์ฉ์ ์ธ ํ์ฉ: ๋ ๋ฆฌ์คํธ์ ๊ณตํต ์์ ์ฐพ๊ธฐ
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common_elements = list(set(list1) & set(list2))
# ์ค๋ณต ์์ ์ฐพ๊ธฐ
def find_duplicates(lst):
    seen = set()
    duplicates = set()
    for item in lst:
        if item in seen:
            duplicates.add(item)
        else:
            seen.add(item)
    return list(duplicates)
collections ๋ชจ๋์ ํน์ ์๋ฃ๊ตฌ์กฐ#
from collections import namedtuple, OrderedDict, ChainMap
# namedtuple: ํ๋๋ช
์ด ์๋ ํํ
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y)  # 3 4
print(p[0], p[1])  # 3 4 (์ธ๋ฑ์ค๋ก๋ ์ ๊ทผ ๊ฐ๋ฅ)
# Student ์์
Student = namedtuple('Student', ['name', 'age', 'grade'])
alice = Student('Alice', 20, 'A')
print(f"{alice.name} got {alice.grade}")
# OrderedDict: ์ฝ์
 ์์ ์ ์ง (Python 3.7+์์๋ ์ผ๋ฐ dict๋ ์์ ์ ์ง)
from collections import OrderedDict
ordered = OrderedDict()
ordered['first'] = 1
ordered['second'] = 2
ordered['third'] = 3
# ChainMap: ์ฌ๋ฌ ๋์
๋๋ฆฌ๋ฅผ ํ๋์ฒ๋ผ ์ฌ์ฉ
default_config = {'timeout': 30, 'retries': 3}
user_config = {'timeout': 60}
config = ChainMap(user_config, default_config)
print(config['timeout'])  # 60 (user_config๊ฐ ์ฐ์ )
print(config['retries'])  # 3 (default_config์์)
๐ฏ 7. ์ค์  ํ์ฉ ํจํด ๋ชจ์#
ํ์ผ ์ฒ๋ฆฌ ํจํด#
# ํ์ผ ์ฝ๊ธฐ ํจํด๋ค
# ์ ์ฒด ํ์ผ ์ฝ๊ธฐ
with open('file.txt', 'r', encoding='utf-8') as f:
    content = f.read()
# ์ค ๋จ์๋ก ์ฝ๊ธฐ
with open('file.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()  # ๊ฐํ๋ฌธ์ ํฌํจ
    lines = [line.strip() for line in lines]  # ๊ฐํ๋ฌธ์ ์ ๊ฑฐ
# ํ ์ค์ฉ ์ฒ๋ฆฌ (๋ฉ๋ชจ๋ฆฌ ํจ์จ์ )
with open('file.txt', 'r', encoding='utf-8') as f:
    for line in f:
        process_line(line.strip())
# CSV ์ฒ๋ฆฌ
import csv
with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['name'], row['age'])
์๋ฌ ์ฒ๋ฆฌ ํจํด#
# ๊ธฐ๋ณธ try-except ํจํด
try:
    result = risky_operation()
except SpecificError as e:
    handle_specific_error(e)
except (ErrorType1, ErrorType2) as e:
    handle_multiple_errors(e)
except Exception as e:
    handle_generic_error(e)
else:
    # ์์ธ๊ฐ ๋ฐ์ํ์ง ์์์ ๋
    success_handler(result)
finally:
    # ํญ์ ์คํ
    cleanup()
# EAFP (Easier to Ask for Forgiveness than Permission) ํจํด
# ํ์ด์ฌ์ค๋ฌ์ด ๋ฐฉ๋ฒ
try:
    return my_dict[key]
except KeyError:
    return default_value
# vs LBYL (Look Before You Leap) - ๋ ํ์ด์ฌ์ค๋ฌ์
if key in my_dict:
    return my_dict[key]
else:
    return default_value
์ฑ๋ฅ ์ต์ ํ ํ#
# ๋ฌธ์์ด ์ฐ๊ฒฐ ์ต์ ํ
# ๋์ ์ (O(nยฒ))
result = ""
for word in words:
    result += word + " "
# ์ข์ ์ (O(n))
result = " ".join(words)
# ๋ฆฌ์คํธ ๋ดํฌ vs map/filter
# ๋ฆฌ์คํธ ๋ดํฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ ๋น ๋ฆ
squares1 = [x**2 for x in range(1000)]
squares2 = list(map(lambda x: x**2, range(1000)))
# ์งํฉ ๋ฉค๋ฒ์ญ ํ
์คํธ
# ๋ฆฌ์คํธ: O(n), ์งํฉ: O(1)
large_list = list(range(10000))
large_set = set(range(10000))
# ๋๋ฆผ
if 9999 in large_list:
    pass
# ๋น ๋ฆ
if 9999 in large_set:
    pass
# ๋์
๋๋ฆฌ vs ๋ฆฌ์คํธ ๊ฒ์
# key๋ก ๊ฒ์ํ  ๋๋ ๋์
๋๋ฆฌ๊ฐ ํจ์ฌ ๋น ๋ฆ
data_dict = {i: f"value_{i}" for i in range(1000)}
data_list = [(i, f"value_{i}") for i in range(1000)]
๐ 3๋จ๊ณ ํต์ฌ ์์ฝ#
Java/C++ ๊ฐ๋ฐ์๊ฐ ์ฃผ์ํ  ์ #
- ํ์
 ์์คํ
: ๋์  ํ์ดํ, isinstance() ํ์ฉ
 
- ๋ฐ๋ณต๋ฌธ: range() ์ฌ์ฉ๋ฒ, enumerate/zip ํ์ฉ
 
- ์กฐ๊ฑด๋ฌธ: Truthy/Falsy ๊ฐ๋
, ์ฒด์ด๋ ๋น๊ต
 
- ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ: ๊ฐ๋น์ง ์ปฌ๋ ์
 ์๋, with๋ฌธ ํ์ฉ
 
ํ์ด์ฌ๋ค์ด ์ฝ๋ฉ ์คํ์ผ#
- EAFP over LBYL: ์์ธ ์ฒ๋ฆฌ ์ฐ์ 
 
- ์ปดํ๋ฆฌํจ์
 ํ์ฉ: ๋ฆฌ์คํธ/๋์
๋๋ฆฌ/์งํฉ ์ปดํ๋ฆฌํจ์
 
- ์ธํจํน ํ์ฉ: ํํ/๋์
๋๋ฆฌ ์ธํจํน
 
- ๋ด์ฅ ํจ์ ํ์ฉ: map, filter, zip, enumerate
 
์์ฃผ ์ฌ์ฉํ๋ ํจํด ์ฒดํฌ๋ฆฌ์คํธ#
ํ์ด์ฌ PS 3๋จ๊ณ: PS ํต์ฌ ํจํด#
๐ 1. ํ์ ์๊ณ ๋ฆฌ์ฆ (DFS/BFS ํ
ํ๋ฆฟ)#
DFS (๊น์ด ์ฐ์  ํ์)#
์ฌ๊ท์  DFS#
def dfs_recursive(graph, start, visited=None):
    if visited is None:
        visited = set()
    
    visited.add(start)
    print(start)  # ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
    
    for neighbor in graph[start]:
        if neighbor not in visited:
            dfs_recursive(graph, neighbor, visited)
    
    return visited
# ์ฌ์ฉ ์์
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}
์คํ์ ์ด์ฉํ DFS#
def dfs_iterative(graph, start):
    visited = set()
    stack = [start]
    
    while stack:
        vertex = stack.pop()
        if vertex not in visited:
            visited.add(vertex)
            print(vertex)  # ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
            
            # ์ญ์์ผ๋ก ์ถ๊ฐ (์ฌ๊ท์ ๊ฐ์ ์์๋ก ๋ฐฉ๋ฌธํ๊ธฐ ์ํด)
            for neighbor in reversed(graph[vertex]):
                if neighbor not in visited:
                    stack.append(neighbor)
    
    return visited
2์ฐจ์ ๊ฒฉ์์์ DFS#
def dfs_grid(grid, start_row, start_col, visited):
    rows, cols = len(grid), len(grid[0])
    
    # ๊ฒฝ๊ณ ์ฒดํฌ ๋ฐ ๋ฐฉ๋ฌธ ์ฒดํฌ
    if (start_row < 0 or start_row >= rows or 
        start_col < 0 or start_col >= cols or
        visited[start_row][start_col] or 
        grid[start_row][start_col] == 0):  # 0์ ๋ฒฝ์ด๋ผ ๊ฐ์ 
        return
    
    visited[start_row][start_col] = True
    print(f"๋ฐฉ๋ฌธ: ({start_row}, {start_col})")
    
    # 4๋ฐฉํฅ ํ์ (์, ํ, ์ข, ์ฐ)
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    for dr, dc in directions:
        dfs_grid(grid, start_row + dr, start_col + dc, visited)
# ์ฌ์ฉ ์์
grid = [
    [1, 1, 0, 1],
    [1, 0, 1, 1],
    [0, 1, 1, 1],
    [1, 1, 1, 0]
]
visited = [[False] * len(grid[0]) for _ in range(len(grid))]
BFS (๋๋น ์ฐ์  ํ์)#
๊ธฐ๋ณธ BFS#
from collections import deque
def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)
    
    while queue:
        vertex = queue.popleft()
        print(vertex)  # ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
        
        for neighbor in graph[vertex]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)
    
    return visited
์ต๋จ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ BFS#
def bfs_shortest_path(graph, start, end):
    visited = set()
    queue = deque([(start, 0)])  # (๋
ธ๋, ๊ฑฐ๋ฆฌ)
    visited.add(start)
    
    while queue:
        vertex, distance = queue.popleft()
        
        if vertex == end:
            return distance
        
        for neighbor in graph[vertex]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, distance + 1))
    
    return -1  # ๊ฒฝ๋ก๊ฐ ์์
2์ฐจ์ ๊ฒฉ์์์ BFS#
def bfs_grid(grid, start_row, start_col):
    rows, cols = len(grid), len(grid[0])
    visited = [[False] * cols for _ in range(rows)]
    queue = deque([(start_row, start_col, 0)])  # (ํ, ์ด, ๊ฑฐ๋ฆฌ)
    visited[start_row][start_col] = True
    
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    
    while queue:
        row, col, dist = queue.popleft()
        print(f"๋ฐฉ๋ฌธ: ({row}, {col}), ๊ฑฐ๋ฆฌ: {dist}")
        
        for dr, dc in directions:
            new_row, new_col = row + dr, col + dc
            
            if (0 <= new_row < rows and 0 <= new_col < cols and
                not visited[new_row][new_col] and 
                grid[new_row][new_col] == 1):  # 1์ ์ด๋ ๊ฐ๋ฅํ ์นธ
                
                visited[new_row][new_col] = True
                queue.append((new_row, new_col, dist + 1))
๐จ DFS/BFS ์ฃผ์ ํจ์ #
- ์ฌ๊ท DFS์ ์คํ ์ค๋ฒํ๋ก์ฐ (Python ๊ธฐ๋ณธ ์ฌ๊ท ํ๋: 1000)
 
sys.setrecursionlimit(10**6) ์ค์  ํ์ํ ๊ฒฝ์ฐ 
- BFS์์ 
deque ์ฌ์ฉ ํ์ (list์ pop(0)์ O(n)) 
- ๋ฐฉ๋ฌธ ์ฒดํฌ๋ฅผ ํ์ ๋ฃ์ ๋ vs ํ์์ ๋บ ๋์ ์ฐจ์ด์ 
 
๐ 2. ์ ๋ ฌ๊ณผ ์ด์งํ์ ํจํด#
๋ค์ํ ์ ๋ ฌ ๊ธฐ๋ฒ#
๊ธฐ๋ณธ ์ ๋ ฌ#
# ๋ฆฌ์คํธ ์ ๋ ฌ
arr = [3, 1, 4, 1, 5, 9, 2, 6]
arr.sort()                    # ์๋ณธ ์์ 
sorted_arr = sorted(arr)      # ์ ๋ฆฌ์คํธ ๋ฐํ
# ์ญ์ ์ ๋ ฌ
arr.sort(reverse=True)
์ปค์คํ
 ์ ๋ ฌ#
# ํํ ์ ๋ ฌ (์ฌ๋ฌ ๊ธฐ์ค)
students = [('Alice', 85, 20), ('Bob', 90, 19), ('Charlie', 85, 21)]
# ์ ์ ๋ด๋ฆผ์ฐจ์, ๊ฐ์ผ๋ฉด ๋์ด ์ค๋ฆ์ฐจ์
students.sort(key=lambda x: (-x[1], x[2]))
# ๋ฌธ์์ด ๊ธธ์ด๋ก ์ ๋ ฌ
words = ['apple', 'pie', 'banana', 'book']
words.sort(key=len)
# ์ ๋๊ฐ์ผ๋ก ์ ๋ ฌ
numbers = [-3, -1, 4, -5, 2]
numbers.sort(key=abs)
์์  ์ ๋ ฌ vs ๋ถ์์  ์ ๋ ฌ#
# Python์ sort()๋ stable sort (๊ฐ์ ๊ฐ์ ์๋ ์์ ์ ์ง)
data = [('A', 1), ('B', 2), ('C', 1), ('D', 2)]
data.sort(key=lambda x: x[1])
# ๊ฒฐ๊ณผ: [('A', 1), ('C', 1), ('B', 2), ('D', 2)]
# A์ C์ ์์, B์ D์ ์์๊ฐ ์ ์ง๋จ
์ด์งํ์ (Binary Search)#
๊ธฐ๋ณธ ์ด์งํ์#
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1  # ์ฐพ์ง ๋ชปํจ
# ๋ด์ฅ ํจ์ ์ฌ์ฉ
import bisect
arr = [1, 3, 5, 7, 9]
index = bisect.bisect_left(arr, 5)  # 5๊ฐ ๋ค์ด๊ฐ ์์น
Lower Bound / Upper Bound#
def lower_bound(arr, target):
    """target ์ด์์ธ ์ฒซ ๋ฒ์งธ ์์์ ์ธ๋ฑ์ค"""
    left, right = 0, len(arr)
    
    while left < right:
        mid = (left + right) // 2
        if arr[mid] < target:
            left = mid + 1
        else:
            right = mid
    
    return left
def upper_bound(arr, target):
    """target ์ด๊ณผ์ธ ์ฒซ ๋ฒ์งธ ์์์ ์ธ๋ฑ์ค"""
    left, right = 0, len(arr)
    
    while left < right:
        mid = (left + right) // 2
        if arr[mid] <= target:
            left = mid + 1
        else:
            right = mid
    
    return left
# bisect ๋ชจ๋ ํ์ฉ
import bisect
arr = [1, 2, 2, 2, 3, 4, 5]
lower = bisect.bisect_left(arr, 2)   # 1
upper = bisect.bisect_right(arr, 2)  # 4
count = upper - lower                # 2์ ๊ฐ์: 3
๋งค๊ฐ๋ณ์ ํ์ (Parametric Search)#
def parametric_search(check_function, left, right):
    """
    check_function(x)๊ฐ True๊ฐ ๋๋ ์ต์๊ฐ์ ์ฐพ๋ ์ด์งํ์
    """
    result = right + 1
    
    while left <= right:
        mid = (left + right) // 2
        
        if check_function(mid):
            result = mid
            right = mid - 1
        else:
            left = mid + 1
    
    return result
# ์์: ๋๋ฌด ์๋ฅด๊ธฐ ๋ฌธ์ 
def can_cut_wood(trees, height, target):
    """๋์ด height๋ก ์๋์ ๋ target ์ด์์ ๋๋ฌด๋ฅผ ์ป์ ์ ์๋์ง"""
    total = sum(max(0, tree - height) for tree in trees)
    return total >= target
trees = [20, 15, 10, 17]
target = 7
max_height = parametric_search(
    lambda h: can_cut_wood(trees, h, target), 
    0, max(trees)
)
๐จ ์ ๋ ฌ/์ด์งํ์ ์ฃผ์ ํจ์ #
- ์ด์งํ์ ์  ๋ฐ๋์ ์ ๋ ฌ ํ์
 
left <= right vs left < right ์กฐ๊ฑด ์ฐจ์ด 
- ๋ฌดํ๋ฃจํ ๋ฐฉ์ง๋ฅผ ์ํ mid ๊ณ์ฐ ์ฃผ์
 
- overflow ๋ฐฉ์ง: 
mid = left + (right - left) // 2 
๐ฅ 3. ํฌ ํฌ์ธํฐ, ์ฌ๋ผ์ด๋ฉ ์๋์ฐ#
ํฌ ํฌ์ธํฐ ๊ธฐ๋ฒ#
๊ธฐ๋ณธ ํฌ ํฌ์ธํฐ#
def two_sum_sorted(arr, target):
    """์ ๋ ฌ๋ ๋ฐฐ์ด์์ ํฉ์ด target์ธ ๋ ์ ์ฐพ๊ธฐ"""
    left, right = 0, len(arr) - 1
    
    while left < right:
        current_sum = arr[left] + arr[right]
        
        if current_sum == target:
            return [left, right]
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    
    return [-1, -1]  # ์ฐพ์ง ๋ชปํจ
์ฐ์ ๋ถ๋ถ๋ฐฐ์ด์ ํฉ#
def subarray_sum(arr, target):
    """ํฉ์ด target์ธ ์ฐ์ ๋ถ๋ถ๋ฐฐ์ด์ ๊ฐ์"""
    left = 0
    current_sum = 0
    count = 0
    
    for right in range(len(arr)):
        current_sum += arr[right]
        
        # ํฉ์ด target๋ณด๋ค ํด ๋ left ํฌ์ธํฐ ์ด๋
        while current_sum > target and left <= right:
            current_sum -= arr[left]
            left += 1
        
        if current_sum == target:
            count += 1
    
    return count
์๋ก ๋ค๋ฅธ ๋ฌธ์์ ์ต์ฅ ๋ถ๋ถ๋ฌธ์์ด#
def longest_unique_substring(s):
    """์๋ก ๋ค๋ฅธ ๋ฌธ์๋ก๋ง ์ด๋ฃจ์ด์ง ์ต์ฅ ๋ถ๋ถ๋ฌธ์์ด์ ๊ธธ์ด"""
    left = 0
    max_length = 0
    char_set = set()
    
    for right in range(len(s)):
        # ์ค๋ณต ๋ฌธ์๊ฐ ๋์ฌ ๋๊น์ง left ์ด๋
        while s[right] in char_set:
            char_set.remove(s[left])
            left += 1
        
        char_set.add(s[right])
        max_length = max(max_length, right - left + 1)
    
    return max_length
์ฌ๋ผ์ด๋ฉ ์๋์ฐ#
๊ณ ์  ํฌ๊ธฐ ์๋์ฐ#
def max_sum_subarray(arr, k):
    """ํฌ๊ธฐ๊ฐ k์ธ ๋ถ๋ถ๋ฐฐ์ด์ ์ต๋ ํฉ"""
    if len(arr) < k:
        return -1
    
    # ์ฒซ ๋ฒ์งธ ์๋์ฐ์ ํฉ
    window_sum = sum(arr[:k])
    max_sum = window_sum
    
    # ์๋์ฐ๋ฅผ ์ฌ๋ผ์ด๋ฉํ๋ฉด์ ํฉ ๊ณ์ฐ
    for i in range(k, len(arr)):
        window_sum = window_sum - arr[i - k] + arr[i]
        max_sum = max(max_sum, window_sum)
    
    return max_sum
๊ฐ๋ณ ํฌ๊ธฐ ์๋์ฐ#
def min_window_sum(arr, target):
    """ํฉ์ด target ์ด์์ธ ์ต์ ๊ธธ์ด ๋ถ๋ถ๋ฐฐ์ด"""
    left = 0
    min_length = float('inf')
    current_sum = 0
    
    for right in range(len(arr)):
        current_sum += arr[right]
        
        # ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋์ ์๋์ฐ ํฌ๊ธฐ ์ค์ด๊ธฐ
        while current_sum >= target:
            min_length = min(min_length, right - left + 1)
            current_sum -= arr[left]
            left += 1
    
    return min_length if min_length != float('inf') else 0
๋ฌธ์์ด์์ ํจํด ๋งค์นญ#
def find_anagrams(s, p):
    """๋ฌธ์์ด s์์ p์ anagram์ธ ๋ถ๋ถ๋ฌธ์์ด์ ์์ ์ธ๋ฑ์ค๋ค"""
    from collections import Counter
    
    if len(p) > len(s):
        return []
    
    p_count = Counter(p)
    window_count = Counter()
    result = []
    
    for i in range(len(s)):
        # ์๋์ฐ์ ๋ฌธ์ ์ถ๊ฐ
        window_count[s[i]] += 1
        
        # ์๋์ฐ ํฌ๊ธฐ๊ฐ p์ ๊ธธ์ด์ ๊ฐ์์ง๋ฉด
        if i >= len(p) - 1:
            if window_count == p_count:
                result.append(i - len(p) + 1)
            
            # ์๋์ฐ์์ ์ฒซ ๋ฒ์งธ ๋ฌธ์ ์ ๊ฑฐ
            left_char = s[i - len(p) + 1]
            window_count[left_char] -= 1
            if window_count[left_char] == 0:
                del window_count[left_char]
    
    return result
๐จ ํฌ ํฌ์ธํฐ/์ฌ๋ผ์ด๋ฉ ์๋์ฐ ์ฃผ์ ํจ์ #
- ํฌ์ธํฐ ์ด๋ ์กฐ๊ฑด์ ๋ช
ํํ ์ ์
 
- ์๋์ฐ ํฌ๊ธฐ ์กฐ์  ์ ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฃผ์
 
- Counter๋ ๋์
๋๋ฆฌ ์ฌ์ฉ ์ 0์ด ๋๋ ํค ์ฒ๋ฆฌ
 
๐ 4. ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ ํจํด#
๊ธฐ๋ณธ ๊ทธ๋ฆฌ๋ ํจํด#
ํ๋ ์ ํ ๋ฌธ์ #
def activity_selection(activities):
    """๋๋๋ ์๊ฐ์ด ๋น ๋ฅธ ์์ผ๋ก ์ต๋ํ ๋ง์ ํ๋ ์ ํ"""
    # (์์์๊ฐ, ๋์๊ฐ) ํํ ๋ฆฌ์คํธ๋ฅผ ๋์๊ฐ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ
    activities.sort(key=lambda x: x[1])
    
    selected = [activities[0]]
    last_end_time = activities[0][1]
    
    for start, end in activities[1:]:
        if start >= last_end_time:  # ๊ฒน์น์ง ์์ผ๋ฉด ์ ํ
            selected.append((start, end))
            last_end_time = end
    
    return selected
# ์ฌ์ฉ ์์
activities = [(1, 4), (3, 5), (0, 6), (5, 7), (3, 9), (5, 9), (6, 10), (8, 11)]
result = activity_selection(activities)
๊ฑฐ์ค๋ฆ๋ ๋ฌธ์ #
def make_change(amount, coins):
    """๊ฐ์ฅ ์ ์ ๊ฐ์์ ๋์ ์ผ๋ก ๊ฑฐ์ค๋ฆ๋ ๋ง๋ค๊ธฐ (๊ทธ๋ฆฌ๋ ์กฐ๊ฑด ๋ง์กฑ ์)"""
    coins.sort(reverse=True)  # ํฐ ๋์ ๋ถํฐ
    
    result = []
    for coin in coins:
        count = amount // coin
        if count > 0:
            result.extend([coin] * count)
            amount %= coin
        
        if amount == 0:
            break
    
    return result if amount == 0 else []  # ๋ง๋ค ์ ์์ผ๋ฉด ๋น ๋ฆฌ์คํธ
# ์ฌ์ฉ ์์
coins = [500, 100, 50, 10]
change = make_change(1260, coins)
์ต์ ์ ์ฅ ํธ๋ฆฌ (ํฌ๋ฃจ์ค์นผ)#
def find_parent(parent, x):
    """Union-Find์ find ์ฐ์ฐ"""
    if parent[x] != x:
        parent[x] = find_parent(parent, parent[x])
    return parent[x]
def union_parent(parent, rank, a, b):
    """Union-Find์ union ์ฐ์ฐ"""
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    
    if rank[a] < rank[b]:
        parent[a] = b
    elif rank[a] > rank[b]:
        parent[b] = a
    else:
        parent[b] = a
        rank[a] += 1
def kruskal(n, edges):
    """ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ต์ ์ ์ฅ ํธ๋ฆฌ"""
    # ๊ฐ์ ์ ๋น์ฉ ์์ผ๋ก ์ ๋ ฌ
    edges.sort(key=lambda x: x[2])
    
    parent = list(range(n))
    rank = [0] * n
    mst = []
    total_cost = 0
    
    for a, b, cost in edges:
        if find_parent(parent, a) != find_parent(parent, b):
            union_parent(parent, rank, a, b)
            mst.append((a, b, cost))
            total_cost += cost
    
    return mst, total_cost
๊ทธ๋ฆฌ๋ ์ ํ์ ์ ๋น์ฑ ์ฆ๋ช
 ํจํด#
ํ์์ค ๋ฐฐ์ #
def meeting_rooms(meetings):
    """์ต์ํ์ ํ์์ค๋ก ๋ชจ๋  ํ์ ๋ฐฐ์ """
    import heapq
    
    if not meetings:
        return 0
    
    # ์์์๊ฐ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ
    meetings.sort(key=lambda x: x[0])
    
    # ๊ฐ ํ์์ค์ ๋๋๋ ์๊ฐ์ ์ ์ฅํ๋ ์ต์ ํ
    heap = []
    
    for start, end in meetings:
        # ๊ฐ์ฅ ๋นจ๋ฆฌ ๋๋๋ ํ์์ค์ด ํ์ฌ ํ์ ์์ ์ ์ ๋๋๋ฉด
        if heap and heap[0] <= start:
            heapq.heappop(heap)
        
        heapq.heappush(heap, end)
    
    return len(heap)  # ํ์ํ ํ์์ค ๊ฐ์
๐จ ๊ทธ๋ฆฌ๋ ์ฃผ์ ํจ์ #
- ๊ทธ๋ฆฌ๋ ์ ํ์ด ํญ์ ์ต์ ํด๋ฅผ ๋ณด์ฅํ์ง ์์
 
- ๋ฐ๋ก๋ฅผ ์ฐพ์ ๊ทธ๋ฆฌ๋ ์กฐ๊ฑด ํ์ธ ํ์
 
- ์ ๋ ฌ ๊ธฐ์ค์ ์ ์คํ๊ฒ ์ ํ
 
๐งฎ 5. ๋์ ๊ณํ๋ฒ(DP) ๊ธฐ๋ณธ ํจํด#
๊ธฐ๋ณธ DP ํจํด#
ํผ๋ณด๋์น ์์ด#
# Top-down (๋ฉ๋ชจ์ด์ ์ด์
)
def fibonacci_memo(n, memo={}):
    if n in memo:
        return memo[n]
    
    if n <= 1:
        return n
    
    memo[n] = fibonacci_memo(n-1, memo) + fibonacci_memo(n-2, memo)
    return memo[n]
# Bottom-up (ํ
์ด๋ธ ๋ฐฉ์)
def fibonacci_dp(n):
    if n <= 1:
        return n
    
    dp = [0] * (n + 1)
    dp[1] = 1
    
    for i in range(2, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    
    return dp[n]
# ๊ณต๊ฐ ์ต์ ํ
def fibonacci_optimized(n):
    if n <= 1:
        return n
    
    prev2, prev1 = 0, 1
    for i in range(2, n + 1):
        current = prev1 + prev2
        prev2, prev1 = prev1, current
    
    return prev1
0-1 ๋ฐฐ๋ญ ๋ฌธ์ #
def knapsack_01(weights, values, capacity):
    """0-1 ๋ฐฐ๋ญ ๋ฌธ์ """
    n = len(weights)
    # dp[i][w] = i๋ฒ์งธ ๋ฌผ๊ฑด๊น์ง ๊ณ ๋ คํ์ ๋ ๋ฌด๊ฒ w ์ดํ๋ก ์ป์ ์ ์๋ ์ต๋ ๊ฐ์น
    dp = [[0] * (capacity + 1) for _ in range(n + 1)]
    
    for i in range(1, n + 1):
        for w in range(1, capacity + 1):
            # i๋ฒ์งธ ๋ฌผ๊ฑด์ ๋ฃ์ง ์๋ ๊ฒฝ์ฐ
            dp[i][w] = dp[i-1][w]
            
            # i๋ฒ์งธ ๋ฌผ๊ฑด์ ๋ฃ๋ ๊ฒฝ์ฐ (๋ฌด๊ฒ๊ฐ ํ์ฉ๋๋ฉด)
            if weights[i-1] <= w:
                dp[i][w] = max(dp[i][w], 
                              dp[i-1][w-weights[i-1]] + values[i-1])
    
    return dp[n][capacity]
# ๊ณต๊ฐ ์ต์ ํ ๋ฒ์ 
def knapsack_01_optimized(weights, values, capacity):
    dp = [0] * (capacity + 1)
    
    for i in range(len(weights)):
        # ๋ค์์๋ถํฐ ๊ฐฑ์  (์ค๋ณต ์ฌ์ฉ ๋ฐฉ์ง)
        for w in range(capacity, weights[i] - 1, -1):
            dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
    
    return dp[capacity]
์ต์ฅ ์ฆ๊ฐ ๋ถ๋ถ ์์ด (LIS)#
def lis_dp(arr):
    """O(nยฒ) ๋์ ๊ณํ๋ฒ"""
    n = len(arr)
    dp = [1] * n  # dp[i] = i๋ฒ์งธ ์์๋ฅผ ๋ง์ง๋ง์ผ๋ก ํ๋ LIS ๊ธธ์ด
    
    for i in range(1, n):
        for j in range(i):
            if arr[j] < arr[i]:
                dp[i] = max(dp[i], dp[j] + 1)
    
    return max(dp)
def lis_binary_search(arr):
    """O(n log n) ์ด์งํ์"""
    import bisect
    
    tails = []  # tails[i] = ๊ธธ์ด i+1์ธ ์ฆ๊ฐ์์ด์ ๋ง์ง๋ง ์์ ์ค ์ต์๊ฐ
    
    for num in arr:
        pos = bisect.bisect_left(tails, num)
        if pos == len(tails):
            tails.append(num)
        else:
            tails[pos] = num
    
    return len(tails)
ํธ์ง ๊ฑฐ๋ฆฌ (Edit Distance)#
def edit_distance(str1, str2):
    """๋ ๋ฌธ์์ด ๊ฐ์ ํธ์ง ๊ฑฐ๋ฆฌ (์ฝ์
, ์ญ์ , ๊ต์ฒด)"""
    m, n = len(str1), len(str2)
    
    # dp[i][j] = str1[:i]๋ฅผ str2[:j]๋ก ๋ณํํ๋ ์ต์ ์ฐ์ฐ ์
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # ์ด๊ธฐํ: ๋น ๋ฌธ์์ด๋ก ๋ณํ
    for i in range(m + 1):
        dp[i][0] = i  # ๋ชจ๋ ์ญ์ 
    for j in range(n + 1):
        dp[0][j] = j  # ๋ชจ๋ ์ฝ์
    
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if str1[i-1] == str2[j-1]:
                dp[i][j] = dp[i-1][j-1]  # ๋ฌธ์๊ฐ ๊ฐ์ผ๋ฉด ๊ทธ๋๋ก
            else:
                dp[i][j] = 1 + min(
                    dp[i-1][j],    # ์ญ์ 
                    dp[i][j-1],    # ์ฝ์
                    dp[i-1][j-1]   # ๊ต์ฒด
                )
    
    return dp[m][n]
DP ์ํ ์ค๊ณ ํจํด#
๊ตฌ๊ฐ DP#
def matrix_chain_multiplication(matrices):
    """ํ๋ ฌ ์ฐ์ ๊ณฑ์
์ ์ต์ ๊ณฑ์
 ํ์"""
    n = len(matrices)
    # dp[i][j] = i๋ฒ์งธ๋ถํฐ j๋ฒ์งธ ํ๋ ฌ๊น์ง ๊ณฑํ๋ ์ต์ ๋น์ฉ
    dp = [[0] * n for _ in range(n)]
    
    # ๊ตฌ๊ฐ ๊ธธ์ด๋ฅผ ๋๋ ค๊ฐ๋ฉฐ ๊ณ์ฐ
    for length in range(2, n + 1):  # ๊ตฌ๊ฐ ๊ธธ์ด
        for i in range(n - length + 1):
            j = i + length - 1
            dp[i][j] = float('inf')
            
            # k๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถํ 
            for k in range(i, j):
                cost = (dp[i][k] + dp[k+1][j] + 
                       matrices[i][0] * matrices[k][1] * matrices[j][1])
                dp[i][j] = min(dp[i][j], cost)
    
    return dp[0][n-1]
๋นํธ๋ง์คํฌ DP#
def traveling_salesman(dist):
    """์ธํ์ ๋ฌธ์  (TSP)"""
    n = len(dist)
    # dp[mask][i] = mask์ ํ์๋ ๋์๋ค์ ๋ฐฉ๋ฌธํ๊ณ  i์์ ๋๋๋ ์ต์ ๋น์ฉ
    dp = [[float('inf')] * n for _ in range(1 << n)]
    
    # ์์์ (0๋ฒ ๋์)์์ ์ถ๋ฐ
    dp[1][0] = 0
    
    for mask in range(1 << n):
        for i in range(n):
            if not (mask & (1 << i)):  # i๋ฒ ๋์๋ฅผ ๋ฐฉ๋ฌธํ์ง ์์์ผ๋ฉด
                continue
            
            for j in range(n):
                if i == j or not (mask & (1 << j)):
                    continue
                
                # j์์ i๋ก ๊ฐ๋ ๊ฒฝ์ฐ
                prev_mask = mask ^ (1 << i)
                dp[mask][i] = min(dp[mask][i], 
                                 dp[prev_mask][j] + dist[j][i])
    
    # ๋ชจ๋  ๋์๋ฅผ ๋ฐฉ๋ฌธํ๊ณ  ์์์ ์ผ๋ก ๋์๊ฐ๋ ์ต์ ๋น์ฉ
    result = float('inf')
    final_mask = (1 << n) - 1
    for i in range(1, n):
        result = min(result, dp[final_mask][i] + dist[i][0])
    
    return result
๐จ DP ์ฃผ์ ํจ์ #
- ์ํ ์ ์๊ฐ ๋ช
ํํ์ง ์์ผ๋ฉด ๊ตฌํ ์ด๋ ค์
 
- ๋ฉ๋ชจ์ด์ ์ด์
์์ ๊ธฐ๋ณธ๊ฐ ์ค์  ์ฃผ์
 
- ์์์ ๋ฐ๋ฅธ ์ค๋ณต ๊ณ์ฐ ๋ฐฉ์ง
 
- ๊ณต๊ฐ ๋ณต์ก๋ ์ต์ ํ ๊ฐ๋ฅ ์ฌ๋ถ ๊ฒํ 
 
๐ค 6. ๋ฌธ์์ด ์ฒ๋ฆฌ ๊ณ ๊ธ ๊ธฐ๋ฒ#
ํจํด ๋งค์นญ#
KMP ์๊ณ ๋ฆฌ์ฆ#
def build_failure_function(pattern):
    """KMP ์๊ณ ๋ฆฌ์ฆ์ ์คํจ ํจ์ ๊ตฌ์ถ"""
    m = len(pattern)
    failure = [0] * m
    j = 0
    
    for i in range(1, m):
        while j > 0 and pattern[i] != pattern[j]:
            j = failure[j - 1]
        
        if pattern[i] == pattern[j]:
            j += 1
            failure[i] = j
    
    return failure
def kmp_search(text, pattern):
    """KMP ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํจํด ๊ฒ์"""
    n, m = len(text), len(pattern)
    if m == 0:
        return []
    
    failure = build_failure_function(pattern)
    matches = []
    j = 0
    
    for i in range(n):
        while j > 0 and text[i] != pattern[j]:
            j = failure[j - 1]
        
        if text[i] == pattern[j]:
            j += 1
        
        if j == m:
            matches.append(i - m + 1)
            j = failure[j - 1]
    
    return matches
๋ผ๋น-์นดํ ์๊ณ ๋ฆฌ์ฆ#
def rabin_karp_search(text, pattern):
    """๋ผ๋น-์นดํ ์๊ณ ๋ฆฌ์ฆ (๋กค๋ง ํด์)"""
    n, m = len(text), len(pattern)
    if m > n:
        return []
    
    base = 256
    mod = 10**9 + 7
    
    # ํจํด์ ํด์๊ฐ ๊ณ์ฐ
    pattern_hash = 0
    for char in pattern:
        pattern_hash = (pattern_hash * base + ord(char)) % mod
    
    # base^(m-1) % mod ๊ณ์ฐ
    h = 1
    for _ in range(m - 1):
        h = (h * base) % mod
    
    # ์ฒซ ๋ฒ์งธ ์๋์ฐ์ ํด์๊ฐ
    window_hash = 0
    for i in range(m):
        window_hash = (window_hash * base + ord(text[i])) % mod
    
    matches = []
    for i in range(n - m + 1):
        # ํด์๊ฐ์ด ๊ฐ์ผ๋ฉด ์ค์  ๋ฌธ์์ด ๋น๊ต
        if window_hash == pattern_hash:
            if text[i:i+m] == pattern:
                matches.append(i)
        
        # ๋ค์ ์๋์ฐ์ ํด์๊ฐ ๊ณ์ฐ (๋กค๋ง)
        if i < n - m:
            window_hash = (window_hash - ord(text[i]) * h) % mod
            window_hash = (window_hash * base + ord(text[i + m])) % mod
            window_hash = (window_hash + mod) % mod  # ์์ ๋ฐฉ์ง
    
    return matches
๋ฌธ์์ด ๋ณํ๊ณผ ์ฒ๋ฆฌ#
ํ๋ฌธ ๊ฒ์ฌ์ ๊ด๋ จ ์๊ณ ๋ฆฌ์ฆ#
def is_palindrome(s):
    """๊ธฐ๋ณธ ํ๋ฌธ ๊ฒ์ฌ"""
    left, right = 0, len(s) - 1
    while left < right:
        if s[left] != s[right]:
            return False
        left += 1
        right -= 1
    return True
def longest_palindrome_center_expand(s):
    """์ค์ฌ ํ์ฅ์ผ๋ก ์ต์ฅ ํ๋ฌธ ์ฐพ๊ธฐ"""
    def expand_around_center(left, right):
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return right - left - 1
    
    start = end = 0
    for i in range(len(s)):
        # ํ์ ๊ธธ์ด ํ๋ฌธ
        len1 = expand_around_center(i, i)
        # ์ง์ ๊ธธ์ด ํ๋ฌธ
        len2 = expand_around_center(i, i + 1)
        
        max_len = max(len1, len2)
        if max_len > end - start:
            start = i - (max_len - 1) // 2
            end = i + max_len // 2
    
    return s[start:end + 1]
def manacher_algorithm(s):
    """๋งค๋ด์ฒ ์๊ณ ๋ฆฌ์ฆ (O(n) ํ๋ฌธ ๊ฒ์ฌ)"""
    # ๋ฌธ์ ์ฌ์ด์ ํน๋ณ ๋ฌธ์ ์ฝ์
    processed = '#'.join('^{}$'.format(s))
    n = len(processed)
    
    # ๊ฐ ์์น์์์ ํ๋ฌธ ๋ฐ์ง๋ฆ
    radius = [0] * n
    center = right = 0
    
    for i in range(1, n - 1):
        # ์ด์ ์ ๊ณ์ฐ๋ ์ ๋ณด ํ์ฉ
        if i < right:
            radius[i] = min(right - i, radius[2 * center - i])
        
        # ์ค์ฌ ํ์ฅ
        while processed[i + radius[i] + 1] == processed[i - radius[i] - 1]:
            radius[i] += 1
        
        # ์ค๋ฅธ์ชฝ ๊ฒฝ๊ณ ๊ฐฑ์ 
        if i + radius[i] > right:
            center, right = i, i + radius[i]
    
    # ์ต์ฅ ํ๋ฌธ ์ฐพ๊ธฐ
    max_len = max(radius)
    center_index = radius.index(max_len)
    start = (center_index - max_len) // 2
    
    return s[start:start + max_len]
์ ๋ฏธ์ฌ ๋ฐฐ์ด๊ณผ LCP#
def suffix_array_naive(s):
    """์ ๋ฏธ์ฌ ๋ฐฐ์ด (๋จ์ ๊ตฌํ)"""
    suffixes = [(s[i:], i) for i in range(len(s))]
    suffixes.sort()
    return [suffix[1] for suffix in suffixes]
def lcp_array(s, suffix_arr):
    """์ต์ฅ ๊ณตํต ์ ๋์ฌ ๋ฐฐ์ด"""
    n = len(s)
    rank = [0] * n
    lcp = [0] * (n - 1)
    
    # ๊ฐ ์ ๋ฏธ์ฌ์ ์์ ๊ณ์ฐ
    for i in range(n):
        rank[suffix_arr[i]] = i
    
    h = 0
    for i in range(n):
        if rank[i] > 0:
            j = suffix_arr[rank[i] - 1]
            while (i + h < n and j + h < n and 
                   s[i + h] == s[j + h]):
                h += 1
            lcp[rank[i] - 1] = h
            if h > 0:
                h -= 1
    
    return lcp
์ ๊ทํํ์ ํจํด#
import re
# ์์ฃผ ์ฌ์ฉํ๋ ์ ๊ทํํ์ ํจํด๋ค
patterns = {
    'email': r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
    'phone': r'^\d{3}-\d{3,4}-\d{4}$',
    'number': r'^-?\d+(\.\d+)?$',
    'korean': r'[๊ฐ-ํฃ]+',
    'english': r'[a-zA-Z]+',
    'alphanumeric': r'^[a-zA-Z0-9]+$'
}
def validate_input(text, pattern_name):
    """์
๋ ฅ๊ฐ ๊ฒ์ฆ"""
    pattern = patterns.get(pattern_name)
    if pattern:
        return bool(re.match(pattern, text))
    return False
# ๋ฌธ์์ด์์ ๋ชจ๋  ์ซ์ ์ถ์ถ
def extract_numbers(text):
    return re.findall(r'-?\d+\.?\d*', text)
# ํน์  ํจํด์ผ๋ก ๋ฌธ์์ด ๋ถํ 
def smart_split(text, delimiter_pattern=r'[,;\s]+'):
    return re.split(delimiter_pattern, text.strip())
๐จ ๋ฌธ์์ด ์ฒ๋ฆฌ ์ฃผ์ ํจ์ #
- ์ ๋์ฝ๋ ์ฒ๋ฆฌ ์ ์ธ์ฝ๋ฉ ๋ฌธ์ 
 
- ์ ๊ทํํ์์ ์ฑ๋ฅ ์ด์ (๋ฐฑํธ๋ํน)
 
- ๋ฌธ์์ด ๋ถ๋ณ์ฑ์ผ๋ก ์ธํ ์ฑ๋ฅ ์ ํ
 
- KMP/๋ผ๋น-์นดํ์์ ๋ชจ๋๋ก ์ฐ์ฐ ์ค๋ฒํ๋ก์ฐ
 
๐ 2๋จ๊ณ ํต์ฌ ์์ฝ#
ํ์ ์๊ธฐ ํ
ํ๋ฆฟ#
- DFS/BFS: ์ฌ๊ท/์คํ/ํ๋ฅผ ์ด์ฉํ ๊ทธ๋ํ ํ์
 
- ์ด์งํ์: lower_bound, upper_bound, ๋งค๊ฐ๋ณ์ ํ์
 
- ํฌ ํฌ์ธํฐ: ์ ๋ ฌ๋ ๋ฐฐ์ด์์ ์กฐ๊ฑด ๋ง์กฑํ๋ ์ ์ฐพ๊ธฐ
 
- ์ฌ๋ผ์ด๋ฉ ์๋์ฐ: ๊ณ ์ /๊ฐ๋ณ ํฌ๊ธฐ ๋ถ๋ถ๋ฐฐ์ด ๋ฌธ์ 
 
- ๊ทธ๋ฆฌ๋: ํ๋ ์ ํ, ์ต์ ์ ์ฅ ํธ๋ฆฌ
 
- DP: 0-1๋ฐฐ๋ญ, LIS, ํธ์ง๊ฑฐ๋ฆฌ
 
์๊ณ ๋ฆฌ์ฆ ์ ํ ๊ฐ์ด๋#
- ์์ ํ์์ด ๊ฐ๋ฅํ๊ฐ? โ DFS/BFS
 
- ์ ๋ ฌ๋ ์ํ์์ ํน์  ๊ฐ ์ฐพ๊ธฐ โ ์ด์งํ์
 
- ์ฐ์๋ ๋ถ๋ถ์์ ์กฐ๊ฑด ๋ง์กฑ โ ํฌ ํฌ์ธํฐ/์ฌ๋ผ์ด๋ฉ ์๋์ฐ
 
- ๋งค ์๊ฐ ์ต์ ์ ์ ํ โ ๊ทธ๋ฆฌ๋
 
- ์์ ๋ฌธ์ ์ ์ต์ ํด๋ก ํฐ ๋ฌธ์  ํด๊ฒฐ โ DP
 
- ํจํด ๊ฒ์/๋ฌธ์์ด ๋ณํ โ KMP/๋ผ๋น-์นดํ