알고리즘🅰/프로그래머스

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

개발조각 2022. 2. 28. 15:26
728x90
반응형

이번 문제는 어려운 건 아니었는데 푸는데 오래 걸렸어요.😂 빠르게 해결방안에 대해 설명하겠습니다.

 


해결방안

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

 

해결방안 설명

  1. 문자열s를 단어를 원소로 가지는 배열 만들기
  2. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸고 각 단어는 하나 이상의 공백 문자로 구분하기

 

1단계. 문자열s를 단어를 원소로 가지는 배열 만들기

let str = '';
let strArr = s.split(' ');
  • let str = ''; : 결과 값을 담기 위한 문자열 변수
  • let strArr = s.split(' '); : 문자열 s의 공백 기준으로, 한 단어씩 담아줌
MDN Web Docs
split()  메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.

구문 : str.split([separator[, limit]])

  • separator Optional
    원본 문자열을 끊어야 할 부분을 나타내는 문자열을 나타냅니다. 실제 문자열이나 정규표현식을 받을 수 있습니다. 문자열 유형의 separator가 두 글자 이상일 경우 그 부분 문자열 전체가 일치해야 끊어집니다. separator가 생략되거나 str에 등장하지 않을 경우, 반환되는 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우 str의 각각의 문자가 배열의 원소 하나씩으로 변환됩니다.
  • limit Optional
    끊어진 문자열의 최대 개수를 나타내는 정수입니다. 이 매개변수를 전달하면 split() 메서드는 주어진 separator가 등장할 때마다 문자열을 끊지만 배열의 원소가 limit개가 되면 멈춥니다. 지정된 한계에 도달하기 전에 문자열의 끝까지 탐색했을 경우 limit개 미만의 원소가 있을 수도 있습니다. 남은 문자열은 새로운 배열에 포함되지 않습니다.
// split 예제
var myString = 'Hello World. How are you doing?';
var splits = myString.split(' ', 3);
console.log(splits); //["Hello", "World.", "How"]

// limit를 안 쓸 경우
let mystring = 'Hello';
console.log(mystring.split('')); // [ 'H', 'e', 'l', 'l', 'o' ]

여기서 split()메소드를 사용한 이후는 2단계에서 각 단어마다 문자(알파벳)를 제어하기 위해 미리 배열로 만들었습니다.

각 문자만큼만 배열에 담기 위해 공백기준으로 ' '을 넣어 주었습니다.

 

테스트 1 (s = "try hello world")
let strArr = s.split(' ');
let strArr = [ 'try', 'hello', 'world' ]

 

2단계. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸고 각 단어는 하나 이상의 공백 문자로 구분하기

for(let i=0; i<strArr.length; i++){
    for(let j=0; j<strArr[i].length; j++){
        j%2 ? str += strArr[i][j].toLowerCase() : str += strArr[i][j].toUpperCase();
    }
    if(i < strArr.length-1) str += ' ';
}
return str;

먼저 중복 for문을 썼습니다.

  • for(let i=0; i<strArr.length; i++) : 첫 번째 for문, strArr배열의 길이만큼 반복함
  • for(let j=0; j<strArr[i].length; j++) : 두 번째 for문, strArr의 단어(원소)의 문자(알파벳)의 개수만큼 반복함

strArr = [ 'try', 'hello', 'world' ]에서 try의 y를 구하고 싶으면

  • strArr[0][2]

이렇게 구하면 됩니다.

 

그리고 두 번째 for문에서 j=0부터 시작한 이유는 제한 사항에서 "첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다."라는 조건이 있는 것을 보아 단어의 문자를 1, 2, 3.... 이런 순으로 세는 게 아니라 0, 1, 2... 순으로 셉니다. 그래서 두 번째 for문에서 j=0부터 시작했습니다.

 

    for(let i=0; i<strArr.length; i++){
        console.log(`i : ${i}, strArr[${i}] : ${strArr[i]}`);
        for(let j=0; j<strArr[i].length; j++){
            console.log(`j : ${j}, strArr[${i}][${j}] : ${strArr[i][j]}`);
        }
    }
테스트 1 (s = "try hello world")
let strArr = [ 'try', 'hello', 'world' ]
i : 0, strArr[0] : try
j : 0, strArr[0][0] : t
j : 1, strArr[0][1] : r
j : 2, strArr[0][2] : y

i : 1, strArr[1] : hello
j : 0, strArr[1][0] : h
j : 1, strArr[1][1] : e
j : 2, strArr[1][2] : l
j : 3, strArr[1][3] : l
j : 4, strArr[1][4] : o

i : 2, strArr[2] : world
j : 0, strArr[2][0] : w
j : 1, strArr[2][1] : o
j : 2, strArr[2][2] : r
j : 3, strArr[2][3] : l
j : 4, strArr[2][4] : d

이렇게 각 단어 별로 인덱스를 만들어 단어의 문자를 제어하게 되었습니다.

 

 

이제 "각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸기"를 구해야 됩니다.

여기서 주의해야 되는 점

  1. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로
  2. 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 됨

이 두 가지를 주의해야 됩니다.

1번에서는 테스트 1번에 단어가 다 소문자라 해도 무조건 홀수번째는 소문자로 처리해야 된다는 거고

2번에서는 0은 짝수로 판단하라는 겁니다. (그래서 조건문에서 조건을 j%2를 써줌)

 

먼저 "알파벳 대소문자 변환 방법"에 대해 설명하자면 toUpperCase() toLowerCase() 메서드를 사용해야 됩니다.

 

MDN Web Docs
toUpperCase() 메서드는 문자열을 대문자로 변환해 반환합니다.

구문 : str.toUpperCase()

// toUpperCase()메서드 예제
const sentence = 'The quick brown fox jumps over the lazy dog.';
console.log(sentence.toUpperCase()); // "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG."

 

MDN Web Docs
toLowerCase() 메서드는 문자열을 소문자로 변환해 반환합니다.

구문 : str.toLowerCase()

// toLowerCase()메서드 예제
const sentence = 'The quick brown fox jumps over the lazy dog.';
console.log(sentence.toLowerCase()); // "the quick brown fox jumps over the lazy dog."

 

저는 toUpperCase() 와 toLowerCase() 메서드와 삼항 조건문을 가지고 "각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸기"를 구했습니다.

 

삼항 연산자

구문 : 조건 ? true : false

  • 조건이 true이면 true를 실행
  • 조건이 false이면 false를 실행

j%2 ? str += strArr[i][j].toLowerCase() : str += strArr[i][j].toUpperCase();

  • 조건 : j%2 -> j가 홀수이면
  • true : str += strArr[i][j].toLowerCase() -> strArr[i][j]를 소문자로 바꾸어서 str문자열에 추가하기
  • false : str += strArr[i][j].toUpperCase(); -> strArr[i][j]를 대문자로 바꾸어서 str문자열에 추가하기
    for(let i=0; i<strArr.length; i++){
        for(let j=0; j<strArr[i].length; j++){
            j%2 ? str += strArr[i][j].toLowerCase() : str += strArr[i][j].toUpperCase();
        }
    }
    console.log(str);
테스트 1 (s = "try hello world")
let strArr = [ 'try', 'hello', 'world' ]
i : 0, strArr[0] : try
j : 0, strArr[0][0] : t -> j가 짝수, 대문자 : str = 'T'
j : 1, strArr[0][1] : r -> j가 홀수, 소문자 : str = 'Tr'
j : 2, strArr[0][2] : y -> j가 짝수, 대문자 : str = 'TrY'

i : 1, strArr[1] : hello
j : 0, strArr[1][0] : h -> j가 짝수, 대문자 : str = 'TrYH'
j : 1, strArr[1][1] : e -> j가 홀수, 소문자 : str = 'TrYHe'
j : 2, strArr[1][2] : l -> j가 짝수, 대문자 : str = 'TrYHeL'
j : 3, strArr[1][3] : l -> j가 홀수, 소문자 : str = 'TrYHeLl'
j : 4, strArr[1][4] : o -> j가 짝수, 대문자 : str = 'TrYHeLlO'

i : 2, strArr[2] : world
j : 0, strArr[2][0] : w -> j가 짝수, 대문자 : str = 'TrYHeLlOW'
j : 1, strArr[2][1] : o -> j가 홀수, 소문자 : str = 'TrYHeLlOWo'
j : 2, strArr[2][2] : r -> j가 짝수, 대문자 : str = 'TrYHeLlOWoR'
j : 3, strArr[2][3] : l -> j가 홀수, 소문자 : str = 'TrYHeLlOWoRl'
j : 4, strArr[2][4] : d -> j가 짝수, 대문자 : str = 'TrYHeLlOWoRlD'

str = 'TrYHeLlOWoRlD'

 

str문자열에 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸어 주었는데요.

여기서 구해야 되는 게 "각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾸기" 뿐만 아니라 "각 단어는 하나 이상의 공백 문자로 구분하기"도 해주어야 됩니다.

 

공백을 넣어줘야 되는 부분이

  • 테스트 1에서 'TrYHeLlOWoRlD' -> 'TrY HeLlO WoRlD'

단어가 끝나는 중간 지점에 넣어주어야 됩니다.

그래서 단어의 문자가 끝나는 즉 j가 끝나는 지점 다음에 넣어주어야 됩니다.

그래야 처음에 공백이 생기지 않고 첫 번째 단어가 끝난 다음에 공백을 넣어 줄 수 있습니다.

    for(let i=0; i<strArr.length; i++){
        for(let j=0; j<strArr[i].length; j++){
            j%2 ? str += strArr[i][j].toLowerCase() : str += strArr[i][j].toUpperCase();
        }
        // 요지점에 "각 단어는 하나 이상의 공백문자로 구분하기" 코드를 넣어 주었습니다.
    }

요지점에 공백 코드를 넣어주면 문자열 str에 처음 자리에 공백을 안 넣게 되고

이제 마지막에 공백이 넣어지지 않게 조건문을 넣어주면 됩니다.

if(i < strArr.length-1) str += ' ';

  • if(i < strArr.length-1) : 마지막 단어가 되기 전까지
  • str += ' ' : 공백 추가하기
테스트 1 (s = "try hello world")
let strArr = [ 'try', 'hello', 'world' ]
i : 0, strArr[0] : try
j : 0, strArr[0][0] : t -> j가 짝수, 대문자 : str = 'T'
j : 1, strArr[0][1] : r -> j가 홀수, 소문자 : str = 'Tr'
j : 2, strArr[0][2] : y -> j가 짝수, 대문자 : str = 'TrY'

if(i < strArr.length-1) str += ' '; -> str = 'TrY '

i : 1, strArr[1] : hello
j : 0, strArr[1][0] : h -> j가 짝수, 대문자 : str = 'TrY H'
j : 1, strArr[1][1] : e -> j가 홀수, 소문자 : str = 'TrY He'
j : 2, strArr[1][2] : l -> j가 짝수, 대문자 : str = 'TrY HeL'
j : 3, strArr[1][3] : l -> j가 홀수, 소문자 : str = 'TrY HeLl'
j : 4, strArr[1][4] : o -> j가 짝수, 대문자 : str = 'TrY HeLlO'

if(i < strArr.length-1) str += ' '; -> str = 'TrY HeLlO '

i : 2, strArr[2] : world
j : 0, strArr[2][0] : w -> j가 짝수, 대문자 : str = 'TrYHeLlOW'
j : 1, strArr[2][1] : o -> j가 홀수, 소문자 : str = 'TrYHeLlOWo'
j : 2, strArr[2][2] : r -> j가 짝수, 대문자 : str = 'TrYHeLlOWoR'
j : 3, strArr[2][3] : l -> j가 홀수, 소문자 : str = 'TrYHeLlOWoRl'
j : 4, strArr[2][4] : d -> j가 짝수, 대문자 : str = 'TrYHeLlOWoRlD'

if(i < strArr.length-1) str += ' '; -> str = 'TrY HeLlO WoRlD'
str = 'TrY HeLlO WoRlD'

여기까지 프로그래머스 이상한 문자 만들기 해결방안에 대해 설명해보았습니다.

728x90
반응형