그리디 알고리즘은 총 이득을 바라보는 것이 아닌, 판단하는 순간 순간의 이득에 집중하는 알고리즘이다. 이러한 판단 방식이 매우 직관적이며, 항상 최적해를 보장하지는 않는다. 현재의 선택이 미래에 영향을 주지 않는 경우, 입출력 제한이 너무 큰 경우 그리디 알고리즘을 고려해보자.
앞서 배운 DFS, BFS와 같은 완전 탐색에서 추가적으로 속도를 높이기 위한 탐색기법. 현제 방문한 노드가 답일 확률이 낮을 때, 해당 노드와 이어진 노드의 탐색을 생략한다(가지치기). 얼마나 가지치기 조건을 잘 세우냐가 중요하며, 자바스크립트의 경우에 재귀의 성능이 좋지 않아 Stack, Queue 자료구조를 이용하여 구현하는 것이 좋다.
이터러블 데이터가 있을 때, 이터러블의 각 요소마다 일정한 변경을 준 또다른 이터러블을 반환하는 함수이다.
const arr = [1, 2, 3, 4, 5];
const func = a => a + 1;
console.log(arr.map(func));
// [2, 3, 4, 5, 6]
위의 Array.prototype.map()과 동일하게 동작한다. 하지만 이터러블 프로토콜을 이용해서 구현한다면, Array를 포함한 이터러블 프로토콜을 따르는 모든 데이터에 사용할 수 있다.
여러 데이터 중 조건과 일치하는 요소만을 가진 이터러블을 반환하는 함수이다.
const arr = [1, 2, 3, 4, 5];
const func = a => a < 4;
console.log(arr.filter(func));
// [1, 2, 3]
위의 Array.prototype.filter()와 동일하게 작동한다.
여러 요소를 가진 이터러블에서 하나의 값으로 수를 줄이는 함수이다. 파라미터는 다음과 같다.
reduce(function f(a, b), acc, iterable)
const arr = [1, 2, 3, 4, 5];
const func = (a, b) => a + b;
console.log(reduce(func, 0, arr));
// 15
위와 같은 reduce 함수가 있을 때, 이 함수의 동작 순서를 표기하면 다음과 같은 재귀 구조이다.
func(func(func(func(func(0, 1), 2), 3), 4), 5);
위의 파라미터 중 acc는 생략이 가능하며, 만약 생략된다면 기본적으로 iterable의 첫번 째 원소가 되고 계산은 두번째 원소부터 시작한다.
reduce(func, arr);
// 아래와 같은 방식으로 동작한다.
// (func, [first, ...arr]) => reduct(func, first, arr);
// func(func(func(func(1, 2), 3), 4), 5);
앞서 본 함수형 프로그래밍의 함수들은 결과를 별도로 사용하지 않고 그대로 반환하므로 중첩하여 사용이 가능하다. 하지만 중첩이 많을수록 가독성이 떨어지며, 가장 안쪽에 위치한 함수부터 동작하므로 사람이 글을 읽는 방향과 반대방향이 된다. 이런 중첩된 코드의 가독성을 높이기 위해서 사용하는 함수가 go 함수이다. go 함수는 시작값과 함수들을 인자로 받아 인자로 받은 함수들을 차례대로 실행한 결과를 반환한다.
go와 비슷하게 동작하지만 모든 함수들의 실행 결과 값이 아닌, 모든 함수실행하는 하나의 함수를 반환한다. 선언한 함수를 반복적으로 사용할 수 있는 점이 go와 다르다.
curry는 함수를 입력받고, 입력받은 인자의 개수에 따라서 다르게 동작하는 또 다른 함수를 결과물로 반환한다. 지정한 숫자만큼의 인자가 입력된다면 실행 결과를 반환하지만, 보다 적은 인자를 입력할 경우에 입력받은 인자는 저장하고 나머지 입력을 받아 결과를 반환하는 함수를 반환한다.
const add = (a, b) => a + b;
const curry_add = curry(add);
const add5 = curry_add(5);
// a와 b 두개의 인자들 중 a를 5로 저장, 나머지 입력을 받는 함수로 반환한다.
// add5 = (5, b) => 5 + b;
// add5 = b => 5 + b;
Currying, 함수형 프로그래밍 구현(go, pipe)
프로그래밍을 접하고 난 뒤로 명령형 프로그래밍에서 벗어난 적이 없었는데, 이렇게 함수형 프로그래밍에 대해서 배울 기회가 생겨 뜻깊다. 아무래도 사고 방식의 전환이라 평범하게 새로운 프로그래밍 언어를 배울 때와는 사뭇 다른 느낌이다. 아직도 함수를 변수에 저장하는 개념이나 표기법에서 이해가 더디다. 함수형 프로그래밍 관련 질문은 기간이 짧으니 이번주 동안은 좀 더 노력해 봐야겠다.
프로그래머스 프론트엔드 데브코스