점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
- [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.
제한사항
const isParallel = (dot) => {
let [dot1, dot2, dot3, dot4] = dot;
// dot1과 dot2를 이은 선분의 기울기
let line1 = Math.abs(dot2[1]-dot1[1]) / Math.abs(dot2[0] - dot1[0]);
// dot3과 dot4를 이은 선분의 기울기
let line2 = Math.abs(dot4[1]-dot3[1]) / Math.abs(dot4[0]-dot3[0]);
return line1 === line2 ? true : false;
}
function solution(dots) {
// x좌표를 기준으로 배열을 정렬하기
let x = dots.sort((a, b) => {
a = a[0];
b = b[0];
return a - b;
});
// y좌표를 기준으로 배열을 정렬하기
let y = dots.sort((a, b) => {
a = a[1];
b = b[1];
return a - b;
});
return isParallel(x) ? 1 : isParallel(y) ? 1 : 0;
}
개선사항
자... 먼저! Math.abs()
는 필요가 없다. 선분의 기울기가 음수여도 평행한 선분으로 판단될 수 있기 때문이다. 그리고 삼항연산자의 사용도 불필요하다.
const isParallel = (dot) => {
let [dot1, dot2, dot3, dot4] = dot;
// dot1과 dot2를 이은 선분의 기울기
let line1 = (dot2[1] - dot1[1]) / (dot2[0] - dot1[0]);
// dot3과 dot4를 이은 선분의 기울기
let line2 = (dot4[1] - dot3[1]) / (dot4[0] - dot3[0]);
return line1 === line2;
}
이렇게 수정해주어도 좋을 것.
정렬의 문제
그런데 말입니다...! 정렬은 필요가 없다고 한다. 당시에 생각할 때는 정렬이 필요할 거라고 생각했는데... 왜 정렬을 안 해도 되는거지...?
먼저 일차적으로 sort()를 두 번 사용한 것은 정말 틀린 풀이였다. sort()는 원본 배열을 바꾼다! 몇 번 얘기 들었었는데도 늘 까먹음 ㅠ 이래서 배열 메서드 한 번 정리를 싹 해야 하는데 시간이 안 난다. 그렇기 때문에 배열을 한 번만 써도 된다.
처음엔 정렬을 아예 없애도 되지 않겠냐는 제안을 받았다.
function solution(dots) {
// x좌표를 기준으로 배열을 정렬할 필요 없음
// let x = dots.sort((a, b) => {
// a = a[0];
// b = b[0];
// return a - b;
// });
// y좌표를 기준으로 배열을 정렬할 필요 없음
// let y = dots.sort((a, b) => {
// a = a[1];
// b = b[1];
// return a - b;
// });
return isParallel(dots) ? 1 : 0;
}
실제로 이렇게 제출했을 때 문제없이 통과하긴 했다. 하지만 이건 선분끼리 겹치지 않을 수 있도록 dots 배열이 신경 써서 주어졌을 때(?) 가능한 거 아닐까?
예를 들어 [[0, 0], [5, 4], [2, 1], [3, 3]]이 주어진다고 생각했을 때 주어진 dot의 순서대로 선분을 이을 경우 선분끼리 교차해서 평행이라고 판단하지 못하는 경우가 생긴다. 문제 자체에서는 주어진 네 개의 점을 두 개씩 이은다고 써있는 것이 그냥 순서대로 잇는다는 표현이었는지 몰라도, 모든 경우의 수를 확인해야 한다면 이것을 정렬하여 푸는 것이 맞다는 생각을 했다.
그래서 나의 최종 답안은 이렇게 정리하도록 하겠다!
const isParallel = (dots) => {
let [dot1, dot2, dot3, dot4] = dot;
// dot1과 dot2를 이은 선분의 기울기
let line1 = (dot2[1] - dot1[1]) / (dot2[0] - dot1[0]);
// dot3과 dot4를 이은 선분의 기울기
let line2 = (dot4[1] - dot3[1]) / (dot4[0] - dot3[0]);
return line1 === line2;
}
function solution(dots) {
let x = dots.sort((a, b) => {
a = a[0];
b = b[0];
return a - b;
});
return isParallel(x) ? 1 : 0;
}
function solution(dots) {
if (calculateSlope(dots[0], dots[1]) === calculateSlope(dots[2], dots[3]))
return 1;
if (calculateSlope(dots[0], dots[2]) === calculateSlope(dots[1], dots[3]))
return 1;
if (calculateSlope(dots[0], dots[3]) === calculateSlope(dots[1], dots[2]))
return 1;
return 0;
}
function calculateSlope(arr1, arr2) {
return (arr2[1] - arr1[1]) / (arr2[0] - arr1[0]);
}
이 풀이는 isParallel 함수를 사용하지 않고도 동일한 결과를 얻을 수 있다.
점들의 순서를 정렬할 필요 없이, 가능한 모든 경우를 검사하여 평행을 확인한다.
이게 더 간단하군...!
function solution(dots) {
const leans = []
for(let i = 0; i < dots.length; i++) {
const dotA = dots[i];
for(let j = i + 1; j < dots.length; j++) {
const dotB = dots[j]
const lean = (dotB[1] - dotA[1]) / (dotB[0] - dotA[0])
if(leans.includes(lean)) return 1
else leans.push(lean)
}
}
return 0;
}
훨씬 더 효율적으로, 모든 경우를 검사하지 않고도 답을 낼 수 있었다! 굿!