1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.
tank → kick → know → wheel → land → dream → mother → robot → tank
위 끝말잇기는 다음과 같이 진행됩니다.
끝말잇기를 계속 진행해 나가다 보면, 3번 사람이 자신의 세 번째 차례에 말한 tank 라는 단어는 이전에 등장했던 단어이므로 탈락하게 됩니다.
사람의 수 n과 사람들이 순서대로 말한 단어 words 가 매개변수로 주어질 때, 가장 먼저 탈락하는 사람의 번호와 그 사람이 자신의 몇 번째 차례에 탈락하는지를 구해서 return 하도록 solution 함수를 완성해주세요.
사실 이 문제는 한번 시도를 했다가 실패한 경험이 있어서 다음 문제로 넘어갔었다. lv2 문제임에도 불구하고 풀지 못했다는 것이 자존심이 상해서 다시 풀어봤는데 30분만에 풀 수 있는 문제였다.
코딩테스트에서 정말 중요하다고 생각하는 것이 문제의 요구사항을 기반으로 잘 분할하는 것이다. 요구사항이 많아 보이는 문제이더라도 잘 쪼개면 금방 풀리는 문제가 있다. 이 문제가 정확하게 그 조건에 맞다고 생각한다.
우선 이 문제의 핵심은 문자의 가장 끝 단어가 다음 단어에서 처음으로 시작하는 단어
여야만 한다는 점과 이전에 나온 문자는 다시 등장하면 안된다는 것
이다. 문자의 끝 단어가 다음 단어에서 처음 단어여야만 한다는 것은 해당 끝 문자를 담고 있는 변수와 계속 for문 안에서 비교하는 것으로 해결하고자 하였다. 또한 이전에 나온 문자는 다시 등장하면 안된다는 것은 새로운 배열에 단어를 넣어두고 해당 단어가 그 배열 안에 있으면 끝말잇기를 중단하는 방법으로 구현하였다.
결과를 도출할 때에는 나머지 연산과 나눗셈 연산을 적절하게 잘 사용하면 된다. 자세한 내용은 아래 코드 주석을 참고해보길 바란다.
연산의 계산 결과 소수점이 있다면 무조건 올림을 해주는 기능을 한다.
배열에 새로운 원소값을 가장 끝에 추가해준다.
배열에 찾고자 하는 문자열이 있다면 해당 index를 return 해주고, 아니라면 -1을 return 해준다.
function solution(n, words) {
let storage = []; // 끝말잇기에 부합하는 단어를 담는 배열
let lastWord; // 끝 문자와 첫 문자를 비교하기 위해 선언한 변수
let result = []; // 최종 결과 값을 넣을 배열
for(let i=0; i<words.length; i++){
// 첫 단어는 아무 조건 없이 storage 배열에 넣는다.
if(storage.length === 0){
lastWord = words[i][words[i].length-1];
storage.push(words[i]);
}
// 끝말잇기 조건에도 부합하고 이전에 등장하지 않은 단어라면 storage에 넣어준다.
else if(words[i][0] === lastWord && storage.indexOf(words[i]) === -1){
lastWord = words[i][words[i].length-1];
storage.push(words[i]);
}
// 둘 중 조건 하나라도 부합하지 않다면 결과 배열에 순서와 차수를 넣어준다.
else if(words[i][0] !== lastWord || storage.indexOf(words[i]) !== -1){
result.push(Math.floor(i%n) + 1);
result.push(Math.ceil((i+1)/n));
break; // 발견되는 즉시 프로그램 중단
}
// 모든 조건에 만족하는 경우는 storage 배열의 길이와 words의 길이가 같을 때이므로 이때는 0을 두번 넣어주면 된다.
if(storage.length === words.length){
result.push(0);
result.push(0);
}
}
return result; // 결과값 return
}