본문 바로가기
Developer/Algorithm

프로그래머스 코딩테스트 연습 Level 3 - 단어 변환 (JavaScript/Python)

by 김씩씩 2022. 11. 24.

프로그래머스 코딩테스트 연습 Level 3 - 단어 변환 (JavaScript/Python)

 

Programmers(프로그래머스)의 코딩테스트 연습문제 Level 3 중 깊이/너비 우선 탐색(DFS/BFS) 관련 문제인,

[단어 변환] 문제를 JavaScript 와 Python를 사용하여 해결해 보도록 하겠습니다.

 

문제

문제 설명

두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다.

1. 한 번에 한 개의 알파벳만 바꿀 수 있습니다.
2. words에 있는 단어로만 변환할 수 있습니다.

예를 들어 begin이 "hit", target가 "cog", words가 ["hot","dot","dog","lot","log","cog"]라면 "hit" -> "hot" -> "dot" -> "dog" -> "cog"와 같이 4단계를 거쳐 변환할 수 있습니다.

두 개의 단어 begin, target과 단어의 집합 words가 매개변수로 주어질 때, 최소 몇 단계의 과정을 거쳐 begin을 target으로 변환할 수 있는지 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 각 단어는 알파벳 소문자로만 이루어져 있습니다.
  • 각 단어의 길이는 3 이상 10 이하이며 모든 단어의 길이는 같습니다.
  • words에는 3개 이상 50개 이하의 단어가 있으며 중복되는 단어는 없습니다.
  • begin과 target은 같지 않습니다.
  • 변환할 수 없는 경우에는 0를 return 합니다.

 

입출력 예

begin target words return
"hit" "cog" ["hot", "dot", "dog", "lot", "log", "cog"] 4
"hit" "cog" ["hot", "dot", "dog", "lot", "log"] 0

 

입출력 예 설명

예제 #1
문제에 나온 예와 같습니다.

 

예제 #2
target인 "cog"는 words 안에 없기 때문에 변환할 수 없습니다.

 

 

작성한 답

solution.js

function solution(begin, target, words) {
    let answer = 0;
    const queue = [];
    const ch = Array.from({length: words.length}, _ => 0);
    queue.push([begin, 0]);
    
    const compare = (w1, w2) => w1.split('').reduce((ac, v, i) => ac + (v !== w2[i] ? 1 : 0), 0) === 1 ? true : false;
    
    while(queue.length) {
        const [cur, cnt] = queue.shift();
        if (cur === target) {
            answer = cnt;
            break;
        }
        for(const i in words) {
            if(ch[i] === 0) {
                const word = words[i];
                if (compare(cur, word)) {
                    ch[i] = 1;
                    queue.push([word, cnt + 1]);
                }
            }
        }
    }
    
    return answer;
}

solution.py

def solution(begin, target, words):
    answer = 0
    queue = []
    ch = [0] * len(words)
    queue.append([begin, 0])
    
    def compare(word1, word2):
        cnt = 0
        for c1, c2 in zip(word1, word2):
            if c1 != c2:
                cnt += 1
        return True if cnt == 1 else False

    while len(queue):
        cur_word, cnt = queue.pop(0)
        if cur_word == target:
            answer = cnt
            break
        for i, word in enumerate(words):
            if not ch[i] and compare(cur_word, word):
                ch[i] = 1
                queue.append([word, cnt + 1])
                
    return answer

 

설명

문제 설명에서 '최소 몇 단계의 과정을 거쳐' 라는 문장을 통해 BFS로 해결하면 되겠다는 생각으로 해결했습니다.

 

답으로 반환활 answer 변수를 변환할 수 없는 경우에 0으로 반환해야하기에 0으로 초기화 해둡니다.

그리고 BFS에 사용할 Queue와 이미 사용한 단어의 경우 다시 사용하지 않기위해 사용했다는 것을 표기해둘 배열 ch를 하나 만들어둡니다. 

그다음 queue에는 시작 단어인 begin 과 몇번의 변환이 이루어졌는지를 카운트할 숫자 0 을 배열로 담아둡니다.

 

그리고 한번에 한개의 알파벳만 바꿀 수 있기 때문에 1개의 알파벳만 다른지를 확인해줄 함수를 미리 작성해두었습니다.

이제 시작 단어를 시작으로 반복문을 돌면서 words 배열에서 이미 변환하는데 사용한적이 없는 단어이면서, 1개의 알파벳만 다른 단어일 때 해당 단어와 변환 횟수를 queue에 집어넣고 해당 단어는 사용한 단어라고 ch 변수에서 해당 단어의 index에 1 로 표기해둡니다.

 

queue가 빌 때 까지 반복하다가 target 단어와 같아지면 그 때의 변환 횟수를 answer 에 넣고 반복문을 나오고 해당 값을 반환합니다.

만약 queue가 빌 때 까지 반복했으나 답이 나오지 않는다면 미리 초기화 해둔 0을 반환하는 것으로 문제를 해결할 수 있습니다.

JavaScript 결과
Python 결과

 

 

도움이 되셨다면 공감, 댓글 부탁드립니다!

궁금하신 점이나 요청사항은 언제든지 말씀해주세요!

피드백도 언제나 환영입니다!

 

감사합니다.


댓글