[Java] 프로그래머스(level-2) - JadenCase 문자열 만들기

입출력 예시
Input-1
“3people unFollowed me”
Output-1
“3people Unfollowed Me”
Input-2
“for the last week”
Output-2
“For The Last Week”
문제 풀이
주어진 문자열에서 단어의 첫문자를 대문자로 바꾸어 반환해야 한다.
이 때, 첫 문자는 숫자가 아니어야 한다.
그리고 단어 중 첫 문자가 아닌 문자가 대문자일 땐 소문자로 변환해야 한다.
먼저 주어진 문자열을 모두 소문자로 변경하면 첫문자가 아닌 문자를 일일이 소문자로 변환할 필요가 없다.
주어진 문자열 s를 char형 배열로 변환하여 공백을 제외한 모든 문자를 소문자로 변환하여 저장하였다.
1
2
3
4
5
char[] arr = s.toCharArray();
for(int i=0; i<arr.length; i++) {
if(arr[i]==' ') arr[i] = ' ';
else arr[i] = Character.toLowerCase(arr[i]);
}
이제 첫 문자가 아닌 문자가 대문자일 경우를 고려하지 않아도 된다.
다음으로 소문자로 변환된 arr을 반복하며 단어의 첫문자일 때 대문자로만 변경해주면 된다.
어떻게 단어의 첫문자인지 알 수 있을까?
주어진 문자열 “for the last week”로 예를 들어서 설명하자면,
arr 배열에는 [‘f’,’o’,’r’,’ ‘,’t’,’h’,’e’,’ ‘,’w’,’e’,’e’,’k’]로 담길 것이다.
이 arr 배열을 순회하며 현재 인덱스의 값이 ‘ ‘(공백)이라면 다음 인덱스의 값을 대문자로 변환하면 되고
위 조건을 만족하지 못했다면 현재 인덱스 값을 그대로 넣으면 될 것이라 생각했다.
1
2
3
4
5
6
7
8
9
10
for(int i=0; i<arr.length; i++) {
if(i<arr.length-1) {
if(arr[i]==' ' && Character.isLowerCase(arr[i+1])) { // 첫 단어 검증
answer += " " + Character.toUpperCase(arr[i+1]);
i+=2;
}
}
if(i==0 && Character.isLowerCase(arr[0])) answer += Character.toUpperCase(arr[i]); // 제일 첫번째 글자
else answer += arr[i];
}
위 코드와 같이 배열에서 공백값을 검증하여 다음 문자를 대문자로 변환하여 answer에 담도록 하였다.
그러나, 다른 테스트케이스를 테스트하며 문제가 있음을 알게 되었다.
오류 발견


위 디버깅은 “f o r for”라는 문자열로 테스트를 해본 내용이다.
위 사진과 같이 중간의 단어 r이 대문자로 변환되지 않았다.
이외 다른 문자열로 테스트했을 때도 비슷하게 중간 단어들의 대문자 변환이 이루어지지 않았다.
위 코드 반복문 내에서 첫 단어를 검증할 때 단어의 첫문자를 대문자를 변환하여 저장하고 인덱스를 증가시킨다.
이 인덱스를 증가시키고 맨 위 if문부터 수행문이 동작되는줄 알았지만, 아니었다.
1
2
3
4
5
6
7
8
9
10
for(int i=0; i<arr.length; i++) {
if(i<arr.length-1) {
if(arr[i]==' ' && Character.isLowerCase(arr[i+1])) { //1
answer += " " + Character.toUpperCase(arr[i+1]);
i+=2; // 오류가 발생한 증가문, 인덱스 증가후 밑의 조건문으로 빠진다.
}
}
if(i==0 && Character.isLowerCase(arr[0])) answer += Character.toUpperCase(arr[i]); //2
else answer += arr[i];
}
1
2
3
4
5
arr = ['f',' ','o',' ','r',' ','f','o','r'], length:9
i = 0 = 'f', answer="F"
i = 1 = ' ', answer="F O", i는 2증가
i = 3 = ' ', answer="F O r" //여기서 반복문 내 수행문을 제대로 수행하지 못함, 2번 조건문의 else문을 타버림.
... 이하 생략
오류 해결
반복문 코드가 잘못되었음을 인지하였고, 그렇다면 접근방식이 달라져야 한다고 생각했고 아래의 아이디어를 도출하였다.
- 현재 인덱스가 공백이 아닌 현재 인덱스-1의 값이 공백일 경우를 고려하자.
위 로직대로라면 arr 배열을 반복하며 현재 인덱스의 값이 문자이고 이전 인덱스의 값이 ‘ ‘(공백)이라면
현재 인덱스의 값을 대문자로 변환하여 answer에 담고 인덱스를 증가시킬 필요가 없게 된다.
1
2
3
4
for(int i=1; i<arr.length; i++) {
if(Character.isLowerCase(arr[i]) && arr[i-1]==' ') answer += Character.toUpperCase(arr[i]);
else answer += arr[i];
}
위와 같이 로직을 변경하여 테스트해보니 발생한 오류를 정상적으로 해결할 수 있었다.
작성 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.*;
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
long start = System.currentTimeMillis();
solution(s);
long end = System.currentTimeMillis();
System.out.println("\n수행시간 = " + (end-start));
}
public static String solution(String s) {
String answer = "";
char[] arr = s.toCharArray();
for(int i=0; i<arr.length; i++) {
if(arr[i]==' ') arr[i] = ' ';
else arr[i] = Character.toLowerCase(arr[i]);
}
if(Character.isLowerCase(arr[0])) answer += Character.toUpperCase(arr[0]);
else answer += arr[0];
for(int i=1; i<arr.length; i++) {
if(Character.isLowerCase(arr[i]) && arr[i-1]==' ') answer += Character.toUpperCase(arr[i]);
else answer += arr[i];
}
return answer;
}
}
회고
- 여러개의 공백까지 포함된 문자열을 String[] arr = str.split(“”, -1)식의 방법도 있겠지만, char형 배열을 활용해 대문자 및 소문자 제어가 편하도록 하였다.
- for문 내 조건문에서 인덱스를 증가시키면 처음부터 수행문을 다시 수행하는 줄 알았는데 아니었다. 반복문 내에서 인덱스를 증가시킬 때 유의해서 사용해야 겠다.