모의고사 문제를 함수형 프로그래밍으로 풀어보자.
문제 해결에 들어가기 앞서 필요한 배열과 함수를 살펴보자.
students
: 학생 한명의 name
과 pattern
을 하나의 객체로하는 배열 const students = [
{name: 1, pattern: [1, 2, 3, 4, 5]},
{name: 2, pattern: [2, 1, 2, 3, 2, 4, 2, 5]},
{name: 3, pattern: [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]},
];
repeat
: generator 객체를 무한으로 반복하는 generator functionfunction* repeat(a) {
while (true) yield a;
}
const solution = (answers) =>
go(
students,
map(scoring(answers)),
groupBy(({score}) => score),
Object.values,
last,
map(({name}) => name),
(_) => [..._]
);
한줄씩 뜯어서 살펴보도록 하자.
map(scoring(answers))
map
을 이용해scoring
함수를 호출한 결과를 모아 새로운 배열을 반환한다.
const scoring =
(answers) =>
({name, pattern}) => ({
name,
score: go(
randomAnswers(pattern, answers.length),
zip(answers),
countBy(([a, b]) => (a === b ? 'o' : 'x')),
(counted) => counted.o || 0
),
});
scoring
함수는 answer
를 받아 함수를 반환한다.
이 함수는 name
과 pattern
을 인자로 받아 name
과 최종 점수인 score
를 만드는 함수를 반환한다.
여기서
score
를 만드는randomAnswers
함수가 핵심이다.
const randomAnswers = (pattern, length) => go(
pattern,
repeat,
flat,
take(length)
);
입력받은 학생의 pattern
을 repeat
함수를 통과시켜 무한히 반복하게 한다.
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], ...]
그 다음
flat
함수를 통해 펼쳐준다.
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, ...]
take
함수를 통해 answer
의 길이만큼만 뽑아낸다.
randomAnswer
를 통해 생성된 답과 answer
와 zip
을 하여
정답의 개수를 구한다.
countBy(([a, b]) => (a === b ? 'o' : 'x')),
(counted) => counted.o || 0
countBy
함수
zip
을 통해 얻은 학생의 답과 정답을 비교한다.o
를 오답이면 x
로 만든다.o
의 개수를 센다.groupBy(({score}) => score)
1번을 통해 얻은 배열을 점수로 그룹화해준다.
groupBy
를 이용해서 객체의 키가 숫자인 경우 숫자가 클 수록 키가 뒤로 간다는 특징을 이용하였다.
Object.values
객체가 가지는 속성의 값들로 이루어진 배열을 리턴
last
groupBy
특징인 마지막 값이 max인 점을 이용한다.
last
: arr
배열의 마지막 값
const last = (arr) => arr[arr.length - 1];
map(({name}) => name)
name
값만 모아서 새로운 객체로 반환
(_) => [..._]
name
을 배열 형식으로 만든다.