빈 배열에 추가 삭제하기
빈 배열에 추가, 삭제하기
문제
문제 설명
아무 원소도 들어있지 않은 빈 배열 X가 있습니다. 길이가 같은 정수 배열 arr과 boolean 배열 flag가 매개변수로 주어질 때, flag를 차례대로 순회하며 flag[i]가 true라면 X의 뒤에 arr[i]를 arr[i] x 2 번 추가하고, flag[i]가 false라면 X에서 마지막 arr[i]개의 원소를 제거한 뒤 X를 return 하는 solution 함수를 작성해 주세요.
풀이(일단은)
function solution(arr, flag) {
const x = [];
for (let i in flag) {
if (flag[i]) {
Array(arr[i])
.fill()
.forEach(() => {
x.push(arr[i]);
x.push(arr[i]);
});
} else {
Array(arr[i])
.fill()
.forEach(() => x.pop());
}
}
return x;
}
설명
이건 일단은 알고리즘을 자랑하려는 게 아니다. 더 편한 해법을 보여주고 싶어서 가져온 문제이다.
세상에는 내 문제를 이미 해결해 놓은 경우가 많다. 하늘 아래 새로울 것 없다고 하는데 코딩 세상에서는 특히 더 그렇다. 내가 고민하는 문제는 미안하지만, 다른 사람도 이미 고민했던 문제고 아마 여러분보다 더 뛰어난 사람들이 더 깔끔한 해법을 남겨놓았을 것이다. 아니라고? 그럼 지금 당장 논문을 써라. 논문이 부담된다면, 깃허브에 그 결과물을 올려라. 탑 티어 프로그래머로서 역사책에 이름을 남길 수 있을 것이다.
하여튼 이 문제도 그런 유형에 속한다. LoDash 라이브러리에는 zip()함수가 있는데 이 함수는 두 배열을 하나의 배열로 합치는 일을 한다. 그런데 합칠 때 pair라고 해야 하나? tuple이라고 해야 하나? 하여튼 원소의 짝으로 그룹화뢴 배열을 반환한다.
_.zip(["a", "b"], [1, 2], [true, false]);
// => [['a', 1, true], ['b', 2, false]]
우리의 문제에서는 두 개의 배열을 같은 인덱스로 참고하느라 forEach
같은 걸 자유롭게 쓰질 못했다. 그렇다고 zip을 직접 구현하려니 번잡하다. 하려면 할 수도 있고 숏코딩에 자신있는 사람이라면 위의 해법보다 훨씬 짧게도 가능하겠지만 아쉽게도 내 머리는 zip 알고리즘을 기억해 줄 정도로 성능이 좋질 않다.
일단 해보자.
const _ = require("lodash");
const arr = [3, 2, 4, 1, 3];
const flag = [true, false, true, false, false];
const x = [];
const cmd = _.zip(arr, flag);
cmd.forEach(([el, flag]) => {
if (flag) {
[...Array(el * 2)].forEach(() => x.push(el));
} else {
[...Array(el)].forEach(() => x.pop());
}
});
console.log(x);
[...Array(n)].forEach()
또는 [...Array(n)].map()
은 이 문제를 푼 뒤에 배운 테크닉이다. 잔재주지만, 자바스크립트 세상에서는 잔재주를 쳐준다. 적어도 자바 세상보다는 더 쳐준다. 하는 일은 간단하다. n 만큼 반복하라
.
하여튼 그게 중요한 게 아니고, zip을 사용함으로써 인텍스 참조가 사라져 코드가 깔끔해졌다. zip이 뭐하는 함수인지는 설명이 필요할 수도 있지만 zip을 안다고 가정할 수 있다면 나머지 코드의 가독성이 훨씬 올라간 것을 볼 수 있다.
그나저나 어떤 함수를 n번 반복 실행하는 고차 함수는 Lodash에 없나보다.
댓글남기기