Kotlin/Algorithm Problems

<백준> 암호 만들기(Gold 5)

re트 2024. 1. 12. 11:30
728x90

[깃허브]

https://github.com/heesoo-park/ForCodeKata/tree/main/baekjoon%20%EB%AC%B8%EC%A0%9C%EC%A7%91/%EC%95%94%ED%98%B8%20%EB%A7%8C%EB%93%A4%EA%B8%B0

[백준]

https://www.acmicpc.net/problem/1759

제출 결과

 

정말 제출하고 많이 틀린 문제였다.

혼자 테스트하면서, 제출하고 나서를 합치면 8번...?

 

접근 자체는 쉽게 떠올랐다.

'모음 따로, 자음 따로 개수를 골라서 넣지 말고 일단 총 문자에서 원하는 개수만큼 뽑은 다음에 모음의 개수와 자음의 개수를 확인하자!'

 

입력은 쉽게 받았고 입력값을 CharArray로 바꿔 바로 받기 위해 filter를 사용해봤다.

그리고 조합 합수를 만들어 원하는 길이에 도달했을 때 모음이 포함되어있는지 확인하고 결과를 저장해 출력했다.

제출했더니 틀렸다.

 

왜 그런가 생각해보면 이 경우에는 모음만 있을 때 결과를 저장하면 안 되는데 저장해버린다.

자음은 최소 2개 이상 들어가야하기 때문이다.

그래서 자음이 포함되어있는지도 추가하고 제출했더니 틀렸다.

더 빨리 틀렸다...

 

이후 '자음 최소 2개를 포함시키지 않아서 그런가?', 'contains로는 안되나?', 'filter말고 다른게 있을까?' 하면서 여러 시도를 했지만 다 틀렸다...

그래서 기본적인 반복문으로 했더니 통과했다.

 

그 때 떠오른건 내가 그냥 암호를 통째로 사용했다는 거였다.

암호의 원소를 따로따로 체크한 게 아니라 통째로 하니까 당연히 그게 자음과 모음에 포함되어가 필터링 될 수 없는 거였다.

그래서 이후에 다시 시도한건 count 람다 함수다.

이 함수는 CharSequence의 확장함수원소 하나하나에 대해 중괄호 안의 내용을 체크한다.

그렇게 또 깨달음을 얻고 통과했다.

 

여기서 색다르게 해본게 있는데 바로 알파벳 모음과 자음 초기화다.

모음은 5개니까 그냥 listOf()로 하고 자음을 할 때 아스키 코드를 응용했다.

97부터 122까지를 리스트로 만들고 map을 통해 문자로 바꾼 다음에 모음에 포함되지 않는 문자만 걸러서 초기화했다.

아주 재밌는 방식이었다.

{ it in vowels } 라는게 'Collection 안에 해당 원소에 있는가?' 를 체크할 수 있다는 걸 이제야 깨달았다.

 

해당 방법으로 작성한 코드는 다음과 같다.

import java.util.StringTokenizer

var l: Int = 0
var c: Int = 0
lateinit var charArr: CharArray
val result = StringBuilder()

val vowels = listOf('a', 'e', 'i', 'o', 'u')
val consonants = (97..122).map { it.toChar() }.filterNot { it in vowels }

fun main() = with(System.`in`.bufferedReader()) {
    with(StringTokenizer(readln())) {
        l = this.nextToken().toInt()
        c = this.nextToken().toInt()
    }

    charArr = readln().filter { it != ' ' }.toCharArray().sortedArray()

    findCode(0, 0, StringBuilder())
    println(result)
}

fun findCode(len: Int, start: Int, code: StringBuilder) {
    if (len == l) {
        if (code.count { it in vowels } > 0
            && code.count { it in consonants} > 1) result.append(code).append("\n")
        return
    }

    for (i in start until charArr.size) {
        code.append(charArr[i])
        findCode(len + 1, i + 1, code)
        code.deleteCharAt(code.lastIndex)
    }
}
반응형