프로그래머스 Python Lv.0 평행 / 겹치는 선분의 길이
1. 평행
문제 설명
점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.
나의 풀이
def solution(dots):
if (dots[0][0]-dots[1][0]) / (dots[0][1]-dots[1][1]) == (dots[2][0]-dots[3][0]) / (dots[2][1]-dots[3][1]):
return "1"
elif (dots[0][0]-dots[2][0]) / (dots[0][1]-dots[2][1]) == (dots[1][0]-dots[3][0]) / (dots[1][1]-dots[3][1]):
return "1"
elif (dots[0][0]-dots[3][0]) / (dots[0][1]-dots[3][1]) == (dots[1][0]-dots[2][0]) / (dots[1][1]-dots[2][1]):
return "1"
else:
return "0"
어렵게 생각하기 싫어서 만들어낸 나의 손 코딩.. 하드 코딩..?
어차피 3가지 경우의 수만 나와서 3가지 조건을 만족하는 경우에는 return 1을 하고 그 외에는 0을 하도록 하였다.
평행의 공식은 (x1,y1) (x2,y2) (x3,y3) (x4,y4) 의 네 점의 좌표가 주어졌을 때 x1-x2 / y1-y2 == x3-x4 / y3-y4 를 만족하면 즉 두 선의 기울기가 동일하면 평행이라고 한다.
그 공식을 사용해서 풀었다.
2. 겹치는 선분의 길이
문제 설명
선분 3개가 평행하게 놓여 있습니다. 세 선분의 시작과 끝 좌표가 [[start, end], [start, end], [start, end]] 형태로 들어있는 2차원 배열 lines가 매개변수로 주어질 때, 두 개 이상의 선분이 겹치는 부분의 길이를 return 하도록 solution 함수를 완성해보세요.
lines가 [[0, 2], [-3, -1], [-2, 1]]일 때 그림으로 나타내면 다음과 같습니다.
선분이 두 개 이상 겹친 곳은 [-2, -1], [0, 1]로 길이 2만큼 겹쳐있습니다.
나의 풀이
def solution(lines):
from itertools import combinations as cb
list = []
for a in cb(range(3),2):
if lines[a[0]][0] < lines[a[1]][1] and lines[a[1]][0] < lines[a[0]][1]:
list.append([max(lines[a[0]][0] , lines[a[1]][0]) , min(lines[a[0]][1] , lines[a[1]][1])])
if len(list) != 0 and min(list)[1] > max(list)[0]:
result = max(list)[1] - min(list)[0]
elif len(list) != 0:
result = min(list)[1] - min(list)[0] +max(list)[1] - max(list)[0]
else :
result = 0
return result
combination 을 통해 0 , 1 , 2 에서 조합 ( 0,1/ 0,2 / 1,2 ) 를 뽑아내고
각각 lines의 첫번째 두번째 세번째 값에서 0번인덱스 1번인덱스로 나누어 비교하였다.
0번 인덱스의 값이 다른 요소의 1번인덱스 값보다 작고 반대로 다른 요소의 0번째 인덱스 값이 1번 인덱스보다 작으면
겹치는 부분이 있다.
예시 : (1,10) (2, 5) -> 1 < 5 , 2 < 10 이면 겹치는 부분이 있음 겹치는 부분(2,5)
예시 : (2,4) (5,8) -> 2 < 8 , 5 > 4 조건 만족 X 겹치는 부분 없음
따라서 겹치는 부분이 있을때의 0번째 인덱스들 중에서 큰값 , 1번 인덱스들 중에서 작은 값을 리스트 형태로 list 에 넣었다.
그 후 만약 리스트의 길이가 0보다 크고 즉 하나라도 겹치는 부분이 있으면 겹치는 부분의 길이를 구하는 것이다.
이때 나는 list의 max 값의 1번 인덱스 에서 list의 min 값의 0번 인덱스를 뺀 값을 result로 주었다.
그런데 이 때 채점 중 실패가 떠서 반례를 찾아보니
[[0, 10], [1, 3], [4, 7]] 가 lines일때 겹치는 부분의 모음인 list 에 [ [1,3] , [4,7] ] 이 있고 내 원래 계산 대로면 7-1 이 되어 6이 나오는 것이다. 이와같이 겹치는 부분에서도 겹치지 않으면 값이 다르게 나오는 것을 고려해서
만약 min(list)의 1번 인덱스 값이 max(list)의 0번 인덱스 값보다 크지 않으면 (3 < 4)
min(list)의 선분 길이와 max(list)의 선분 길이를 더한 값이 return 되도록 하였다.
다른사람 풀이 + 개선점
def solution(lines):
s1 = set(i for i in range(lines[0][0], lines[0][1]))
s2 = set(i for i in range(lines[1][0], lines[1][1]))
s3 = set(i for i in range(lines[2][0], lines[2][1]))
return len((s1 & s2) | (s2 & s3) | (s1 & s3))
set 집합 함수를 이용한 풀이이다.
우선 set을 통해 각각 세 선분의 시작부터 끝까지의 숫자들을 집합으로 담고 그 세개의 각각의 교집합을 구한 뒤에 그 합집합을 구한다. 즉 각각 겹치는 선분을 구한 뒤에 그 합을 구하는 것이다.