팰린드롬 만들기

문제

언어

  • JavaScript

순서도

  1. 이름에서 각 알파벳의 개수 세기
  2. 알파벳의 개수가 홀수인 경우의 개수 세기
  3. 알파벳의 개수가 홀수인 경우가 2 번 이상이면 “I’m Sorry Hansoo” 출력
  4. 알파벳의 개수가 홀수인 경우가 1 번 이하라면 사전 순으로 가장 앞선 팰린드롬 만들어서 출력

문제 풀이 step 1

  • 임문빈을 도와서 임한수의 영어 이름을 팰린드롬으로 바꾸는 프로그램을 작성하는 문제입니다.
  • 팰린드롬이란?
    • 거꾸로 읽어도 제대로 읽는 것과 같은 문장이나 낱말, 숫자, 문자열 등을 말합니다.
  • 팰린드롬을 만들 수 있는 경우는?
    • 문자열을 구성하는 모든 문자의 개수가 짝수개인 경우
    • 문자열을 구성하는 문자 중 단 하나의 문자만 홀수개인 경우

문제 풀이 step 2

  • 위의 팰린드롬에 관한 정보를 바탕으로 임한수의 영어 이름으로 팰린드롬을 만들 수 있는지 판별하고, 만약 만들 수 있다면 사전 순으로 가장 앞서는 팰린드롬을 만들어서 출력하면 됩니다.
  • 우선, 이름에서 각 문자의 개수를 세기 위해서 26 크기의 배열을 선언하고, 각 문자의 개수를 세어줍니다.
  • 각 문자의 개수 중에서 홀수인 경우를 셉니다.
    • 홀수인 경우가 2 번 이상일 경우 “I’m Sorry Hansoo” 를 출력합니다.
    • 홀수인 경우가 1 번 이하일 경우 팰린드롬으로 만들어서 출력합니다.
  • 팰린드롬을 만들기 위해서 우선 팰린드롬을 반으로 쪼갤 때의 왼쪽 문자열을 먼저 만듭니다.
    • 빈 문자열을 생성합니다.
    • 알파벳 순서대로 이름의 각 문자의 개수의 반만큼씩 빈 문자열에 추가해서 팰린드롬의 반을 구현합니다.
    • 위 과정을 통해서 만든 팰린드롬의 반을 뒤집어서 반대쪽 팰린드롬의 반을 구현합니다.
    • “팰린드롬의 반”“홀수인 문자 한 개”“반대쪽 팰린드롬의 반”을 모두 합치면 팰린드롬이 됩니다.
  • 위 과정을 통해서 만든 팰린드롬을 출력하면 정답입니다.
  • 추가 설명은 주석으로 작성하겠습니다.

후기

  • 팰린드롬에 대한 이해 부족과 사전순으로 앞선 문자열에 대한 이해 부족으로 상당한 시행 착오를 겪었습니다.
  • “AABBCCCDD” 일 경우, 사전순으로 앞선 팰린드롬은 “ABCDCDCBA” 인데, “ABDCCCDBA” 라고 생각을 했었습니다.
  • 홀수인 문자들이 모두 뭉쳐서 가운데로 가야한다고 잘못 생각해서 상당히 많은 시간을 허비했습니다.

소스 코드

const input = require("fs")
	.readFileSync("/dev/stdin")
	.toString()
	.trim()
	.split("\n");

const solution = (input) => {
	const name = input[0].split("").sort();

	// 이름에서 각 문자의 개수 세기
	const alphabets = Array(26).fill(0);
	for (let i = 0; i < name.length; i++) {
		alphabets[name[i].charCodeAt(0) - "A".charCodeAt(0)] += 1;
	}

	let oddCnt = 0;
	let midIdx = -1;
	for (let i = 0; i < 26; i++) {
		if (alphabets[i] === 0 || alphabets[i] % 2 === 0) continue;

		// 문자의 개수가 홀수인 경우 세기
		oddCnt += 1;
		midIdx = i;
	}

	// 문자의 개수가 홀수인 경우가 2 이상인 경우
	if (oddCnt > 1) return "I'm Sorry Hansoo";

	let res = [];
	for (let i = 0; i < 26; i++) {
		if (alphabets[i] === 0) continue;

		// 각 문자의 개수의 반 만큼씩 배열에 추가
		const alphabet = String.fromCharCode("A".charCodeAt(0) + i);
		for (let j = 0; j < parseInt(alphabets[i] / 2); j++) {
			res.push(alphabet);
		}
	}

	let palindrome = "";

	// 팰린드롬을 반으로 쪼갤 때의 왼쪽 문자열
	for (let i = 0; i < res.length; i++) {
		palindrome += res[i];
	}
	// 문자의 개수가 홀수인 문자 추가
	if (oddCnt === 1)
		palindrome += String.fromCharCode("A".charCodeAt(0) + midIdx);
	// 팰린드롬을 반으로 쪼갤 때의 오른쪽 문자열
	for (let i = res.length - 1; i >= 0; i--) {
		palindrome += res[i];
	}

	return palindrome;
};

console.log(solution(input));