문제 설명
문자열 s가 입력되었을 때 다음 규칙을 따라서 이 문자열을 여러 문자열로 분해하려고 합니다.
- 먼저 첫 글자를 읽습니다. 이 글자를 x라고 합시다.
- 이제 이 문자열을 왼쪽에서 오른쪽으로 읽어나가면서, x와 x가 아닌 다른 글자들이 나온 횟수를 각각 셉니다. 처음으로 두 횟수가 같아지는 순간 멈추고, 지금까지 읽은 문자열을 분리합니다.
- s에서 분리한 문자열을 빼고 남은 부분에 대해서 이 과정을 반복합니다.
- 남은 부분이 없다면 종료합니다.
만약 두 횟수가 다른 상태에서 더 이상 읽을 글자가 없다면, 역시 지금까지 읽은 문자열을 분리하고, 종료합니다. 문자열 s가 매개변수로 주어질 때, 위 과정과 같이 문자열들로 분해하고, 분해한 문자열의 개수를 return 하는 함수 solution을 완성하세요.
제한사항
- 1 ≤ s의 길이 ≤ 10,000
- s는 영어 소문자로만 이루어져 있습니다.
풀이
const solution = (s) =>
[...s].reduce((acc, cur, idx, arr) => {
acc.temp.push(cur);
if(acc.start === cur) acc.count.same += 1;
else acc.count.diff += 1;
if(acc.count.same === acc.count.diff){
acc.result.push(acc.temp.join(""));
acc.temp = [];
acc.start = arr[idx + 1];
return acc;
}
if(idx === arr.length - 1) acc.result.push(acc.temp.join(""));
return acc;
},{
temp:[],
result:[],
start: s.at(0),
count: {same: 0, diff: 0}
}).result.length;
reduce()를 이용해서 정직하게 문제에서 설명한대로 풀었다.
"banana" 라고 주어진다면 첫글자인 b로 시작해서
b랑 b가 같으니까 같은거 1, b랑 a가 다르니까 다른거 1
이때 같은 횟수와 다른 횟수가 같아지므로 ba 자르고 다음 첫글자인 n으로 비교 시작.
n과 n이 같고 n과 a가 다르니 na 자르고 다시 다음 첫글자인 n으로 비교 시작
위와 같이 na로 잘라지고 나머지는 없으니 최종 결과물인 ["ba","na","na] 의 갯수인 3을 리턴해주면 된다.
1. split() 혹은 전개연산자를 이용해 주어진 문자열 s를 배열로 변경.
2. 생성된 배열에 reduce()를 이용해서 순회를 할껀데, 이때 초기값은 아래와 같다.
acc = {
temp: [], // result에 넣기전 임시로 문자들을 넣어줄 배열
result: [], // 최종 결과물들을 넣기 위한 배열
start: s.at(0), // 비교를 시작할 문자열을 저장
count: { // 비교시, 같은것과 다른것의 카운팅을 위한 객체
same: 0, // 같은 원소가 나온 횟수
diff: 0 // 다른 원소가 나온 횟수
}
}
3. 이제 reduce()의 블럭문을 살펴보면
- 우선 acc의 temp 배열에 현재 원소를 담아준다.
- acc.start와 현재 원소를 비교해서 acc.count 객체의 same과 diff에 각각 1을 더해준다.
- 그다음 acc.count 객체의 same과 diff가 같은지 판단한다.
같을 경우 acc.result 배열에 acc.temp 배열을 join() 매서드로 문자열의 형태로 넣어준다.
그리고 acc.temp 배열을 빈배열로 초기화 해주고, acc.start를 원본 배열의 현재 인덱스 다음 번호로 변경 해준 뒤
acc를 리턴해준다.
같지 않을 경우 현재 인덱스가 마지막인지 확인하고, 마지막이라면 acc.result에 위와 마찬가지로
acc.temp를 문자열로 합쳐준걸 넣어주고 끝낸다. - 위 과정이 반복되면 문제에서 요구한대로 문자열이 나눠지고 reduce의 객체가 완성되므로
.result.length 를 리턴해주면 된다.