본문 바로가기
[JavaScript]

[javascript] 겹치는 구간 찾기 & map의 활용

by 쥰5017 2022. 8. 24.

수직선 상에 A구간과 B구간이 있을 때 두 구간이 겹치는 범위를 출력하는 문제.

input은 A구간의 시작점종료점, B구간의 시작점종료점 순서로 입력되며

두 구간의 공통 부분은 배열로 출력된다.

공통 부분이 없는 경우 X를 출력한다.

input output
3
5
7
9
[5,7]
0
10
3
8
[3,8]
7
9
0
3
X

 

 

1. 맨 처음 한 것은 주어진 input을 다루기 좋게 잘라 배열에 넣어준 것이다.

newarr를 따로 생성한 것은 input이 작은 수 구간부터 차례대로 되어 있지 않아서 (표에서 세 번째 케이스와 같이) 작은 쪽 구간부터 순서를 잡아주려고 newarr를 생성했다.

function solution(input) {

  const mapfn = x => Number(x);
  var arr = [];
  var newarr = [];    

  arr = input.split('\n').map(mapfn);
  
  return;
  }

이 코드를 쓰면서 새롭게 배운 것이 map의 활용이다. 그동안 split을 사용하면서 요소들이 문자열로 저장되는 것이 불편했는데 map을 사용하여 문자열을 숫자형 요소로 저장할 수 있게 되었다.

 

위의 코드는 처음 사용해보는 거라 mapfn을 따로 설정해 주었는데,

아래와 같이 map()에 직접 써주어도 된다. 간단하고 기억하기 쉬워 참 좋다.

  arr = input.split('\n').map(x => Number(x));

 

 

2. 그 다음으로는 arr에 저장된 두 구간을 앞쪽 구간과 뒤쪽 구간으로 분류하여 순서대로 재정비해주었다.

(세 번째 input의 경우 arr = [7, 9, 0, 3]이었다가 newarr = [0, 3, 7, 9]가 되는 것이다.)

if (arr[0] < arr[2]) {
      newarr = arr;
  } else {
      newarr = [arr[2], arr[3], arr[0], arr[1]];
  }

 

 

newarr에 저장하지 않고 arr을 순서대로 수정하는 방법은 없나? 없을리가 없는데 아직 잘 모르겠다. 아마도 연결리스트 강의를 들을 때 노드 간 값을 이동해 주던 그 방법이면 될 것 같은데, 아직 완전히 익숙해지지가 않았고, 사용하기가 어렵다... 그래도 newarr를 생성하는 것보단 나을 것 같기도 하여, 다음에 시도해봐야겠다.

 

 

3. 수직선에서 공통 구간 구하기? > 4가지 케이스만 고려하면 된다.

1)두 구간이 만나지 않을 때   2)두 구간이 한 점만 겹칠 때   3)두 구간이 적당히 겹칠 때   4)한 구간이 다른 구간을 모두 덮을 때

 

if (newarr[1] < newarr[2]) {  //1번 케이스
      return 'X';
  } else if (newarr[1] == newarr[2]) {  //2번 케이스
      return [newarr[1]];
  } else if (newarr[1] > newarr[2] && newarr[3] > newarr[1]) {  //3번 케이스
      return [newarr[2], newarr[1]];
  } else if (newarr[1] >= newarr[3]) {  //4번 케이스
      return [newarr[2], newarr[3]];
  }

2번 케이스의 경우는 한 점만 답으로 출력해야 맞다. 3번 케이스의 경우 조건에 newarr[3] > newarr[1]를 넣지 않으면 4번 케이스와 조건이 중첩되어 답이 제대로 나오지 않는다.

 

 

 

마무리.

function solution(input) {

  const mapfn = x => Number(x);
  var arr = [];
  var newarr = [];    

  arr = input.split('\n').map(mapfn);
  
  if (arr[0] < arr[2]) {
      newarr = arr;
  } else {
      newarr = [arr[2], arr[3], arr[0], arr[1]];
  }

  if (newarr[1] < newarr[2]) {
      return 'X';
  } else if (newarr[1] == newarr[2]) {
      return [newarr[1]];
  } else if (newarr[1] > newarr[2] && newarr[3] > newarr[1]) {
      return [newarr[2], newarr[1]];
  } else if (newarr[1] >= newarr[3]) {
      return [newarr[2], newarr[3]];
  }
}

newarr를 사용한 것, 케이스를 일일이 쪼갠 것. 두 가지가 맘에 들지 않는다. 특히 배열을 두 개나 사용한 것은 배열 문제를 풀 때마다 자주 사용하는 방법인데, 아직 배열에 익숙지 않고 (특히 '재할당'에) 좀 더 간단한 방법을 떠올리는 게 어려워서 그렇다. 

 

댓글