[시작]
참여 기간 : 2025/03/31 ~ 2025/04/28
참여 난이도 : 파이썬 / 비기너
⏳ 코테 스터디 진행도 🧱 : [▰▰▰▰▰░ ] 3/29일 (10%)
본 글에서 다룬 문제 : 백준 31458번
문제 푸는 데 걸린 시간 : 28분
[오늘의 문제]
오늘의 문제는 백준 31458번
예상대로 초콜릿이랑 아무 상관없었다 ㅎㅎ;
[문제 분석]
수식의 개수 T가 주어짐
T개의 수식이 한줄에 하나씩 입력
하나의 수식은 a개의 느낌표, 정수 n, b개의 느낌표가 공백 없이 순서대로 합쳐진 형태
물론 정수n은 0 혹은 1 임
n! 은 팩토리얼인데 0! 1! 둘 다 결과가 1 임
!n은 논리 반전이여서 !0 =1, !1=0이라 보면 됨
팩토리얼이나 논리 반전이 중첩되어 있으면 중첩된 횟수만큼 계산
대신 우선순위는 팩토리얼이 먼저
[의사 코드]
- 입력
- 수식의 개수 T 입력
- T개의 수식을 하나씩 입력
- 느낌표 개수 계산
- 문자열 왼쪽 느낌표 개수 a
- 문자열 오른쪽 느낌표 개수 b
- 숫자 부분
- 전제 수식에서 느낌표 a와 b만큼을 제외한 부분이 숫자
- 오른쪽 느낌표가 있을 경우와 없을 경우를 구분하여 숫자 추출해야 함
- 정수 변환
- 추출한 숫자 문자열을 정수로 변환
- 팩토리얼 적용
- 오른쪽 느낌표가 하나 이상 있으면 팩토리얼 연산 적용
- 결과는 1로 동일
- 논리 반전 적용
- 왼쪽 느낌표의 개수만큼 반복해서 현재 값을 논리 반전
- 출력
- 최종적으로 계산된 값을 출력
[의사 코드를 실제 코드로 구현]
import sys
import math
T = int(sys.stdin.readline().strip())
for _ in range(T):
expr = sys.stdin.readline().strip()
a = len(expr) - len(expr.lstrip('!'))
b = len(expr) - len(expr.rstrip('!'))
if b > 0:
number_str = expr[a:-b]
else:
number_str = expr[a:]
n = int(number_str)
if b > 0:
n = math.factorial(n)
for _ in range(a):
n = 1 if n == 0 else 0
print(n)
★ 코드 설명 ★
- math 모듈
- 팩토리얼 계산을 위해 사용
- math.factorial
- for문
- T개의 수식을 처리하기 위해 사용
- expr = sys.stdin.readline().strip()
- 각 수식을 한 줄씩 읽어옴
- 수식이어서 expr로 변수명 적음
- a = len(expr) - len(expr.lstrip('!'))
- expr.lstrip('!')는 문자열의 왼쪽에서 모든 느낌표를 제거한 문자열을 반환
- 어제 TIL에서 메서드 정리할 때 다뤘음(여기서 써먹네)
- 원래 문자열 길이 - 왼쪽 모든 느낌표 제거한 문자열 길이
- 왼쪽에 몇 개의 느낌표가 있는지 알 수 있음
- a는 즉 왼쪽에 있는 느낌표 개수이고 나중에 논리 반전 연산에서 사용할 거임
- expr.lstrip('!')는 문자열의 왼쪽에서 모든 느낌표를 제거한 문자열을 반환
- b = len(expr) - len(expr.rstrip('!'))
- expr.rstrip('!')는 문자열의 오른쪽에서 모든 느낌표를 제거한 문자열을 반환
- 원래 문자열 길이 - 오른쪽 모든 느낌표 제거한 문자열 길이
- 오른쪽에 몇 개의 느낌표가 있는지 알 수 있음
- b는 오른쪽에 있는 느낌표 개수이고 팩토리얼 연산을 적용할 횟수 결정
- 숫자 부분 추출
- 수식은 왼쪽과 오른쪽에 느낌표로 둘러싸인 구조
- if b > 0:
- 오른쪽에 느낌표가 있다면, 숫자 부분은 왼쪽 a개의 느낌표를 제외하고 뒤쪽 b개의 느낌표를 제외한 부분
- number_str = expr[a:-b]
- else:
- 오른쪽에 느낌표가 없으면 숫자 부분은 왼쪽의 느낌표만 제외한 뒤 나머지 전부
- expr[a:]
- n = int(number_str)
- 추출한 숫자를 정수로 변환
- 팩토리얼 처리
- if b > 0: 에서 오른쪽에 느낌표가 하나 이상 있다면 팩토리얼 연산 적용
- n = math.factorial(n) 로 계산하는데 결과는 1로 고정이긴 함
- 사실 팩토리얼 함수 안 써도 푸는데 문제가 없다! 근데 다른 문제에서는 써야 할 수도 있으니 써봤음
- 논리 반전
- for _ in range(a):를 사용해서 왼쪽 느낌표의 개수만큼 논리 반전 연산 수행
- n = 1 if n == 0 else 0
- 최종 결과 출력 print(n)
[제출 결과]
[실수한 부분]
vs code에서 CPH Judge로 돌려보고 맞으면 제출
저 코드가 나오기 전에 4번 정도 오답이었다.
- 한 줄만 처리하는 코드로 작성해서 오답 (여러 줄 입력인데)
- 문자열 슬라이싱으로 수정하는데 인덱스가 꼬였음
- 수식의 구조를 제대로 분리 못함 (단순 문자 단위로 처리하려 했음ㅠ)
- 마지막엔 출력을 잘못함 ㅎㅎ;
원래 코드는 중첩 반복문을 사용했고 for문 while문 골고루 썼다.
근데 가독성이 너무 안 좋아서 지우고 다시 작성했음
[다른 코드]
백준에서 다른 분이 제출한 코드를 가져와봤다.
import sys
input = sys.stdin.readline
for _ in range(int(input())):
s = input().strip()
num = '0' if '0' in s else '1'
# parts = s.split(num) #숫자 기준으로 리스트로 나누기 ['!!', '!!']
left_n = s.split(num)[0].count('!')
right_n = s.split(num)[1].count('!')
if right_n > 0:
num = '1'
if left_n % 2 == 1:
num = '0' if num == '1' else '1'
print(num)
# 만약 오른쪽에 !이게 있으면 무조건 1로 바꾸기
# 그 다음 왼쪽에 !가 홀수면 반전(0->1, 1->0) 짝수면 그대로
내 코드와 뭐가 다른지 살펴보면
- 문자열 분리 방식이 다름
- 나 : 앞뒤 느낌표 개수를 lstrip(), rstip()을 사용해 계산하고 슬라이싱으로 숫자 부분 추출
- 이 코드 : split(num)을 사용해서 숫자를 기준으로 왼쪽 오른쪽 느낌표를 한 번에 분리한 뒤 count('!')로 개수 확인
- 팩토리얼 연산 부분이 다름
- 나 : 팩토리얼 함수를 이용
- 이 코드 : 오른쪽에 느낌표가 있으면 바로 num을 '1'로 만들었음
[마무리]
어렵다 어려워... 파이썬 문법 부분 지식이 부족하다 느낀다.
수학 공식 모르는데 문제 어찌어찌 풀어보려 하는 느낌
'스파르타 코딩클럽 > 99클럽 코딩테스트 스터디 6기' 카테고리의 다른 글
99클럽 코테 스터디 6일차 TIL [04/07] (0) | 2025.04.07 |
---|---|
99클럽 코테 스터디 5일차 TIL [04/04] (0) | 2025.04.05 |
99클럽 코테 스터디 4일차 TIL [04/03] (0) | 2025.04.03 |
99클럽 코테 스터디 2일차 TIL [04/01] (0) | 2025.04.01 |
99클럽 코테 스터디 1일차 TIL [03/31] (0) | 2025.03.31 |