자바스크립트 알고리즘

[프로그래머스 L1] 이상한 문자 만들기

옐 FE 2022. 3. 16. 09:57

https://programmers.co.kr/learn/courses/30/lessons/12930

 

코딩테스트 연습 - 이상한 문자 만들기

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

programmers.co.kr

 


 

이 문제에서 유의해야할 점은 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야 한다. 그리고 첫 번째 글자는 0번째 인덱스로 봐서 짝수번째 알파벳으로 처리해야 한다.

 

 

문제를 어떻게 접근해야할까 고민했는데, 

  1. 문자열을 공백을 기준으로 단어를 나눠서 하나의 배열을 만든다.
  2. 배열 안에 있는 단어 하나씩 알파벳 하나, 하나 순환하면서 인덱스별로 나눈다.
  3. 인덱스가 짝수인지, 홀수인지 확인해서 짝수 인덱스는 대문자로 변환한다.

 

function solution(s) {
    const answerArr = [];
    const isEven = (index) => index % 2 === 0;
    
    s.split(' ')
     .map(word => word + ' ')
     .forEach(word => {
        for(let i = 0; i < word.length; i++) {
            if (word[i] === ' ' || !isEven(i)) {
                answerArr.push(word[i].toLowerCase());
           } else {
                answerArr.push(word[i].toUpperCase());
            }
        }
    });
    
    return answerArr.join('').slice(0, answerArr.length - 1);
}

 

코드를 작성할 때 for문을 잘 쓰지 않는 편인데도 이상하게 코테 문제를 풀려고 하다보면 문자열 또는 배열을 순환해야할 때가 있어서 문자열이나 배열의 method가 떠오르지 않으면 결국엔 for문으로 접근하게 된다.

 

전에 스터디에서 문제를 함께 풀 때, 짝수인지 아닌지 판별해서 true 또는 false를 반환하는 함수를 만든 분이 있어서 이번에도 간단하게 그 함수를 만들어서 문자열 알파벳의 인덱스가 짝수인지, 아닌지 판별하는 함수를 만들었다.

 

공백을 기준으로 split을 써서 문자열을 배열에 넣어주고, 결국에 반환해야 하는 값이 공백을 포함한 문자열이기 때문에 map을 써서 단어마다 알파벳 마지막에 공백을 넣어주고, 공백을 넣어준 단어를 forEach에 써서 그 안에서 인덱스를 따지는 for문에 if/else를 써서 알파벳 하나마다 소문자 또는 대문자로 변환해서 만들어둔 answerArr에 넣어주는 방식으로 풀었다.

 

마지막에 반환할 때는 공백을 포함한 배열을 join으로 묶어주는데, 마지막 단어 넣어준 공백을 빼주기 위해서 slice를 썼다. 

 


 

여기서 제시해준 테스트 케이스 "try hello world"로 했을 때는 문자열이 전부 다 소문자여서 인덱스가 홀수일 때, toLowerCase()를 쓸 생각을 하지 못했다. 그래서 제출했을 때 하나 빼고 전부 실패로 떠서 이해를 할 수가 없었는데, 스터디원들과 풀이를 공유하며 하나 빼고 다 실패했다고 하니, 알파벳이 대문자일 수도 있지 않겠냐 라는 경우의 수를 말해줘서 

if (word[i] === ' ' || !isEven(i)) {
    answerArr.push(word[i].toLowerCase());

공백이거나 알파벳의 인덱스가 홀수일 때 소문자로 만들어주는 method를 넣어주니 테스트를 모두 통과하고 점수를 얻었다-!

 

 


 

 

function solution(s) {
  let answer = "";
  const arr = s.split("");
  let num = 0;

  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === " ") {
      num = 0;
      answer += " ";
      continue;
    } else if (num % 2) { // 참이면, 홀수
      answer += arr[i].toLowerCase();
      num += 1;
    } else { // 거짓이면, 짝수
      answer += arr[i].toUpperCase();
      num += 1;
    }
  }

  return answer;
}

팀원분이 공유해 준 풀이. 

 

 

 

여기서 num을 알파벳의 인덱스로 쓰도록 변수로 할당해서 쓰는 게 흥미로웠고, for문 안에서 단어의 공백을 만나면 num을 다시 0으로 만들어주고 continue를 쓰는 게 또 흥미로웠다. 그리고 num % 2는 나머지가 0 또는 1이 나올 수 밖에 없기 때문에 이걸 if 조건문에서 true 혹은 false로 값을 받아서 실행할 수 있게 하는 걸 하나 배웠다.

 

이 풀이와 내 것을 비교하니, Array method를 너무 많이 쓴 건 아닌가 라는 생각이 들긴 했다.