Day 8 코딩테스트 공부 기록
프로그래머스 Day 8 조건문·문자열: 논리 연산부터 문자열 뒤집기까지
이번 Day 8은 조건문과 문자열을 함께 다루는 문제들이었습니다. 처음에는 문제가 짧아 보여도 막상 풀어보면 and, or, =와 ==, 문자열 누적, 슬라이싱, 리스트 변환처럼 헷갈리는 지점이 계속 나왔습니다.
특히 문자열 문제는 “문자열은 리스트처럼 중간을 바로 바꿀 수 없다”는 점을 이해하는 것이 중요했습니다. 그래서 이번 글은 정답 코드만 적기보다, 처음 헷갈린 코드와 왜 고쳐야 하는지를 같이 정리했습니다.
Day 8의 핵심은 “문제 문장을 파이썬 문법으로 정확히 옮기는 것”이었습니다.
이 글의 풀이 순서
- 문제 및 프로그래머스 공식 링크
- 내 풀이 또는 처음 헷갈린 코드
- 설명 및 잘못된 점
- 기본 수정 풀이
- 더 간단한 풀이와 설명
- 입출력 예로 검산하기
1. 문제 및 프로그래머스 공식 링크
이번 글에서 정리한 문제는 프로그래머스 코딩 기초 트레이닝 Day 8의 조건문, 문자열 문제입니다.
| 문제 | 공식 링크 | 핵심 개념 |
|---|---|---|
| 간단한 논리 연산 | 문제 보기 | boolean, and, or |
| 주사위 게임 3 | 문제 보기 | 조건 분기, 빈도수 |
| 글자 이어 붙여 문자열 만들기 | 문제 보기 | 인덱싱, 문자열 누적, join |
| 9로 나눈 나머지 | 문제 보기 | 문자열 순회, int, map |
| 문자열 여러 번 뒤집기 | 문제 보기 | 슬라이싱, 리스트 변환, 구간 뒤집기 |
2. 간단한 논리 연산: 수식을 그대로 코드로 옮기기
문제 요약
x1, x2, x3, x4가 주어질 때 (x1 or x2) and (x3 or x4)의 결과를 반환하면 됩니다. 문제 지문에서는 ∨가 OR, ∧가 AND를 뜻합니다.
처음 헷갈린 코드
def solution(x1, x2, x3, x4):
answer = True
if a == True and b == Ture:
a ∨ b = True
a ∧ b = True
elif a == True and b == False:
a ∨ b = False
a ∧ b = False
return answer
잘못된 점
Ture는 오타입니다. 파이썬에서는True처럼 정확히 써야 합니다.- 함수 입력은
x1,x2,x3,x4인데 코드 안에서는 정의되지 않은a,b를 사용했습니다. - 파이썬에서는
∨,∧대신or,and를 씁니다. a ∨ b = True처럼 연산 결과에 값을 대입할 수 없습니다. 결과를 변수에 담거나 바로 반환해야 합니다.- OR는 둘 중 하나만
True여도True입니다. 진리표를 직접 구현하기보다 파이썬 연산자를 그대로 쓰는 편이 정확합니다.
기본 수정 풀이
def solution(x1, x2, x3, x4):
return (x1 or x2) and (x3 or x4)
문제의 식을 그대로 파이썬 문법으로 바꾸면 됩니다. 괄호를 넣어두면 어떤 부분을 먼저 계산하는지 눈에 잘 들어옵니다.
더 짧은 풀이
def solution(x1, x2, x3, x4):
return (x1 | x2) & (x3 | x4)
|와 &도 boolean 값에서 OR, AND처럼 동작합니다. 다만 일반적인 조건식에서는 단축 평가가 되는 or, and가 더 익숙하고 안전합니다. 이 문제처럼 단순한 boolean 변수만 다룰 때는 위 풀이도 가능합니다.
3. 주사위 게임 3: 숫자 종류와 등장 횟수로 나누기
문제 요약
네 개의 주사위 숫자 a, b, c, d가 주어집니다. 네 숫자가 모두 같은지, 3개만 같은지, 2개씩 같은지, 2개만 같은지, 모두 다른지에 따라 점수 공식이 달라집니다.
처음 작성한 코드
def solution(a, b, c, d):
answer = 0
dice = [a, b, c, d]
if len(set(dice)) == 1:
answer == 1111 × a
elif len(set(dice)) == 4:
answer == min(set(dice))
elif len(set(dice)) == 2:
for i in range(1, 7):
if dice.count(i) == 2:
p, q = i
answer = (i) × |p - q|
return answer
잘못된 점
answer == 1111 * a는 비교입니다. 값을 저장하려면answer = 1111 * a처럼=하나를 써야 합니다.- 파이썬에서 곱하기는
×가 아니라*입니다. - 절댓값은 수학 기호
|p - q|가 아니라abs(p - q)로 계산합니다. p, q = i는 숫자 하나를 변수 두 개에 나누어 담으려는 코드라 에러가 납니다.len(set(dice)) == 2일 때는3개 + 1개와2개 + 2개를 다시 구분해야 합니다.
빈도수 배열을 활용한 풀이
def solution(a, b, c, d):
dice = [a, b, c, d]
counts = [dice.count(x) for x in dice]
if max(counts) == 4:
return 1111 * a
elif max(counts) == 3:
p = dice[counts.index(3)]
q = dice[counts.index(1)]
return (10 * p + q) ** 2
elif max(counts) == 2:
if min(counts) == 2:
p, q = set(dice)
return (p + q) * abs(p - q)
else:
q, r = [dice[i] for i in range(4) if counts[i] == 1]
return q * r
else:
return min(dice)
counts = [dice.count(x) for x in dice]는 각 주사위 숫자가 전체에서 몇 번 나왔는지를 같은 위치에 저장합니다. 예를 들어 [2, 5, 2, 6]이면 counts는 [2, 1, 2, 1]이 됩니다. 그래서 max(counts)만 봐도 4개가 같은지, 3개가 같은지, 2개가 같은지 큰 분기를 나눌 수 있습니다.
다른 풀이에서 eval('*'.join(...))처럼 문자열을 코드로 실행하는 방식이 보일 수 있습니다. 하지만 이 문제에서는 1번 나온 두 숫자 q, r을 뽑아 q * r로 직접 계산하면 충분합니다. eval()은 문자열을 실제 코드처럼 실행하기 때문에 안전성과 가독성 면에서 추천하지 않습니다.
Counter를 활용한 풀이
from collections import Counter
def solution(a, b, c, d):
dice = [a, b, c, d]
counts = Counter(dice).most_common()
if len(counts) == 1:
p = counts[0][0]
return 1111 * p
elif len(counts) == 2:
if counts[0][1] == 3:
p = counts[0][0]
q = counts[1][0]
return (10 * p + q) ** 2
else:
p = counts[0][0]
q = counts[1][0]
return (p + q) * abs(p - q)
elif len(counts) == 3:
q = counts[1][0]
r = counts[2][0]
return q * r
else:
return min(dice)
Counter(dice).most_common()은 숫자와 등장 횟수를 많이 나온 순서대로 정리해 줍니다. 주사위 게임 3처럼 “몇 번 등장했는가”가 핵심인 문제에서는 조건문을 훨씬 읽기 좋게 만들 수 있습니다.
4. 글자 이어 붙여 문자열 만들기: 인덱스에 해당하는 글자만 모으기
문제 요약
my_string에서 index_list에 들어 있는 인덱스의 글자를 순서대로 꺼내 이어 붙이면 됩니다.
내 풀이
def solution(my_string, index_list):
answer = ''
for i in index_list:
answer += my_string[i]
return answer
이 풀이는 정답입니다. answer가 빈 문자열이기 때문에 answer += my_string[i]로 문자를 이어 붙일 수 있습니다. 다만 여기서 헷갈렸던 부분은 “왜 append()는 안 되고 +는 되는가?”였습니다.
문자열에는 append()가 없습니다. append()는 리스트 전용 메서드입니다. 문자열을 하나씩 붙일 때는 +를 사용할 수 있지만, 반복 횟수가 많아질수록 매번 새 문자열을 만드는 방식이라 비효율적일 수 있습니다. 그래서 여러 글자를 모을 때는 리스트에 담고 마지막에 join()으로 합치는 패턴을 자주 씁니다.
리스트와 join을 활용한 기본 풀이
def solution(my_string, index_list):
answer = []
for i in index_list:
answer.append(my_string[i])
return ''.join(answer)
더 간단한 풀이
def solution(my_string, index_list):
return ''.join(my_string[idx] for idx in index_list)
index_list에서 인덱스 idx를 하나씩 꺼내고, my_string[idx]로 해당 위치의 글자를 가져옵니다. 그렇게 나온 글자들을 ''.join(...)으로 빈틈없이 이어 붙이면 됩니다.
5. 9로 나눈 나머지: 큰 숫자는 문자열 그대로 순회하기
문제 요약
문자열 number로 매우 큰 수가 주어집니다. 숫자를 9로 나눈 나머지는 각 자리 숫자의 합을 9로 나눈 나머지와 같으므로, 한 글자씩 정수로 바꿔 더한 뒤 9로 나누면 됩니다.
내 풀이
def solution(number):
a = list(number)
answer = 0
for char in a:
answer += int(char)
ans = answer % 9
return ans
보완할 점
list(number)는 없어도 됩니다. 문자열은 그대로for char in number처럼 순회할 수 있습니다.ans = answer % 9를 반복문 안에서 매번 계산할 필요가 없습니다. 모든 자리 숫자를 더한 뒤 마지막에 한 번만 계산하면 됩니다.- 문제에서
number의 길이가 최대 100,000이므로,int(number) % 9처럼 전체 문자열을 한 번에 정수로 바꾸는 방식은 피하는 편이 안전합니다.
기본 수정 풀이
def solution(number):
answer = 0
for char in number:
answer += int(char)
return answer % 9
더 간단한 풀이
def solution(number):
return sum(map(int, number)) % 9
map(int, number)는 문자열의 각 글자에 int를 적용합니다. 예를 들어 "123"이면 1, 2, 3으로 바뀌고, sum()이 이 값들을 모두 더합니다. 마지막으로 % 9를 붙이면 9로 나눈 나머지가 됩니다.
6. 문자열 여러 번 뒤집기: 구간을 자르고 뒤집고 다시 붙이기
문제 요약
queries의 각 원소는 [s, e]입니다. 각 쿼리마다 my_string의 s번 인덱스부터 e번 인덱스까지를 뒤집어야 합니다.
처음 작성한 코드
def solution(my_string, queries):
for char in queries:
for s, e in char:
my_string[s:e] == my_string[e:s]
return my_string
잘못된 점
queries는[[2, 3], [0, 7]]처럼 들어오므로for s, e in queries:한 번으로 꺼내면 됩니다. 이중 반복문을 쓰면 숫자 하나를s,e로 나누려 해서 에러가 납니다.==는 비교입니다. 문자열을 바꾸려면 새 문자열을 만들어=로 다시 저장해야 합니다.my_string[e:s]라고 쓴다고 문자열이 거꾸로 뒤집히지 않습니다. 뒤집기는[::-1]을 사용합니다.- 슬라이싱에서 끝 인덱스는 포함되지 않으므로
e까지 포함하려면s:e+1로 잘라야 합니다. - 문자열은 불변 자료형이라 중간 일부만 바로 교체할 수 없습니다. 앞부분, 뒤집은 중간 부분, 뒷부분을 새로 이어 붙여야 합니다.
기본 수정 풀이
def solution(my_string, queries):
for s, e in queries:
my_string = my_string[:s] + my_string[s:e+1][::-1] + my_string[e+1:]
return my_string
핵심은 문자열을 세 조각으로 나누는 것입니다. my_string[:s]는 앞부분, my_string[s:e+1][::-1]는 뒤집을 부분, my_string[e+1:]는 뒷부분입니다. 이 세 조각을 다시 붙이면 쿼리 하나가 처리됩니다.
리스트로 바꾼 더 깔끔한 풀이
def solution(my_string, queries):
answer = list(my_string)
for s, e in queries:
answer[s:e+1] = answer[s:e+1][::-1]
return ''.join(answer)
문자열은 직접 수정할 수 없지만 리스트는 구간을 통째로 바꿀 수 있습니다. 그래서 처음에 list(my_string)으로 바꾼 뒤, answer[s:e+1] 구간을 뒤집은 리스트로 교체하고, 마지막에 ''.join(answer)로 다시 문자열로 합칩니다.
7. 입출력 예로 빠르게 검산하기
| 문제 | 예시 입력 | 기대 결과 |
|---|---|---|
| 간단한 논리 연산 | False, True, True, True |
True |
| 주사위 게임 3 | 4, 1, 4, 4 |
1681 |
| 글자 이어 붙여 문자열 만들기 | "zpiaz", [1, 2, 0, 0, 3] |
"pizza" |
| 9로 나눈 나머지 | "78720646226947352489" |
2 |
| 문자열 여러 번 뒤집기 | "rermgorpsam", [[2,3],[0,7],[5,9],[6,10]] |
"programmers" |
8. 실수 방지 체크리스트
=는 대입,==는 비교다.- 논리 연산은 수학 기호 대신
and,or를 먼저 떠올린다. - 값이 몇 번 등장했는지 볼 때는
count()나Counter를 활용한다. - 문자열에는
append()가 없다. 여러 글자를 모을 때는 리스트에 담고join()을 쓴다. - 문자열을 한 글자씩 순회할 때 굳이
list()로 바꾸지 않아도 된다. - 슬라이싱의 끝 인덱스는 포함되지 않는다.
e까지 포함하려면e+1을 쓴다. - 문자열 뒤집기는
[::-1]을 사용한다. - 문자열은 불변 자료형이므로, 여러 번 수정해야 하면 리스트로 바꾸는 방법을 고려한다.
eval()은 문자열을 코드로 실행하므로, 코딩테스트 풀이에서도 가능한 한 피한다.
9. 같이 보면 좋은 글
- 파이썬 논리 연산자 정리:
and,or, 단축 평가가 헷갈릴 때 같이 보면 좋습니다. - 파이썬 문자열 슬라이싱:
s:e+1,[::-1]패턴을 연습하기 좋습니다. - join과 문자열 누적 차이: 문자열을 여러 번 이어 붙이는 문제에서 자주 나옵니다.
- Counter와 빈도수 문제: 주사위 게임 3처럼 등장 횟수로 조건을 나누는 문제와 연결됩니다.
마무리
Day 8은 조건문과 문자열 기본기를 한 번에 점검하기 좋은 날이었습니다. 논리 연산은 문제의 식을 그대로 코드로 옮기면 되고, 주사위 문제는 숫자 종류와 등장 횟수로 나누면 복잡한 조건도 정리됩니다.
문자열 문제에서는 append(), join(), map(), 슬라이싱을 언제 쓰는지 구분하는 연습이 중요했습니다. 특히 문자열은 직접 수정할 수 없기 때문에, 구간을 여러 번 바꾸는 문제에서는 리스트로 변환하는 풀이가 훨씬 깔끔하게 느껴졌습니다.
'AI > Coding_Test' 카테고리의 다른 글
| Day 7) 프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리 (0) | 2026.07.12 |
|---|---|
| Day 6)Programmers Coding Test (0) | 2026.07.11 |
| Day5) Programmers Coding Test (0) | 2026.07.11 |
| Day4)Programmers Coding Test (0) | 2026.07.08 |
| Day3) Programmers Coding Test (0) | 2026.07.08 |