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

Jun_Gyu·2023년 9월 4일
0

프로그래머스

목록 보기
12/14
post-thumbnail

해당 문제는 문자열 s의 각 단어들 중, index가 짝수번호인 글자들만 대문자로 변경하여 다시 return 하는 기능의 함수를 만드는 문제이다.

첫 풀이

우선 매개변수로 받아오는 문자열 s의 문자들을 빈칸을 기준으로 나누어 배열로 변환해준 뒤,

2중 반복문을 활용하여

index 번호가 짝수면 toUpperCase()메소드를 통해 대문자로 변경될 수 있도록 코드를 구성해보았다.

// 첫 풀이 (문자열도 배열처럼 idx로 접근! (짝수 idx만 UppderCase로))
const solution = (s) => {
    let answer = []
    let sArr = s.split(' ')
    for(let i = 0; i < sArr.length; i++) {
        let word = sArr[i]
        let upperWord = ''
        console.log("들어올 단어 : ", word)
        for (let y = 0; y < word.length; y++) {
            console.log('현재 만들어진 단어 : ', upperWord)
            if(y % 2 === 0){
                upperWord += word[y].toUpperCase()
                console.log("합쳐진 완성단어 : ", upperWord)
            } else {
                upperWord += word[y]
            }
            if(word.length-1 === y) {
                answer.push(upperWord)
            }
        }
    }
    console.log("완성된 anwer 배열 : ", answer)
  	console.log("최종 return값 : ", answer.join(' '))
    return answer.join(' ');
}

(사실 여기까지 오는데도 시간이 좀 결렸다)

split()을 통해 분리된 단어들을 sArr라는 변수에 배열 데이터로 담아주었으며,

첫번째 for문에서는 배열의 각 단어들을 순회하도록 해주었다.

그리고 upperWord 라는 빈 문자열 변수를 선언하여 두번째 반복문에서 대문자로 변경된 후에는

미리 선언해두었던 answer라는 빈 배열에 하나씩 push해주었고,

마지막으로는 배열의 데이터들을 빈칸으로 구분되어 문자열 상태로 출력될 수 있도록 join(' ')를 사용했다.

이를 한눈에 판단하기 쉽게 console.log를 통해서 각 기능이 수행될때마다 단어들의 상태를 출력할 수 있도록 했다.

위의 과정을 거치고 출력을 해보면..

위와같이 잘 작동됨을 확인할 수 있다.


하지만 문제가 발생했으니..


오마이갓;;


뭐가 문제일까..?

사실 기능상으로는 완벽하게 작동한다. 하지만 오답률(?) 93.7%인 이유는 분명히 존재했다.

처음 문제를 읽었을때,

이 부분만 읽고

'아, s로 들어오는 모든 문자열은 소문자로 들어오는구나 ㅇㅋㅇㅋ'
'대문자로만 바꿔주면 되겠네'

라고 착각했던 것이다..

위의 풀이 중 한가지 허점이 있었다면,

if(y % 2 === 0) { // 짝수번째 idx 알파벳은 대문자로 만들어주고,
	upperWord += word[y].toUpperCase()
	console.log("합쳐진 완성단어 : ", upperWord)
} else {
	upperWord += word[y] // 홀수번째 idx 알파벳은 그냥 통과시켜~
}

두번째 for문의 조건문에서 대문자인 경우는 제대로 처리를 해줬는데,

소문자로 나가는 경우에는 그냥 변수에 밀어넣어버린것이다..


다시말해, 매개변수로 들어오는 문자열이 만약 전부 대문자로 들어온다면,

리턴해서 나가는 문장도 전부
'TRY HELLO WORLD'
처럼 대문자가 될 거라는 이야기이다.

그리하여 else문의 조건에 toLowerCase()라는 메소드를 추가하여 소문자로 반환되도록 코드를 추가해주었다..

그리고 확인해본 결과..

오마이갓222;;

왜 또..?

JS 코드 실행기까지 투입하여 문제를 확인해보았는데도, 멀쩡하게 잘 출력됨을 확인할 수 있다..

한시간 이상 찾아보다가 도무지 해결방법을 찾을 수 없어 GPT 선생님께 여쭤보기로 했다..

말하자면,

현재 코드에서 빈 배열 answer로 변경된 단어들을 push하고자 할 때,
두번째 for문에다 마지막 단어까지 작업이 끝나면 push한다 라는 작업을 진행시키게 되면
예기치 못한 오류(?) 가 발생한다고 한다.. 코드실행기에서는 잘만되는데

그리하여 answer.push(upperWord)는 두번째 for문에서 꺼내서 첫번째 for문의 맨 아래쪽에 위치 시켜주어야 한다.

코드를 수정해준 후, 남아있던 조건문은 삼항 연산자로 수정하여 코드를 좀 더 간결하게 해주었다.

// 수정된 답안
const solution = (s) => {
    let answer = []
    let sArr = s.split(' ')
    for(let i = 0; i < sArr.length; i++) {
        let word = sArr[i]
        let upperWord = ''
        for (let y = 0; y < word.length; y++) {
            upperWord += (y % 2 === 0 
                          ? word[y].toUpperCase() 
                          : word[y].toLowerCase() )
        }
        answer.push(upperWord)
    }
    return answer.join(' ');
}

위의 문제점에 대해서 명확하게 설명을 할 수 없는 상태라, 현재 스터디 그룹의 멘토님께 별도로 질문을 드린 상태이다.

이후 확실하게 이해가 된 상태에서 해당 내용을 추가해서 포스팅 할 예정이다.

해결완료!!!

문제점을 찾았다.

아래 기존 코드의 경우에는,

const solution = (s) => {
    let answer = []
    let sArr = s.split(' ')
    for(let i = 0; i < sArr.length; i++) {
        let word = sArr[i]
        let upperWord = ''
        for (let y = 0; y < word.length; y++) {
            upperWord += (y % 2 === 0 
                          ? word[y].toUpperCase() 
                          : word[y].toLowerCase() )
            if(word.length === y+1) {
                answer.push(upperWord)
            }
        }
        
    }
    return answer.join(' ');
}

사실 원래 구현하려던 기능적으로는 잘 동작하는것이 맞다.

단어마다 한칸씩 띄어쓰기로 answer를 문자열로 출력해준다.

하지만 한가지 간과한것이 있었는데,

solution('   T he re       is No th ing Here   ')

와 같이 빈칸이 한개가 아닌 여러개인 경우에는

   T He Re       Is No Th InG HeRe   

위처럼 단어와는 별개로 띄어쓰기도 갯수만큼 적용이 되어 출력되어야 한다는 점이다.

그래서 이러한 부분을 적용시키기 위해
아래와 같이 anwer.push(upperWord)를 2번째 for문에서 꺼내
첫번째 for문이 끝나는 부분에 위치시켜야 한다.

const solution = (s) => {
    let answer = []
    let sArr = s.split(' ')
    for(let i = 0; i < sArr.length; i++) {
      	// 만약 
        let word = sArr[i]
        let upperWord = ''
        for (let y = 0; y < word.length; y++) {
            upperWord += (y % 2 === 0 
                          ? word[y].toUpperCase() 
                          : word[y].toLowerCase() )
        }
        answer.push(upperWord)
    }
    return answer.join(' ');
}

위의 코드를 조금 더 직관적으로 확인하기 위해서 console.log를 사용해보았다.

위와 같은 느낌으로

빈칸인 경우에는 단어의 길이 자체가 존재하지 않으니, 2번째의 for문이 동작하지 않을 것이고, 빈 문자열인 변수upperWord가 그대로 배열 answer에 push되는 형식이라고 보면 되겠다..!


겨우 1레벨 짜리 문제를 푸는데 다사다난한 대장정이었지만

잘 정리된 풀이를 보고 있자니 카타르시스를 느낀다..ㅎㅎ

profile
시작은 미약하지만, 그 끝은 창대하리라

0개의 댓글