영어 끝말잇기
1. 개요
프로그래머스
Lv.2
Summer/Winter Coding(~2018)
2. 문제 설명
1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.
1번부터 번호 순서대로 한 사람씩 차례대로 단어를 말합니다.
마지막 사람이 단어를 말한 다음에는 다시 1번부터 시작합니다.
앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야 합니다.
이전에 등장했던 단어는 사용할 수 없습니다.
한 글자인 단어는 인정되지 않습니다.
다음은 3명이 끝말잇기를 하는 상황을 나타냅니다.
tank → kick → know → wheel → land → dream → mother → robot → tank
위 끝말잇기는 다음과 같이 진행됩니다.
1번 사람이 자신의 첫 번째 차례에 tank를 말합니다.
2번 사람이 자신의 첫 번째 차례에 kick을 말합니다.
3번 사람이 자신의 첫 번째 차례에 know를 말합니다.
1번 사람이 자신의 두 번째 차례에 wheel을 말합니다.
(계속 진행)
끝말잇기를 계속 진행해 나가다 보면, 3번 사람이 자신의 세 번째 차례에 말한 tank 라는 단어는 이전에 등장했던 단어이므로 탈락하게 됩니다.
사람의 수 n과 사람들이 순서대로 말한 단어 words 가 매개변수로 주어질 때, 가장 먼저 탈락하는 사람의 번호와 그 사람이 자신의 몇 번째 차례에 탈락하는지를 구해서 return 하도록 solution 함수를 완성해주세요.
2-1. 문제 설명 - 제한 사항
끝말잇기에 참여하는 사람의 수 n은 2 이상 10 이하의 자연수입니다.
words는 끝말잇기에 사용한 단어들이 순서대로 들어있는 배열이며, 길이는 n 이상 100 이하입니다.
단어의 길이는 2 이상 50 이하입니다.
모든 단어는 알파벳 소문자로만 이루어져 있습니다.
끝말잇기에 사용되는 단어의 뜻(의미)은 신경 쓰지 않으셔도 됩니다.
정답은 [ 번호, 차례 ] 형태로 return 해주세요.
만약 주어진 단어들로 탈락자가 생기지 않는다면, [0, 0]을 return 해주세요.
2-2. 문제 설명 - 입출력 예
3
["tank", "kick", "know", "wheel", "land", "dream", "mother", "robot", "tank"]
[3,3]
5
["hello", "observe", "effect", "take", "either", "recognize", "encourage", "ensure", "establish", "hang", "gather", "refer", "reference", "estimate", "executive"]
[0,0]
2
["hello", "one", "even", "never", "now", "world", "draw"]
[1,3]
2-3. 문제 설명 - 입출력 예 설명
입출력 예 #1
3명의 사람이 끝말잇기에 참여하고 있습니다.
1번 사람 : tank, wheel, mother
2번 사람 : kick, land, robot
3번 사람 : know, dream, tank
와 같은 순서로 말을 하게 되며, 3번 사람이 자신의 세 번째 차례에 말한 tank라는 단어가 1번 사람이 자신의 첫 번째 차례에 말한 tank와 같으므로 3번 사람이 자신의 세 번째 차례로 말을 할 때 처음 탈락자가 나오게 됩니다.
입출력 예 #2
5명의 사람이 끝말잇기에 참여하고 있습니다.
1번 사람 : hello, recognize, gather
2번 사람 : observe, encourage, refer
3번 사람 : effect, ensure, reference
4번 사람 : take, establish, estimate
5번 사람 : either, hang, executive
와 같은 순서로 말을 하게 되며, 이 경우는 주어진 단어로만으로는 탈락자가 발생하지 않습니다. 따라서 [0, 0]을 return하면 됩니다.
입출력 예 #3
2명의 사람이 끝말잇기에 참여하고 있습니다.
1번 사람 : hello, even, now, draw
2번 사람 : one, never, world
와 같은 순서로 말을 하게 되며, 1번 사람이 자신의 세 번째 차례에 'r'로 시작하는 단어 대신, n으로 시작하는 now를 말했기 때문에 이때 처음 탈락자가 나오게 됩니다.
3. 문제 풀이
1) 진행된 단어를 요소로 가지는 배열과 탈락 라운드를 카운트하는 변수 만들기
첫 번째 라운드인 words[0]
를 0번째 요소로 가지는 round
배열을 만든다. 그리고 탈락된 순서를 계산하는 변수 fail
를 변수로 만든다.
round
배열은 아래의 반복문을 통해 새로운 단어들이 추가되고 fail
변수는 아래의 반복문에서 특정 조건이 만족하지 않는다면 1씩 증가된다.
2) 이미 등장한 단어가 다시 등장되면 반복문 종료하기
만약 제시한 단어가 이전에 등장했다면 해당 단어를 말한 사람은 탈락한다.
즉, round
배열에 요소로 해당 단어가 있다면 탈락을 하게 된다. 탈락이 확정되면 더 이상의 라운드 진행은 필요없기 때문에 break
를 실행하여 반복문을 종료한다.
3) 이전 단어의 마지막 문자와 현재 단어의 첫 문자가 다르면 반복문 종료하기
만약 제시한 단어의 첫 문자가 이전 단어의 마지막 문자와 다르면 해당 단어를 말한 사람은 탈락한다.
즉, round
배열의 마지막 요소의 마지막 문자가 word[i]
의 첫 번재 문자가 다르면 탈락을 한다. 이와 같은 경우엔 더 이상의 라운드 진행이 필요없기 때문에 break
를 실행하여 반복문을 진행한다.
4) round 배열에 단어 추가한 후 fail 1증가시키기
round
배열에 없는 단어, 이전 단어의 마지막 문자가 첫 번재 문자로 온 경우 즉, 위의 조건문에서 걸러지지 않았다면 해당 단어를 round
에 추가한다. 또한 탈락한 순서인 fail
를 1증가시킨다.
지금 생각해보면 fail
변수는 그닥 필요 없어 보인다. 그 이유는 round
의 배열의 길이로 탈락한 순서를 알 수 있기 때문이다.
5) 아무도 실패하지 않았따면 [0, 0]를 반환하기
마지막 라운드까지 완료를 하였다면 문제의 조건에 맞게 [0, 0]
를 반환한다.
6) 탈락한 사람과 탈락한 순서 구한 후 반환하기
중간에 탈락한 사람이 생기면 그 사람이 누구인지와 그 사람이 해당 단어를 몇 번째에 말했는지 알아야 한다.
person
을 구하기 위해선 먼저 탈락한 순서를 전체 사람의 수로 나누어야 한다. 나눈 나머지가 0
이라면 탈락한 사람의 순서는 n
이고 그러지 않으면 나눈 수의 나머지가 된다.
order
는 탈락한 사람이 탈락된 단어를 몇 번째에 말했는지를 나타낸다. 이를 위해 탈락한 순서에 사람을 수로 나눈 몫을 올림하여 구한다.
그 후 person
, order
순으로 배열를 만들어 반환한다.
결과
4. Refactoring
배열에서 array[index]
와 같은 방법으로 특정 인덱스의 요소에 접근한다. 이는 문자열에도 같다. 즉 문자열[index]
와 같은 방법으로 접근이 가능한다. 이를 사용하여 단어의 마지막 문자와 첫 번째 문자를 접근하여 비교하였다.
또한 round
배열을 없애고 words
배열을 i
로 접근하였다.
전체적인 로직은 비슷하나 반복문 내에서 조건을 비교하는 방법은 달라졌다. 이를 위주로 설명을 작성한다.
1) 첫 번째 단어는 뒤도 돌아보지 않고 건너뛰기
i
가 0
이라는 것은 첫 번재 단어라는 것이다. 첫 번째 단어는 당연히 탈락을 할 수 없기 때문에 다음 반복문으로 넘어간다.
2) 이전 단어의 마지막 문자와 현재 단어의 첫 번째 문자를 비교하기
i
번째 단어의 이전 단어인 i - 1
번째 단어의 마지막 문자와 i
번째 단어의 첫 번째 문자를 비교하였을 때 그 둘이 다르다면 fail
를 i + 1
로 바꾸고 반복문을 종룔한다.
i
는 인덱스이기 때문에 실제 실패한 순서는 i
에 1을 더한 값이다. 왜냐! i
는 0부터 시작하기 때문이다.
3) 현재 단어가 이전에 존재 했는지 확인하기
i
번째 단어를 indexOf
를 검색하였을 때 i
와 같지 않다면 이전에 i
번째 단어와 같은 단어가 존재한다는 것이다. array.indexOf()
메서드는 매개변수로 주어진 값과 일치하는 요소의 인덱스를 반환한다. 만약 3번 인덱스와 8번 인덱스가 같은 값이고 해당 값이 매개변수로 주어진다면 array.indexOf()
메서드는 3
를 반환한다. 즉, 순서가 빠른 인덱스를 반환한다.
결과
뭔가.. 더 가독성이 좋아졌다고 생각해서 실행속도도 크게 차이나지 않을 것이라 생각했는데 리팩토링한 풀이가 더 오래 걸린다.
5. Conclusion
엄청 어렵지 않은 문제였다. 조건만 잘 파악하면 특정 알고리즘과 자료구조 없이 쉽게 해결할 수 있는 문제라고 생각한다. 어렵지 않았지만 무엇이 더 효율적인 풀이인지 항상 고민을 해야 겠다고 생각했다. 내가 처음으로 풀었던 풀이에서는 굳이 필요없는 배열을 만들어 풀었다. 딱 처음 생각하는 풀이를 그대로 적었기 때문에 수정하는 과정은 반드시 필요하겠지만 실제 코딩테스트에선 여유롭게 풀 수 없기 때문에 한 번 생각할 때 최적의 최선의 최고의 풀이를 떠오를 수 있도록 공부하고 노력하자.
📅 2022-09-26
Last updated