알고리즘 문제 풀이
프로그래머스 - 단어 변환
블린더르
2021. 1. 2. 00:14
/*
* 2021-01-01
* https://programmers.co.kr/learn/courses/30/lessons/43163
*/
fun wordConversion(begin: String, target: String, words: Array<String>): Int {
// words 에 target 이 없는 경우 0 반환
if (!words.any { it == target }) {
return 0
}
// begin 을 포함한 allWords 생성
val allWords = words.plus(begin)
// 각 단어별 노드 생성
val nodeMap = allWords.associate { it to WordNode(it) }
nodeMap.forEach { (word, node) ->
// 한글자만 다른 단어를 찾아서 다음 노드로 추가
findOneAlphabetDiff(word, allWords).forEach { diffWord ->
nodeMap[diffWord]?.let {
node.addNextWordNode(it)
}
}
}
nodeMap[begin].let {
return if (it != null) {
searchGraph(it, target, 1)
} else {
0
}
}
}
fun searchGraph(node: WordNode, target: String, depth: Int): Int {
node.setVisited(true)
val nextNodes = node.getNextWordNodes()
var result: Int = Int.MAX_VALUE
nextNodes.forEach {
if (!it.getVisited()) {
val word = it.getWord()
val resultDepth = if (word == target) {
depth
} else {
searchGraph(it, target, depth + 1)
}
if (result > resultDepth) {
result = resultDepth
}
}
}
return result
}
fun findOneAlphabetDiff(word: String, words: Array<String>): List<String> {
return words.filter { w ->
w.withIndex().filter { it.value != word[it.index] }.count() == 1
}.map { it }
}
class WordNode(word: String) {
private val word: String = word
private val nextNodes: MutableList<WordNode> = mutableListOf()
private var visited: Boolean = false
fun getWord(): String {
return this.word
}
fun addNextWordNode(wordNode: WordNode) {
nextNodes.add(wordNode)
}
fun getNextWordNodes(): MutableList<WordNode> {
return nextNodes
}
fun setVisited(visited: Boolean) {
this.visited = visited
}
fun getVisited(): Boolean {
return visited
}
}
테스트
class DfsBfsTest {
companion object {
@JvmStatic
fun wordConversionArgs(): Stream<Arguments> {
return Stream.of(
Arguments.of("hit", "cog", arrayOf("hot", "dot", "dog", "lot", "log", "cog"), 4),
Arguments.of("hit", "cog", arrayOf("hot", "dot", "dog", "lot", "log"), 0)
)
}
}
@ParameterizedTest
@MethodSource("wordConversionArgs")
fun testWordConversion(begin: String, target: String, words: Array<String>, answer: Int) {
assertEquals(answer, wordConversion(begin, target, words))
}
}
반응형