[복습]프로그래머스 Level0

Leejaegun·2025년 10월 5일

코딩테스트 시리즈

목록 보기
43/49

🧱 1️⃣ 개행·이스케이프 문자

문자열 안에서 특수기능을 하는 문자들.

표현의미예시 출력
\n줄바꿈 (newline)"a\nb"
a
b
\t탭 (4칸 공백)"A\tB"A B
\\역슬래시 자체 출력"C:\\path"C:\path
\', \"따옴표 자체 출력'He said: \'Hi\''

🔢 2️⃣ 숫자 연산과 divmod

  • / : 실수 나눗셈

  • // : 몫

  • % : 나머지

  • divmod(a, b)(몫, 나머지)를 한 번에 반환

    q, r = divmod(11, 3)
    # q=3, r=2

🔁 3️⃣ for문과 in

리스트, 문자열, range 등 반복 가능한 객체 순회.

for i in range(5):
    print(i)

→ 0 1 2 3 4


⚙️ 4️⃣ 조건문 if / elif / else

조건 분기 처리.

if x > 0:
    print("양수")
elif x == 0:
    print("0")
else:
    print("음수")

🧩 5️⃣ 문자열 더하기

  • 문자열끼리 + → 이어 붙임
  • 숫자 + 문자열 → ❌ 에러
  • 숫자를 문자열로 바꾸려면 str() 사용
int_val = 3
string_val = "3"
print(int_val + 10)       # 13
print(string_val + "10")  # "310"

🧮 6️⃣ .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))]

🔠 7️⃣ 문자열 검사 및 변환

메서드설명예시
.lower()소문자로 변환"ABC".lower()"abc"
.upper()대문자로 변환"abc".upper()"ABC"
.islower()모두 소문자인가"abc".islower()True
.isupper()모두 대문자인가"ABC".isupper()True
.isdigit()숫자인가"123".isdigit()True
.isalpha()알파벳인가"abc".isalpha()True

🔤 8️⃣ 출력 특수문자 처리

문자열 안에서 특수문자 출력 시 이스케이프 필요.

print("!@#$%^&*(\\'\"<>?:;)")

!@#$%^&*('"<>?:;)

  • \\ : 역슬래시 하나 출력
  • \', \" : 따옴표 문자 출력

✂️ 9️⃣ .strip().split()

함수기능예시
.strip()문자열 양쪽 공백 제거" hi ".strip()"hi"
.split()문자열을 구분자로 나눠 리스트로 반환"a b c".split()['a','b','c']

🔗 10️⃣ .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 등을 중심으로 핵심을 한눈에 보게 정리해줄게.
단순 문법이 아니라 “어떻게, 왜 그렇게 쓰는가”를 강조하겠다.


🧭 11. dictionary 기본 구조

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

defaultdict

from collections import defaultdict
cnt = defaultdict(int)  # 기본값 0으로 시작
cnt['a'] += 1

→ 존재하지 않는 key 접근 시 자동으로 초기화됨.


🧩 12. any() / all()

함수의미예시
any(iterable)하나라도 True면 Trueany([False, True, False]) → True
all(iterable)모두 True면 Trueall([True, True, False]) → False
# 숫자 안에 금지된 숫자 있으면 제외
not any(d in str(x) for d in ["1","2","3"])

📊 13. Counter

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는 리스트의 빈도 계산, 최빈값 찾기, 조합 문제 등에 최적.


🔁 14. reverse / reversed / sort / sorted

함수동작원본 변화반환
.reverse()리스트 뒤집기 (in-place)ONone
reversed(list)뒤집은 반복자 반환Xiterator
.sort()제자리 정렬ONone
sorted(list)새 정렬 리스트 반환Xlist
lst = [3,1,2]
lst.sort()          # [1,2,3]
new = sorted(lst)   # [1,2,3] (원본 유지)

📐 15. 슬라이싱

표현의미
a[::-1]역순
a[-n:]뒤에서 n개
a[::-2]2칸 간격으로 역순
s = "abcdef"
s[::-1]   # 'fedcba'
s[-3:]    # 'def'

🅰️ 16. rfind / rindex

함수설명차이
.rfind(sub)뒤에서부터 탐색, 없으면 -1안전
.rindex(sub)뒤에서부터 탐색, 없으면 ValueError예외 발생
s = "abcabc"
s.rfind("a")   # 3
s.rindex("a")  # 3

🧮 17. dict.get 예제

answer = {}
for s in ["hi","a","bb","hi"]:
    answer[len(s)] = answer.get(len(s), 0) + 1

get(key, default)존재하지 않으면 default 반환하므로,
카운트 누적할 때 유용하다.


🧩 18. sort와 sorted 구별 (key, lambda)

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

✂️ 19. strip / lstrip / rstrip

메서드방향예시
.strip()양쪽" hi ".strip()"hi"
.lstrip()왼쪽만" hi".lstrip()"hi"
.rstrip()오른쪽만"hi ".rstrip()"hi"

인자 지정 가능:

"000123".lstrip("0")"123"

🧮 20. N차원 정방행렬 만들기

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같은 리스트 참조 복제라서 안 됨.


🔄 21. deque와 rotate

from collections import deque

directions = deque([(0,1), (1,0), (0,-1), (-1,0)])
directions.rotate(-1)
메서드설명
.rotate(k)오른쪽으로 k만큼 회전 (음수면 왼쪽)
.popleft()맨 앞 원소 제거
.appendleft(x)앞에 추가

행렬 달팽이 순회에서 rotate를 쓰는 이유:
현재 방향(오른→아래→왼→위)을 큐로 관리하고,
막히면 방향을 회전시켜 다음 이동 방향으로 전환하기 위함.


🧭 22. 종합 요약

분류핵심 키워드
문자열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).
둘 다 직관적이지만, 잘못 쓰면 헷갈리기 쉬워서 예시 중심으로 정리하겠다.


🔗 1️⃣ .join() — 여러 문자열을 하나로 합치기

기본 구조

"구분자".join(리스트)
  • 문자열 리스트의 모든 요소를 지정한 구분자로 연결해 하나의 문자열을 만든다.
  • 리스트 내부의 요소는 반드시 문자열(str) 이어야 함.

예시

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"

→ 숫자를 문자열로 바꾸고 이어붙일 때 자주 쓴다.


🔍 2️⃣ .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 → 좌표이동 → 리스트 메서드 → 최빈값으로 이어지는 “기초 자료구조 응용편”이야.
아래는 각 문법의 정의 → 예시 → 주의점을 체계적으로 정리한 내용이다.


🧩 22️⃣ 슬라이싱 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 간격으로 끝까지 가져와라.


🔢 23️⃣ 이진수 ↔ 십진수 변환

① 이진수 → 십진수

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:]

🧮 24️⃣ 집합 연산과 |=, &

Python 집합(set)

A = {1,2,3}
B = {3,4,5}
연산의미결과
`AB`합집합{1,2,3,4,5}
A & B교집합{3}
A - B차집합{1,2}
A ^ B대칭차집합{1,2,4,5}

대입 연산자 버전

연산설명예시
`A= B``A = AB`A에 B 합치기
A &= BA = A & BA를 교집합으로 갱신

예시 (문제 24)

answer |= set(range(a[0], a[1])) & set(range(b[0], b[1]))

→ 두 선분이 겹치는 구간의 교집합을 answer 에 합집합으로 누적.


🔢 25️⃣ 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'), ...]

🧭 26️⃣ 이동 시뮬레이션 (up/down/left/right)

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

🗑️ 27️⃣ .remove()

리스트 요소 삭제

lst = ["a","b","c","b"]
lst.remove("b")
print(lst)  # ['a','c','b']
  • 첫 번째 일치값만 삭제
  • 값이 없으면 ValueError
  • 인덱스로 삭제할 때는 del lst[i] 또는 lst.pop(i)

문자열에는 .remove() 없다.
→ 문자열은 수정 불가(immutable).
replace() 나 슬라이싱으로 새로 만들어야 함.


📊 28️⃣ 최빈값 (mode) 구하기

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()
profile
Lee_AA

0개의 댓글