문자열 안에서 특수기능을 하는 문자들.
| 표현 | 의미 | 예시 출력 |
|---|---|---|
\n | 줄바꿈 (newline) | "a\nb" → a b |
\t | 탭 (4칸 공백) | "A\tB" → A B |
\\ | 역슬래시 자체 출력 | "C:\\path" → C:\path |
\', \" | 따옴표 자체 출력 | 'He said: \'Hi\'' |
divmod/ : 실수 나눗셈
// : 몫
% : 나머지
divmod(a, b) → (몫, 나머지)를 한 번에 반환
q, r = divmod(11, 3)
# q=3, r=2
리스트, 문자열, range 등 반복 가능한 객체 순회.
for i in range(5):
print(i)
→ 0 1 2 3 4
조건 분기 처리.
if x > 0:
print("양수")
elif x == 0:
print("0")
else:
print("음수")
+ → 이어 붙임str() 사용int_val = 3
string_val = "3"
print(int_val + 10) # 13
print(string_val + "10") # "310"
.index()와 리스트 조작리스트 안에서 특정 값의 위치(인덱스)를 반환.
a = ['apple', 'banana', 'cherry']
print(a.index('banana')) # 1
활용 예시: 중복 항목 누적하기
def solution(storage, num):
clean_storage = []
clean_num = []
for i in range(len(storage)):
if storage[i] in clean_storage:
pos = clean_storage.index(storage[i])
clean_num[pos] += num[i]
else:
clean_storage.append(storage[i])
clean_num.append(num[i])
return clean_storage[clean_num.index(max(clean_num))]
| 메서드 | 설명 | 예시 |
|---|---|---|
.lower() | 소문자로 변환 | "ABC".lower() → "abc" |
.upper() | 대문자로 변환 | "abc".upper() → "ABC" |
.islower() | 모두 소문자인가 | "abc".islower() → True |
.isupper() | 모두 대문자인가 | "ABC".isupper() → True |
.isdigit() | 숫자인가 | "123".isdigit() → True |
.isalpha() | 알파벳인가 | "abc".isalpha() → True |
문자열 안에서 특수문자 출력 시 이스케이프 필요.
print("!@#$%^&*(\\'\"<>?:;)")
→ !@#$%^&*('"<>?:;)
\\ : 역슬래시 하나 출력\', \" : 따옴표 문자 출력.strip()과 .split()| 함수 | 기능 | 예시 |
|---|---|---|
.strip() | 문자열 양쪽 공백 제거 | " hi ".strip() → "hi" |
.split() | 문자열을 구분자로 나눠 리스트로 반환 | "a b c".split() → ['a','b','c'] |
.join()리스트를 하나의 문자열로 결합.
"".join(['a', 'b', 'c']) # "abc"
" ".join(['a', 'b', 'c']) # "a b c"
활용 예시:
def solution(my_string, overwrite_string, s):
my_string = list(my_string)
for i in range(len(overwrite_string)):
my_string[int(s)+i] = overwrite_string[i]
return "".join(my_string)
좋다, 이제 Level 0에서 다뤘던 dictionary, Counter, reverse/sort, slicing, deque 등을 중심으로 핵심을 한눈에 보게 정리해줄게.
단순 문법이 아니라 “어떻게, 왜 그렇게 쓰는가”를 강조하겠다.
d = {"1": "w", "-1": "s", "10": "d", "-10": "a"}
| 메서드 | 기능 | 예시 |
|---|---|---|
.keys() | key 목록만 | ['1','-1','10','-10'] |
.values() | value 목록만 | ['w','s','d','a'] |
.items() | (key, value) 쌍 튜플 리스트 | [('1','w'),('-1','s'), ...] |
.get(key, default) | key 존재 시 값 반환, 없으면 기본값 | d.get("11", 0) → 0 |
defaultdictfrom collections import defaultdict
cnt = defaultdict(int) # 기본값 0으로 시작
cnt['a'] += 1
→ 존재하지 않는 key 접근 시 자동으로 초기화됨.
| 함수 | 의미 | 예시 |
|---|---|---|
any(iterable) | 하나라도 True면 True | any([False, True, False]) → True |
all(iterable) | 모두 True면 True | all([True, True, False]) → False |
# 숫자 안에 금지된 숫자 있으면 제외
not any(d in str(x) for d in ["1","2","3"])
from collections import Counter
cnt = Counter([1,1,2,3,3,3])
cnt.most_common()
# [(3, 3), (1, 2), (2, 1)]
| 메서드 | 설명 |
|---|---|
.most_common(n) | 가장 많이 등장한 요소 상위 n개 |
.elements() | 각 key를 count만큼 반복해 iterator 생성 |
cnt[k] | 해당 key의 개수 반환 |
.keys(), .values() | dict와 동일 |
👉 Counter는 리스트의 빈도 계산, 최빈값 찾기, 조합 문제 등에 최적.
| 함수 | 동작 | 원본 변화 | 반환 |
|---|---|---|---|
.reverse() | 리스트 뒤집기 (in-place) | O | None |
reversed(list) | 뒤집은 반복자 반환 | X | iterator |
.sort() | 제자리 정렬 | O | None |
sorted(list) | 새 정렬 리스트 반환 | X | list |
lst = [3,1,2]
lst.sort() # [1,2,3]
new = sorted(lst) # [1,2,3] (원본 유지)
| 표현 | 의미 |
|---|---|
a[::-1] | 역순 |
a[-n:] | 뒤에서 n개 |
a[::-2] | 2칸 간격으로 역순 |
s = "abcdef"
s[::-1] # 'fedcba'
s[-3:] # 'def'
| 함수 | 설명 | 차이 |
|---|---|---|
.rfind(sub) | 뒤에서부터 탐색, 없으면 -1 | 안전 |
.rindex(sub) | 뒤에서부터 탐색, 없으면 ValueError | 예외 발생 |
s = "abcabc"
s.rfind("a") # 3
s.rindex("a") # 3
answer = {}
for s in ["hi","a","bb","hi"]:
answer[len(s)] = answer.get(len(s), 0) + 1
get(key, default)은 존재하지 않으면 default 반환하므로,
카운트 누적할 때 유용하다.
pairs = [(2,'b'), (1,'a'), (3,'c')]
pairs.sort(key=lambda x: x[0]) # 첫번째 기준
pairs.sort(key=lambda x: x[1], reverse=True)
.sort()는 리스트에 직접 적용sorted()는 어떤 iterable에도 적용 가능 (문자열, dict 등)| 메서드 | 방향 | 예시 |
|---|---|---|
.strip() | 양쪽 | " hi ".strip() → "hi" |
.lstrip() | 왼쪽만 | " hi".lstrip() → "hi" |
.rstrip() | 오른쪽만 | "hi ".rstrip() → "hi" |
인자 지정 가능:
"000123".lstrip("0") → "123"
n = 3
array = [[0]*n for _ in range(n)]
for i in range(n):
array[i][i] = 1
결과:
[[1,0,0],
[0,1,0],
[0,0,1]]
주의: [[0]*n]*n은 같은 리스트 참조 복제라서 안 됨.
from collections import deque
directions = deque([(0,1), (1,0), (0,-1), (-1,0)])
directions.rotate(-1)
| 메서드 | 설명 |
|---|---|
.rotate(k) | 오른쪽으로 k만큼 회전 (음수면 왼쪽) |
.popleft() | 맨 앞 원소 제거 |
.appendleft(x) | 앞에 추가 |
행렬 달팽이 순회에서 rotate를 쓰는 이유:
현재 방향(오른→아래→왼→위)을 큐로 관리하고,
막히면 방향을 회전시켜 다음 이동 방향으로 전환하기 위함.
| 분류 | 핵심 키워드 |
|---|---|
| 문자열 | strip, split, join, find, rfind, lower, upper |
| 리스트 | append, sort, sorted, reverse, 슬라이싱 |
| dict | .keys, .values, .items, .get, defaultdict, Counter |
| 제어 | for, if, elif, else, any, all |
| 기타 | deque.rotate, 2D 배열 생성, divmod, enumerate |
좋다, 이건 deque(덱)의 작동 원리를 직접 눈으로 보는 게 제일 이해가 빠른 부분이다.
deque는 양쪽 끝에서 삽입/삭제가 가능한 큐고, rotate(k)는 덱을 k칸 회전시키는 함수다.
핵심은:
rotate(k)→ 오른쪽으로 k칸 이동,
rotate(-k)→ 왼쪽으로 k칸 이동
from collections import deque
d = deque(["→", "↓", "←", "↑"])
print("초기 상태:", list(d))
for k in [1, 2, 3, -1, -2, -3]:
temp = deque(d)
temp.rotate(k)
print(f"rotate({k:>2}) → {list(temp)}")
초기 상태: ['→', '↓', '←', '↑']
rotate( 1) → ['↑', '→', '↓', '←']
rotate( 2) → ['←', '↑', '→', '↓']
rotate( 3) → ['↓', '←', '↑', '→']
rotate(-1) → ['↓', '←', '↑', '→']
rotate(-2) → ['←', '↑', '→', '↓']
rotate(-3) → ['↑', '→', '↓', '←']
rotate(1) : 오른쪽 끝 요소 '↑'가 맨 앞으로 이동rotate(2) : 오른쪽에서 두 칸 밀림rotate(-1) : 왼쪽 끝 요소 '→'가 맨 뒤로 이동rotate(5)는 rotate(1)과 동일 (4칸짜리 덱이니까)rotate(-1)이 의미하는 것directions = deque([(0,1), (1,0), (0,-1), (-1,0)]) # → ↓ ← ↑
directions.rotate(-1)
print(directions)
# 결과: ↓ ← ↑ →
즉, 현재 방향이 오른쪽(→) 일 때 rotate(-1)을 하면
다음 방향이 아래(↓)가 되어 시계 방향으로 90도 회전한 것과 같다.
정리하자면:
| 명령 | 회전 방향 | 효과 |
|---|---|---|
.rotate(1) | 오른쪽으로 한 칸 | 시계 반대 방향 회전 |
.rotate(-1) | 왼쪽으로 한 칸 | 시계 방향 회전 (달팽이 문제에서 사용) |
.rotate(n) | n칸 오른쪽 이동 | 순환 이동 |
.rotate(-n) | n칸 왼쪽 이동 | 순환 이동 |
좋아, 이 둘은 파이썬 문자열/리스트 처리에서 거의 매일 쓰이는 핵심 함수들이야.
하나는 리스트 → 문자열을 합치는 메서드(.join),
다른 하나는 값의 위치(인덱스)를 찾는 메서드(.index).
둘 다 직관적이지만, 잘못 쓰면 헷갈리기 쉬워서 예시 중심으로 정리하겠다.
.join() — 여러 문자열을 하나로 합치기"구분자".join(리스트)
words = ["apple", "banana", "cherry"]
print("".join(words)) # applebananacherry
print(", ".join(words)) # apple, banana, cherry
print("-".join(words)) # apple-banana-cherry
text = "python"
chars = list(text) # ['p','y','t','h','o','n']
print(".".join(chars)) # p.y.t.h.o.n
result = "".join([str(x) for x in [1, 2, 3]])
print(result) # "123"
→ 숫자를 문자열로 바꾸고 이어붙일 때 자주 쓴다.
.index() — 값의 위치(인덱스) 찾기list.index(찾을값)
ValueError 발생.nums = [10, 20, 30, 20]
print(nums.index(20)) # 1 ← 첫 번째 20의 위치만 반환
text = "banana"
print(text.index("a")) # 1
.rindex() 사용 (오른쪽부터 검색).text = "banana"
print(text.rindex("a")) # 5
값이 없을 수도 있으면,
if value in list: 로 먼저 검사하거나 try-except 구문 사용.
if "z" in text:
print(text.index("z"))
else:
print("없음")
| 항목 | .join() | .index() |
|---|---|---|
| 목적 | 여러 문자열을 하나로 결합 | 리스트나 문자열에서 값의 위치 찾기 |
| 대상 | 문자열 리스트 | 문자열 또는 리스트 |
| 반환 | 하나의 문자열 | 정수(인덱스) |
| 주의 | 모든 요소는 문자열이어야 함 | 없으면 ValueError 발생 |
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
word = "KNU"
positions = [alphabet.index(c) for c in word]
print(positions)
# [10, 13, 20]
joined = "-".join(word)
print(joined)
# K-N-U
요약하자면
.join() → “리스트를 문자열로 묶는다.”.index() → “원소의 위치를 찾는다.”둘 다 데이터 구조를 “다루는 손” 역할을 한다 — 하나는 묶고, 하나는 찾는다.
좋다. 이제 너는 프로그래머스 Level 0의 거의 모든 문법을 건드렸어.
이제 22 ~ 28번은 리스트 슬라이싱 → 진법 변환 → 집합 연산 → itertools → 좌표이동 → 리스트 메서드 → 최빈값으로 이어지는 “기초 자료구조 응용편”이야.
아래는 각 문법의 정의 → 예시 → 주의점을 체계적으로 정리한 내용이다.
cipher[code-1::code]리스트[시작:끝:간격]
시작: 어디서부터 시작할지 (기본 0)끝: 어디까지 가져올지 (미포함)간격: step — 몇 칸씩 건너뛸지 (기본 1)s = [0,1,2,3,4,5,6,7,8,9]
print(s[1:4]) # [1,2,3]
print(s[1:9:3]) # [1,4,7]
print(s[::2]) # [0,2,4,6,8]
print(s[::-1]) # [9,8,7,6,5,4,3,2,1,0] ← 역순
즉,
cipher[code-1::code] → code-1 번째 원소부터 code 간격으로 끝까지 가져와라.
int(이진문자열, 2)
print(int("101", 2)) # 5
bin(숫자)
print(bin(5)) # '0b101'
print(bin(5)[2:]) # '101' ← '0b' 제외
def solution(bin1, bin2):
dec = int(bin1, 2) + int(bin2, 2)
return bin(dec)[2:]
|=, &A = {1,2,3}
B = {3,4,5}
| 연산 | 의미 | 결과 | |
|---|---|---|---|
| `A | B` | 합집합 | {1,2,3,4,5} |
A & B | 교집합 | {3} | |
A - B | 차집합 | {1,2} | |
A ^ B | 대칭차집합 | {1,2,4,5} |
| 연산 | 설명 | 예시 | ||
|---|---|---|---|---|
| `A | = B` | `A = A | B` | A에 B 합치기 |
A &= B | A = A & B | A를 교집합으로 갱신 |
answer |= set(range(a[0], a[1])) & set(range(b[0], b[1]))
→ 두 선분이 겹치는 구간의 교집합을 answer 에 합집합으로 누적.
itertools — 조합 / 순열 / 중복 조합 / 중복 순열from itertools import combinations, permutations, combinations_with_replacement, product
data = ['A','B','C']
| 함수 | 의미 | 예시 (k = 2) | 결과 |
|---|---|---|---|
combinations(data,k) | 조합(순서 무관, 중복 X) | AB, AC, BC | [('A','B'),('A','C'),('B','C')] |
permutations(data,k) | 순열(순서 중요, 중복 X) | AB, AC, BA, BC, CA, CB | [('A','B'), ...] |
combinations_with_replacement(data,k) | 중복 조합(순서 무관, 중복 O) | AA, AB, AC, BB, BC, CC | [('A','A'), ...] |
product(data, repeat=k) | 중복 순열(순서 중요, 중복 O) | AA, AB, AC, BA, BB, BC, CA, CB, CC | [('A','A'), ...] |
move = {
"up": (0, 1),
"down": (0, -1),
"left": (-1, 0),
"right": (1, 0)
}
| 방향 | 변화량(dx, dy) | 설명 |
|---|---|---|
| up | (0, 1) | y + 1, 위로 1칸 |
| down | (0, -1) | y – 1, 아래로 1칸 |
| left | (–1, 0) | x – 1, 왼쪽으로 1칸 |
| right | (1, 0) | x + 1, 오른쪽으로 1칸 |
경계 확인:
if -max_x <= nx <= max_x and -max_y <= ny <= max_y:
x, y = nx, ny
.remove()lst = ["a","b","c","b"]
lst.remove("b")
print(lst) # ['a','c','b']
ValueErrordel lst[i] 또는 lst.pop(i)문자열에는 .remove() 없다.
→ 문자열은 수정 불가(immutable).
replace() 나 슬라이싱으로 새로 만들어야 함.
def solution(array):
dic = {}
for i in array:
dic[i] = dic.get(i, 0) + 1
max_freq = max(dic.values())
mode = [k for k, v in dic.items() if v == max_freq]
return -1 if len(mode) > 1 else mode[0]
| 개념 | 설명 |
|---|---|
| 최빈값 | 데이터에서 가장 자주 등장하는 값 |
dic.get(i, 0)+1 | 존재 X 시 0부터 시작해서 카운트 누적 |
max(dic.values()) | 가장 큰 빈도 찾기 |
[k for k,v in dic.items() if v == max_freq] | 최대 빈도와 같은 값만 모으기 |
| 항목 | 핵심 키워드 | 주요 함수 | |
|---|---|---|---|
| 슬라이싱 | start:end:step | [::], [::-1] | |
| 진법변환 | 이진↔십진 | int(x,2), bin(x)[2:] | |
| 집합연산 | 합집합·교집합·차집합 | ` | , &, -, ^` |
| itertools | 조합/순열/중복 | combinations, permutations, product | |
| 좌표이동 | 방향 매핑 (dict) | "up": (0,1) 등 | |
| 리스트삭제 | .remove() vs pop() | 값 기준 vs 인덱스 기준 | |
| 최빈값 | dict 빈도계산 | .get(), max(), items() |