[Python]BAEKJOON 1002번 터렛
https://www.acmicpc.net/problem/1002
1002번: 터렛
각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.
www.acmicpc.net
문제
조규현과 백승환은 터렛에 근무하는 직원이다. 하지만 워낙 존재감이 없어서 인구수는 차지하지 않는다. 다음은 조규현과 백승환의 사진이다.

이석원은 조규현과 백승환에게 상대편 마린(류재명)의 위치를 계산하라는 명령을 내렸다. 조규현과 백승환은 각각 자신의 터렛 위치에서 현재 적까지의 거리를 계산했다.
조규현의 좌표 (x1, y1)와 백승환의 좌표 (x2, y2)가 주어지고, 조규현이 계산한 류재명과의 거리 r1과 백승환이 계산한 류재명과의 거리 r2가 주어졌을 때, 류재명이 있을 수 있는 좌표의 수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 이루어져 있다.
한 줄에 x1, y1, r1, x2, y2, r2가 주어진다. x1, y1, x2, y2는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이고, r1, r2는 10,000보다 작거나 같은 음이 아닌 정수이다.
출력
각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.
예제 입력 1
3
0 0 13 40 0 37
0 0 3 0 7 4
1 1 1 1 1 5
예제 출력 1
2
1
0
1) 위 그림에서 교점이 무한대인 경우(류재명이 있을 수 있는 위치의 개수가 무한대일 경우)는 1(두 원의 반경이 완전히 겹치는 경우)에 한정된다. print(-1)
2) 다음, 교점이 존재하지 않는 경우(류재명이 있을 수 있는 위치의 개수가 0)가 2번과 6번이다.
참고로 이 경우는 이석원과 조규현 중 적어도 한 명이 류재명의 위치를 잘못 계산했음을 의미한다. 필자는 2번을 고려하지 않고 코드를 짰다가 제출과 동시에 '틀렸습니다'를 남발했다. print(0)
3) 또한 교점이 한 개인 경우는 두 반경이 접하는 경우로, 3(내접)과 5(외접)가 있다. print(1)
4) 마지막으로 교점이 두 개인 경우는 4번이 유일하다. print(2)
462B 40M Sol 1
import sys
input = sys.stdin.readline
import math
for i in range(int(input())):
a,b,c,d,e,f = list(map(int,input().split()))
dis =math.sqrt((a-d)**2+(b-e)**2)
if a == d and b == e and c == f: print(-1) # 1.완전히 겹침
elif max(c,f) > dis + min(c,f): print(0) # 2.안겹치도록 포함
else:
if max(c,f) == dis + min(c,f): print(1) # 3. 내접
elif dis < c+f:print(2) # 4.두 점
elif dis == c+f: print(1) # 5. 외접
elif dis > c+f: print(0) # 6. 바깥
416B 48ms Sol2
import sys
input = sys.stdin.readline
import math
for i in range(int(input())):
a,b,c,d,e,f = list(map(int,input().split()))
dis =math.sqrt((a-d)**2+(b-e)**2)
if a == d and b == e and c == f: print(-1) # 1.완전히 겹침
elif max(c,f) > dis + min(c,f): print(0) # 2.안겹치도록 포함
elif max(c,f) == dis + min(c,f): print(1) # 3. 내접
elif dis < c+f:print(2) # 4.두 점
elif dis == c+f: print(1) # 5. 외접
elif dis > c+f: print(0) # 6. 바깥
이 문제의 핵심은 '우선순위'다. Sol2를 보면 if 와 elif만으로 코드를 구성했다. 1,2,3의 조건들을 보면 하나같이 조건이 길고 구체적이다. 분명하게 조건을 명시하고 있기 때문에 해당 조건에 딱 맞는 경우가 먼저 걸러져 나간다. 이에 비해, 조건 4,5,6은 구체적이지 않다. 무슨 말인지 와닿지 않을텐데, 필자가 잘못 짠 다음의 코드를 보면 쉽게 알 수 있다.
실패 Try - '틀렸습니다.'
import sys
input = sys.stdin.readline
import math
for i in range(int(input())):
a,b,c,d,e,f = list(map(int,input().split()))
dis =math.sqrt((a-d)**2+(b-e)**2)
if a == d and b == e and c == f: print(-1) # 1.완전히 겹침
elif max(c,f) > dis + min(c,f): print(0) # 2.안겹치도록 포함
else:
if dis < c+f:print(2) # 4.두 점
elif max(c,f) == dis + min(c,f): print(1) # 3. 내접
elif dis == c+f: print(1) # 5. 외접
elif dis > c+f: print(0) # 6. 바깥
다른 건 그대론데, else문 아래, '4. 두 점'과 '3. 내접'의 순서가 뒤바뀌었다. 앞서 설명했듯, 1,2,3은 그 조건이 매우 명시적인 반면, 4,5,6은 조건이 다소 모호하다. 따라서 위 try코드는 다음의 입력값에 대해 잘못된 출력값을 내놓는다.
INPUT
2
0 0 3 2 0 1
FALSE OUPUT
2
실제 정답
1
이런 까닭은, 해당 INPUT이 '3.내접'하는 특수한 케이스인데, '4.두 점'조건도 만족하기 때문이다. 따라서 명시적 조건이 모호한 조건에 비해 선행되어야 함을 알 수 있다.