[백준] 팰린드롬 만들기 (1213)(kotlin)

문제 설명

백준 1213번 문제 링크

입력 및 출력

» 입력

첫째 줄에 임한수의 영어 이름이 있다. 알파벳 대문자로만 된 최대 50글자이다.

» 출력

첫째 줄에 문제의 정답을 출력한다. 만약 불가능할 때는 “I’m Sorry Hansoo”를 출력한다. 정답이 여러 개일 경우에는 사전순으로 앞서는 것을 출력한다.

예제 입출력(테스트케이스)

입력 출력
AABB ABBA
AAACC ACACA
AAAAC AACAA

문제 풀이1

var evenCount = 0
var oddCount = 0
var nameLength = 0
val intArr = IntArray(26) { 0 }

fun main(args: Array<String>) = with(System.`in`.bufferedReader()) {
    val name = readLine()

    // name의 길이 값을 전역 변수에 저장
    nameLength = name.length

    // name의 글자를 하나씩 탐색하면서 26 sized IntArray에 index로 카운트
    // intArr[0] -> 'A'의 갯수, ~, intArry[25] -> 'Z'의 갯수
    name.forEach { intArr[it - 'A']++ }

    // intArr을 순차 탐색하면서 짝수개를 가진 글자수와 홀수개를 가진 글자수를 카운
    intArr.forEach {
        if (it != 0) {
            if (it % 2 == 0) evenCount++
            else oddCount++
        }
    }

    // name의 길이가 짝수일 경우
    if (nameLength % 2 == 0) {
        // 홀수개를 가진 글자가 0개가 아닐 경우 팰린드롬이 불가능
        if (oddCount != 0) {
            println("I'm Sorry Hansoo")
            return
        } else {
            // 홀수개를 가진 글자가 없을 경우 팰린드롬 가능
            println(palindrome())
        }
    } else {    // name의 길이가 홀수일 경우
        // 홀수개를 가진 글자가 없거나 2개 이상일 경우 팰린드롬 불가능
        if (oddCount != 1) {
            println("I'm Sorry Hansoo")
            return
        } else {
            // 홀수개를 가진 글자가 딱 하나만 있을 경우 팰린드롬 가능
            println(palindrome())
        }
    }

}

fun palindrome(): String {
    var ret = ""

    when (nameLength % 2) {
        // name의 길이가 짝수일 경우
        0 -> {
            // intArr를 통해 'A'부터 'Z'까지 순차탐색
            for (i in intArr.indices) {
                // intArr[i]의 값이 존재하는 경우만
                if (intArr[i] != 0) {
                    // 개수(짝수) / 2 개 만큼만 ret 변수에 누적
                    repeat(intArr[i] / 2) {
                        ret += ('A' + i)
                    }
                }
            }
            // 반복문이 끝나면 팰린드롬 문자열의 대칭성을 가진 절반만 완성됨
            // 나머니 절반은 기존 만들어진 문자열을 거꾸로 해서 합치면 끝
            // e.g. ABABABAB -> 반복문 -> AABB -> 거꾸로 합치기 -> "AABB" + "BBAA" -> "AABBBBAA"
            ret += ret.reversed()
        }
        // name의 길이가 홀수일 경우
        else -> {
            // 홀수는 단 하나만 존재해야 했고, 홀수개를 가진 글자가
            // 어느 것인지 저장할 변수 선언
            var oddIdx = 0

            // intArr를 통해 'A'부터 'Z'까지 순차탐색
            for (i in intArr.indices) {
                // intArr[i]의 값이 존재하는 경우만
                if (intArr[i] != 0) {
                    // 탐색한 값이 짝수일 경우
                    if (intArr[i] % 2 == 0) {
                        // 개수(짝수) / 2 개 만큼만 ret 변수에 누적
                        repeat(intArr[i] / 2) {
                            ret += ('A' + i)
                        }
                        // 탐색한 값이 홀수일 경우
                    } else {
                        // 홀수개를 가진 글자의 갯수가 3이상인 경우
                        if (intArr[i] > 2) {
                            // 개수(홀수) / 2 개 만큼만 ret 변수에 누적
                            repeat(intArr[i] / 2) {
                                ret += ('A' + i)
                            }
                        }
                        // 홀수개의 글자를 포함한 팰린드롬을 만들때,
                        // 대칭성을 위해 문자열 가장 가운데 위치하게 될
                        // 홀수개를 가진 글자값 저장
                        oddIdx = i
                    }
                }
            }
            // 반복문이 끝나면 팰린드롬 문자열의 대칭성을 가진 절반만 완성됨
            // 홀수개를 가진 글자를 가운데 위치시키고
            // 나머니 절반은 기존 만들어진 문자열을 거꾸로 해서 합치면 끝
            // e.g. if (홀수갯수 < 2) AABBC -> "AB" + "C" + "BA"
            // e.g. if (홀수갯수 > 2) AABBBCC -> "ABC" + "B" + "CBA"
            ret += (('A' + oddIdx) + ret.reversed())
        }
    }

    return ret
}