백준 4659 코틀린 풀이
1. 문제 설명
input으로 여러 문자열이 주어집니다. 이 문자열들이 조건에 맞는지 검토하는 문제입니다.
2. 초기 구상 및 의도
정규표현식을 알고 있다면 풀리는 아주 간단한 문제입니다. 세 가지 조건은 ‘하나 이상의 모음’, ‘3개 이상 연속되지 않는 모음/자음’, ‘같은 글자의 반복 제외(ee, oo는 예외)’ 이 세 조건을 만족하는 조건을 정규식으로 표현할지, 만족하지 않는 조선을 정규식으로 표현할지 정해야 합니다. 각 조건의 여집합이 정규식으로 표현하기 편한지 살펴보고 정해야 합니다. 1번 조건은 여집합으로도 표현하는 것이 어렵지 않지만, 2번과 3번은 여집합으로 정규식으로 표현하는 것이 어려워, 해당 조건 중 하나라도 만족하지 않는 문자열을 찾기 위한 정규식을 만들고자 했습니다.
명심! 코틀린의 matches는 boolean을 반환값으로, 해당 문자열이 regex와 일치하는지 판단, JS의 match는 배열을 반환값으로, 문자열 속, 일치하는 문자열을 담는다. matches는 전체가 패턴에 부합해야 하지만, match는 그렇지 않다.
3. 코드
import java.util.*
import java.io.*
fun main(args: Array<String>) = with(BufferedReader(InputStreamReader(System.`in`))) {
val answer = StringBuilder()
// 아래의 정규식에 대한 설명은 아래의 개선된 코드에서 하겠습니다.
val regex = "^[^aeiou]+$|.*[aeiou]{3,}.*|.*[^aeiou]{3,}.*|.*([^eo])\\1+.*".toRegex()
while (true) {
val input = readLine()
if(input == "end")
break
answer.append('<').append(input)
if(input.matches(regex)){
// 문장 마지막에 "."이 없으면 오답!!!
answer.append("> is not acceptable.").append("\n")
}else{
answer.append("> is acceptable.").append("\n")
}
}
print(answer)
}
4. 개선점
- 정규식을 만드는 과정에서 run을 사용하여 정의하면, 타인이 해석하기 쉬운 정규식 표현이 가능합니다.
5. 코드
import java.util.*
import java.io.*
fun main(args: Array<String>) = with(BufferedReader(InputStreamReader(System.`in`))) {
val answer = StringBuilder()
val regex = run{
/*
^: 문장의 처음
$: 문장의 끝
[]: 안의 문자 아무거나
[^]: 안의 문자만 아니면 된다!
-> [^aeiou] 자음
+ : 앞의 문자가 1개 이상
결) 처음과 끝 사이에 자음만 1개 이상 == 문자열에 모음이 없다
*/
val onlyConsonant = "^[^aeiou]+$"
/*
. : 아무 문자
* : 0개 이상
-> .* 아무 문자나 0개 이상 존재
{n,m} : 앞의 문자가 최소 n번 최대 m번
결) 어떤 문자 사이에든, 자음/모음이 3번 이상 연속으로 존재
*/
val threeConsonant = ".*[^aeiou]{3,}.*"
val threeVowel = ".*[aeiou]{3,}.*"
/*
(): 캡쳐 그룹을 지정하고, 이후 \을 이용하여 값을 참조할 수 있다.
\\: 앞의 \은 escape 문자로 뒤의 \이 참조를 위해 사용되었음을 알린다.
결) [^eo]가 두번!
*/
val repetitive = ".*([^eo])\\1.*"
"${onlyConsonant}|${threeConsonant}|${threeVowel}|${repetitive}".toRegex()
}
while (true) {
val input = readLine()
if(input == "end")
break
answer.append('<').append(input)
if(input.matches(regex)){
answer.append("> is not acceptable.").append("\n")
}else{
answer.append("> is acceptable.").append("\n")
}
}
print(answer)
}
댓글남기기