<백준> 암호 만들기(Gold 5)
[깃허브]
[백준]
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)
}
}