이름들이 담긴 문자열 배열이 다음과 같이 있다고 가정해 보겠습니다.
const arr = ['Dinesh', 'Mahesh', 'Rohit', 'Kamal', 'Jatin Sapru', 'Jai'];
그리고 다음과 같은 임의의 문자열이 하나 주어집니다.
const str = 'lsoaakjm';
문제 정의
이 배열과 문자열을 두 개의 인수로 받는 JavaScript 함수를 작성해야 합니다.
함수는 배열의 각 요소를 순회하면서, 해당 요소(이름)가 두 번째 인수로 전달된 문자열에 포함된 문자들만으로 완전히 구성될 수 있는지 확인해야 합니다. 이때 각 문자는 주어진 문자열 안에서 사용된 횟수만큼만 사용할 수 있습니다.
조건을 만족하는 요소가 존재하면 그 요소를 그대로 반환하고, 어떤 요소도 조건을 충족하지 못하면 빈 문자열('')을 반환하면 됩니다.
예제 코드
다음은 위 문제를 해결하는 코드입니다.
const arr = ['Dinesh', 'Mahesh', 'Rohit', 'Kamal', 'Jatin Sapru', 'Jai'];
const str = 'lsoaakjm';
const initialise = (str = '', map) => {
for(let i = 0; i < str.length; i++){
map[str[i]] = (map[str[i]] || 0) + 1;
};
};
const deleteAll = map => {
for(key in map){
delete map[key];
};
};
const checkForFormation = (arr = [], str = '') => {
const map = {};
for(let i = 0; i < arr.length; i++){
const el = arr[i].toLowerCase();
initialise(str, map);
let j;
for(j = 0; j < el.length; j++){
const char = el[j];
if(!map[char]){
break;
}else{
map[char]--;
}
};
if(j === el.length){
return arr[i];
};
deleteAll(map);
}
return '';
};
console.log(checkForFormation(arr, str));코드 동작 방식
- initialise 함수: 두 번째 인수로 전달된 문자열을 한 글자씩 순회하며 각 문자의 등장 횟수를 map 객체(해시 맵)에 저장합니다.
- deleteAll 함수: 다음 배열 요소를 검사하기 전에 map 객체의 모든 키를 삭제해 카운터를 초기화합니다.
- checkForFormation 함수: 배열의 각 이름을 소문자로 변환한 뒤, 필요한 문자가 map에 아직 남아 있는지 확인하면서 문자를 하나씩 소비(map[char]--)합니다. 이름의 모든 문자를 성공적으로 처리하면 해당 원본 요소를 즉시 반환하고, 도중에 필요한 문자가 부족하면 break로 반복을 중단한 뒤 map을 비우고 다음 요소를 검사합니다.
예제에서 문자열 'lsoaakjm'에는 k, a, m, a, l이 모두 포함되어 있으므로 'Kamal'을 완성할 수 있습니다. 반면 'Dinesh'나 'Mahesh'는 d, e, s, h 등의 문자가 없어 만들 수 없습니다.
출력 결과
콘솔 출력 결과는 다음과 같습니다.
Kamal