Test/python

겹치는 선분의 길이 ( set , &, | )

soo15 2023. 4. 18. 22:16

 

[문제 설명]

선분 3개가 평행하게 놓여 있습니다. 

세 선분의 시작과 끝 좌표가 [[start, end], [start, end], [start, end]] 형태로 들어있는 

2차원 배열 lines가 매개변수로 주어질 때, 두 개 이상의 선분이 겹치는 부분의 길이를 

return 하도록 solution 함수를 완성해보세요.

lines가 [[0, 2], [-3, -1], [-2, 1]]일 때 그림으로 나타내면 다음과 같습니다.

선분이 두 개 이상 겹친 곳은 [-2, -1], [0, 1]로 길이 2만큼 겹쳐있습니다.

 

[제한사항]

  • lines의 길이 = 3
  • lines의 원소의 길이 = 2
  • 모든 선분은 길이가 1 이상입니다.
  • lines의 원소는 [a, b] 형태이며, a, b는 각각 선분의 양 끝점 입니다.
    -100 ≤ a < b ≤ 100

[입출력 예]

lines  result
[[0, 1], [2, 5], [3, 9]] 2
[[-1, 1], [1, 3], [3, 9]] 0
[[0, 5], [3, 9], [1, 10]] 8

 


[입출력 예 설명]

 

입출력 예 #1)
두 번째, 세 번째 선분 [2, 5], [3, 9]가 [3, 5] 구간에 겹쳐있으므로 2를 return 합니다.


입출력 예 #2)
겹친 선분이 없으므로 0을 return 합니다.


입출력 예 #3)
첫 번째와 두 번째 선분이 [3, 5] 구간에서 겹칩니다.
첫 번째와 세 번째 선분 [1, 5] 구간에서 겹칩니다.
두 번째와 세 번째 선분 [3, 9] 구간에서 겹칩니다.
따라서 [1, 9] 구간에 두 개 이상의 선분이 겹쳐있으므로, 8을 return 합니다.

 


 

[나의 풀이]

def solution(lines):
  
  # 1. range를 정수 list로 바꾸기
  list = []
  for line in lines:
    range_line = range(line[0], line[1])
    int_list = [int(i) for i in range_line]
    list.append(int_list)

  # 2. list를 set으로 바꾸기
  a = set(list[0])
  b = set(list[1])
  c = set(list[2])

  # 3. 교집합 찾아 개수 구하기
  return len((a & b) | (b & c) | (c & a))

[설명]

- 겹치는 길이를 구하는 대신에 겹치는 정수가 몇 개인지 구한다.

 

1. range를 정수 list로 바꾸기

lines = [[0, 5], [3, 9], [1, 10]]

list = []
for line in lines:
  range_line = range(line[0], line[1])
  int_list = [int(i) for i in range_line]
  print(int_list) 
  list.append(int_list)

print(list)

Out[1]:

[0, 1, 2, 3, 4]                     # list[0]   
[3, 4, 5, 6, 7, 8]                 # list[1]  
[1, 2, 3, 4, 5, 6, 7, 8, 9]     # list[2] 

[[0, 1, 2, 3, 4], [3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8, 9]]   # list

 

> range(0,5) 안에 있는 수를 정수로 나타내면 아래와 같이 나타낼 수 있다.

  [0, 1, 2, 3, 4]  

 

 

2. list를 set으로 바꾸기

a = set(list[0])
b = set(list[1])
c = set(list[2])

print(a)
print(b)
print(c)

Out[2]:

{0, -1}                     # set( list[0] )

{1, 2}                      # set( list[1] )

{3, 4, 5, 6, 7, 8}      # set( list[2] )

 

 

3. 교집합을 찾아 개수 구하기

print(len((a & b) | (b & c) | (c & a)))

Out[3]:

8

 

> 추가 설명

print('a & b = ', a&b)
print('b & c = ', b&c)
print('a & c = ', a&c)

print('(a & c) | (b & c) | (a & c) = ' , (a&c) | (b&c) | (a&c))
print('len((a & b) | (b & c) | (c & a)) = ', len((a & b) | (b & c) | (c & a)))

Out[4]:

a & b = {3, 4}

b & c = {3, 4, 5, 6, 7, 8}

a & c = {1, 2, 3, 4}

 

(a & c) | (b & c) | (a & c) = {1, 2, 3, 4, 5, 6, 7, 8}

len((a & b) | (b & c) | (c & a)) = 8

 

 


 

[다른 사람 풀이]

def solution(lines):
    
    # 1. range를 set으로 바꾸기
    sets = [set(range(min(l), max(l))) for l in lines]
    
    # 2. 교집합의 개수 구하기
    return len(sets[0] & sets[1] | sets[0] & sets[2] | sets[1] & sets[2])

[설명]

1. range를 set으로 바꾸기

lines = [[0, 5], [3, 9], [1, 10]]
sets = [set(range(min(l), max(l))) for l in lines]
print(sets)

Out[5]:

[{0, 1, 2, 3, 4}, {3, 4, 5, 6, 7, 8}, {1, 2, 3, 4, 5, 6, 7, 8, 9}]

 

> [나의 풀이]의 1. range를 정수 list로 바꾸기,  2. list를 set으로 바꾸기 과정을 한 줄로 정리하였다. 

> [나의 풀이]에서는 range를 list로 바꾸고 난 후 set으로 바꾸었는데

[다른 사람 풀이]에서는 range를 바로 set으로 바꾸어 list에 저장하였다.

 

 

2. 교집합의 개수 구하기

len(sets[0] & sets[1] | sets[0] & sets[2] | sets[1] & sets[2])

Out[6]:

8

 

> [나의 풀이]의 3. 교집합을 찾아 개수 구하기 설명 참고하면 쉽게 이해할 수 있을 것이다.

 

 


 

[다른 사람 풀이 수정]

def solution(lines):
    
    # 1. range를 set으로 바꾸기
    [a, b, c] = [set(range(min(l), max(l))) for l in lines]
    
    # 2. 교집합의 개수 구하기
    return len(a & b | a & c | b & c)

> [다른 사람 풀이]를 조금 더 간단하게 수정하였다.