프로그래머스(Programmers) 이상한 문자 만들기 - javascript

ppmyor·2022년 7월 5일
0

Programmers-JavaScript

목록 보기
1/16
post-thumbnail

프로그래머스(Programmers) 이상한 문자 만들기

🙋‍♀️ 문제 정보

문제 설명

문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

제한 사항

  • 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
  • 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

입출력 예

입력

"try hello world"

출력

"TrY HeLlO WoRlD"

입출력 예 설명

"try hello world"는 세 단어 "try", "hello", "world"로 구성되어 있습니다. 각 단어의 짝수번째 문자를 대문자로, 홀수번째 문자를 소문자로 바꾸면 "TrY", "HeLlO", "WoRlD"입니다. 따라서 "TrY HeLlO WoRlD" 를 리턴합니다.

🔥 시도 과정

세상 간단한 문제 같은데 왜 이렇게 오래 걸렸는가..

첫번째 소스 코드

function solution(s) {
    s = s.split(" ");
    let answer = "";
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < s[i].length; j++) {
            if (j % 2 === 0) {
                // 대문자
              	answer += String.fromCharCode(j[i][j].charCodeAt(0) - 32);
            } else {
                // 소문자
                answer += String.fromCharCode(j[i][j].charCodeAt(0));
            }
        }
        anser += " ";
    }
    return answer.trim();
}

결과

  • 실패

해결 방법

문제보자마자 음 대소문자 변환? 아스키코드 쓰면 되겠다. 하고 쭉쭉 적어나갔는데 실패가 떠서 당황했다.
문자 -> 아스키코드 -> 문자로 변환하는 과정에서
1. j가 짝수라면 아스키코드에서 32를 빼주면서 대문자로 변환
2. j가 홀수라면 그대로 삽입하는 풀이였다.
정신차리고 문제를 잘 살펴보니 문자열에 소문자만 들어온다는 소리가 없다. 🤦‍♀️
입력값에 대한 대소문자 예외처리를 삽입해서 다시 코드를 작성했다.

두번째 소스 코드

function solution(s) {
    s = s.split(" ");
    let answer = "";
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < s[i].length; j++) {
            if (j % 2 === 0) {
                // 대문자
                answer +=
                    j[i][j].charCodeAt(0) > 65 && j[i][j].charCodeAt(0) < 90
                        ? String.fromCharCode(j[i][j].charCodeAt(0))
                        : String.fromCharCode(j[i][j].charCodeAt(0) - 32);
            } else {
                // 소문자
                answer +=
                    j[i][j].charCodeAt(0) > 65 && j[i][j].charCodeAt(0) < 90
                        ? String.fromCharCode(j[i][j].charCodeAt(0) + 32)
                        : String.fromCharCode(j[i][j].charCodeAt(0));
            }
        }
        anser += " ";
    }
    return answer.trim();
}

결과

  • 실패

해결 방법

그래서 대소문자 예외처리 해줬는데 왜 안되는 것인가.
우선, trim이 문제였다.
백준같은 경우는 입력값 뒤에 쓸데없는 공백이 붙는 경우가 없어서 trim을 잘 썼었는데 프로그래머스는 입력값 맨 마지막 값에 공백이 붙는 경우도 있어 trim을 신중하게 써야하는 것 같았다.
둘째로, 아스키코드 변환 과정에 있어 문자 -> 아스키코드 -> 문자 과정이 복잡하기 때문에 실수가 발생할 것같아 toUpperCase(), toLowerCase() 메소드로 변환해주었다.
해당 메소드로 변환하면서 입력값이 대문자인지 소문자인지 판별해서 예외처리를 해주지 않아도 되어서 코드가 한결 간략해졌다.

✨ 풀이

소스 코드

function solution(s) {
    s = s.split(" ");
    let answer = "";
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < s[i].length; j++) {
            answer += j % 2 === 0 ? s[i][j].toUpperCase() : s[i][j].toLowerCase();
        }
        i === s.length - 1 ? (answer += "") : (answer += " ");
    }
    return answer;
}

결과

  • 성공

해결 방법

우선, 문자 -> 아스키코드 -> 문자 과정을 대소문자 변환 메소드로 변환해주었다.
기존 코드에서는 단어의 마지막 부분에 공백을 붙여주고, 마지막 공백은 trim 처리를 해주었는데 문자열 자체에 마지막 자리 공백이 들어오는 경우가 있어 이렇게 처리하면 실패이다.
따라서, trim을 제거하고 해당 단어가 마지막 단어라면 공백을 붙이지 않고, 마지막 단어가 아니라면 공백을 붙여주는 조건문을 붙여 처리했다.

➕ 더 나아가서

map을 통해서 조금 더 간략하게 나타내는 방법을 써보았는데, 이중 반복문 구조이기 때문에 헷갈린다.

function solution(s) {
    return s
        .split(" ")
        .map((v) =>
            v.split("")
                .map((char, i) => (i % 2 === 0 ? char.toUpperCase() : char.toLowerCase()))
                .join("")
        )
        .join(" ");
}

split을 해주기 때문에 map이 종료되는 시점에서 join을 해주어야한다.
겉의 map은 join은 단어의 마지막이기 때문에 join(" ") 처리를 하고, 내부의 map은 단어의 문자 별로 split을 해두었기 때문에 join("") 처리를 한다.

profile
유영하는 개발자

0개의 댓글