문제
https://www.acmicpc.net/problem/1105
이번엔 좀 쉬운 문제로 날먹하려고 가져 왔다.
1. 첫 번째 풀이
사고 과정
L 이상, R 이하 수 중에서, 8이 가장 적게 들어간 수의 8의 개수를 구하는 문제.
8을 안 쓸 수 있다면 안 쓴다. 아주 간단한 해법이다. 88과 89가 있다면, 89를 쓰면 된다. 즉, 웬만한 상황에서, 8을 안 써도 된다면 그냥 안 쓰면 된다. 자릿수를 전부 따로따로 보고, 8을 안 골라도 되면 안 고른다.
그럼 언제 8을 안 써도 될까? 이는 다음 2가지 경우가 있다.
- L과 R의 자리 중 하나라도 8이 아닐 때 (ex. 880과 889라면, 앞의 8 두개는 무조건 써야만 하지만, 맨 뒤는 8을 안 써도 된다)
- 둘 모두 8이더라도, 그 앞자리에 8이 아닐 때. (ex. 878과 888이면, 879를 고르면 된다.
요약하면, 맨 앞에서부터 비교하며 둘 다 8인 자리의 개수가 정답이 된다.
로직은 매우 심플. 중요한 건 구현. 파이썬을 쓸 거고, 문자열로 풀면 되는데, 중요한 건 자릿수 맞추기다.
간단히, 긴쪽을 기준으로 짧은 쪽의 왼쪽을 0으로 채우는 방법과, 짧은 쪽을 기준으로 긴쪽의 왼쪽을 잘라내는 방법이 있는데, 이번 문제는 0으로 채우면 그냥 끝이기 때문에 의미가 없다. (ex. 088과 888이면, 맨 왼쪽 자리부터 틀려서 정답은 0이다.)
그러면 딱히 자릿수 맞출 필요도 없이, 그냥 길이가 다르면 0을 반환하면 된다.
코드
import sys
l, r = input().split()
if len(l) != len(r):
print(0)
sys.exit()
i = 0
while i < len(l) and l[i] == '8' and r[i] == '8':
i += 1
print(i)
결과

하지만 백준은 만만하지 않았다. 일퀘 후딱 끝내고 Inspector 마저 개조하러 갈랬더니 쉽지 않네
2. 마지막 풀이
사고 과정
정답 비율이 32퍼인 이유가 나처럼 날먹하러 왔다가 실패해서 그런 게 아닐까.
반례를 이것저것 넣어보다 하나 발견했다. 8785와 8786. 이때 정답은 2인데, 내 코드로는 1이 나온다.
그렇다. 해당 자리가 8이 아니더라도, 같은 값이라면 그 숫자로 고정되고, 이후까지 살펴야 하는데 그걸 빼먹었다.
코드
import sys
l, r = input().split()
if len(l) != len(r):
print(0)
sys.exit()
count = 0
i = 0
while i < len(l) and l[i] == r[i]:
if l[i] == '8':
count += 1
i += 1
print(count)
count 변수를 추가해 8의 개수를 따로 세어줬다.
결과

다행히 더이상의 반례는 없었다. 저거도 안 됐으면 멘탈이 나가지 않았을까
개선
사고 과정
이번엔 코드를 좀 더 깔끔하게 쓸 방법을 강구해보자.
sys.exit()를 쓴 건 그냥 개인 취향으로, 매번 __name__ == "__main__" 쓰고 solve 감싸기 귀찮아서 적었다.
비교하는 부분을 좀 더 간편하게, l과 r 비교 후 겹치는 부분~ 같은 걸 써볼까 했는데, 앞에서부터 검사하며 l, r이 달라지면 즉시 종료하는 로직과는 많이 달라서 포기했다. (87879 87899에서 마지막 9가 같다는 게 문제가 될 것)
for문과 while문도, 처음에 for문으로 썼다가 if문 하나 더 쓰기 싫어서 바꾼 거기에 딱히 건드릴 게 없고....
일단은 지금이 최선인 것 같다. 다른 코드와 비교해보자.
가장 효율적인 코드
https://www.acmicpc.net/source/102399719
dhhae1120님의 코드. 이 문제의 로직은 다 거기서 거기라, 문법적으로 배울 게 많아서 가져왔다.
내 코드와 비교
따지자면 저분의 코드에도 개선할 점이 몇 가지 있다. input을 int로 매핑한 다음 다시 str로 매핑하는 부분이라거나, l과 r이 다를 때와 반복문이 끝났을 때를 따로 처리한 점 등등. 그런데, 그런 걸 감안해도 아래 코드는 배울만 하다.
1. 간편하게 빠른 입력 받기
input = sys.stdin.readline
아무래도 파이썬을 처음 접할 때, input을 쓰다보니 이게 편하다. 매번 입력받을 때마다 sys.stdin.readline을 일일이 치기엔 귀찮지 않나.
그런데 이분은 코드 상단에 해당 코드를 입력해둬서, input함수를 덮어씌워 버렸다.
두 함수 모두 string을 반환하기에 이후 split(), strip() 같은 함수를 쓸 때, 반환된 값을 다룰 때 거의 차이가 없다. 딱 하나, 문자열을 그대로 사용할 때 맨 뒤에 \n이 붙는다는 것만 인지하면, 편하고, 빠르게 문제를 풀 수 있다.
일종의, readline을 input처럼 쓰는 것이다.
2. exit() 함수 바로 사용하기
import sys
sys.exit() # 기존 내가 사용한 방식
exit() # dhhae1120님이 사용한 방식
처음엔 C#과 같다고 생각해서, exit()가 자동으로 sys.exit()로 해석되는 줄 알았다. 그런데 제미나이에게 물어본 결과, 파이썬은 import를 한 후에도 namespace를 명시해줘야 한다.
exit() 함수는 사실 sys의 exit()가 아니라, site의 exit() 함수다. 이는 쉘 자체를 종료시키는 함수로, 파이썬 개발에선 지양한다고 한다. 코테 수준에선 그게 그거 같긴 하다.
단순히 namespace 생략이면 줄여쓰려고 했었는데, 이러면 앞으로도 그냥 sys.exit를 사용할 것 같다. 변한 건 없지만 지식이 늘었으니 만족.
코드
import sys
input = sys.stdin.readline
l, r = input().split()
if len(l) != len(r):
print(0)
exit()
count = 0
i = 0
while i < len(l) and l[i] == r[i]:
if l[i] == '8':
count += 1
i += 1
print(count)
결과

어차피 10자리 문자열 2개 받는 거라 시간상 큰 차이는 없다. 메모리가 32 KB 늘었는데, 개행 문자만 늘었다면 2개니까 2 byte가 늘었을 텐데, 무언가 다른 차이가 또 있는 걸까.
강평
로직은 심플하지만 함정이 하나 있었던 문제. 그래도 어렵지 않게, 빨리 풀어낼 수 있었다. 예전에도 수학 문제만 편식했었는데, 요새도 빨리 끝내려면 수학 문제 위주로 푸는 경향이 남아 있다.
시간을 좀 여유롭게 두고 다른 문제도 풀어봐야겠지....
'코딩테스트 > 백준' 카테고리의 다른 글
| [백준/Python3] 25419번. 정수를 끝까지 외치자 (0) | 2026.02.11 |
|---|---|
| [백준/Python3] 14238번. 출근 기록 (0) | 2026.02.08 |
| [백준/Python3] 1024번. 수열의 합 (0) | 2026.02.02 |
| [백준/Python3] 1018번. 체스판 다시 칠하기 (0) | 2026.01.31 |
| [백준/Python3] 1075번. 나누기 (0) | 2026.01.24 |