모든 분기를 테스트 해보세요.
작성한 코드가 한 번에 내가 생각한 로직 그대로 올바르게 동작할 가능성은 그다지 크지 않습니다. 그렇기 때문에 코드가 무사히 컴파일이 되었다고 해도 한 번에 맞았습니다!를 받기는 어렵고, 예제가 강력하면 틀렸습니다를 받기 전에 스스로 고쳐볼 기회가 많아집니다. 하지만 예제는 예제일 뿐, 내 코드의 모든 취약점을 다 잡아줄 거라고 절대 기대할 수 없습니다. 결국 스스로 반례를 찾는 연습이 필요합니다. 이때 가장 먼저 해보면 좋을 것이 바로 모든 분기의 코드가 제대로 실행되는지 확인해보는 것입니다.
이를 연습해볼 수 있는 대표적인 문제, 주사위 세개를 예시로 들어보겠습니다. 간단한 로직이니, 내가 쓰는 언어가 아니라도 무서워하지 마세요.
a, b, c = map(int, input().split())
if a == b == c: # 모든 주사위가 같으면
print(10000 + a * 1000)
elif a == b != c: # a와 b가 같으면
print(1000 + a * 100)
elif a != b == c: # b와 c가 같으면
print(1000 + a * 100)
elif a == c != b: # a와 c가 같으면
print(1000 + b * 100)
else: # 모두 다르면
print(max(a, b) * 100)
이 코드는 예제가 모두 나오지만, 제출하면 틀리게 됩니다. 아... 예제가 나오는데 어떻게 반례를 찾을지 너무 막막하네요... 바로 질문 게시판으로 갈까요? 그러기 전에 스스로 문제점을 찾아봅시다.
우선 이 문제의 예제 3개가 어느 분기들에 걸리는지 각각 살펴봅시다.
- a와 b가 같은 분기
- 세 주사위가 모두 같은 분기
- 세 주사위가 모두 다른 분기
그러면 다섯 분기 중 세 개는 일단 테스트를 한 번씩은 했으니까, 나머지 두 개를 테스트 해봅시다. b와 c가 같은 분기는 답을 제대로 출력할까요?
음... 아쉽지만 틀리네요. 무엇이 잘못되었을까요? 해당 분기를 다시 볼까요?
elif a != b == c: # b와 c가 같으면
print(1000 + a * 100)
b와 c가 같으니 b나 c중 하나에 100을 곱해야 하는데 a에 곱한 실수가 있었네요. 이렇게 고치면 이제 이 케이스도 잘 나옵니다.
elif a != b == c: # b와 c가 같으면
print(1000 + b * 100)
다음은 a와 c가 같은 부분도 볼까요? 테스트를 돌려볼 것도 없이, 여기에도 똑같은 실수가 있습니다.
elif a == c != b: # a와 c가 같으면
print(1000 + b * 100)
여기도 b 대신 c로 고쳐줍시다.
elif a == c != b: # a와 c가 같으면
print(1000 + c * 100)
그런데 이렇게까지 고쳤는데도 여전히 제출하면 틀립니다. 대체 왜일까요?
디버깅을 할 때는 테스트를 여럿 넣어보는 것도 좋지만 코드 자체를 다시 한 줄 한 줄 복기하는 것이 무엇보다 중요합니다. 가장 마지막 줄을 볼까요?
else: # 모두 다르면
print(max(a, b) * 100)
분명 세 개의 수 중에 가장 큰 수를 골라야 하는데, c는 어디 가고 a랑 b 중에서만 고르고 있습니다. 여기에 c를 추가해 봅시다.
else: # 모두 다르면
print(max(a, b, c) * 100)
이제 모두 고친 이 버전을 제출하면 드디어 맞았습니다!를 받습니다.
a, b, c = map(int, input().split())
if a == b == c: # 모든 주사위가 같으면
print(10000 + a * 1000)
elif a == b != c: # a와 b가 같으면
print(1000 + a * 100)
elif a != b == c: # b와 c가 같으면
print(1000 + b * 100)
elif a == c != b: # a와 c가 같으면
print(1000 + c * 100)
else: # 모두 다르면
print(max(a, b, c) * 100)
이제 어떤 식으로 테스트를 해야 할지 감이 잡히나요?