[Java] 프로그래머스(level1) - 이상한 문자 만들기

Input-1
“try hello world” Output-1
“TrY HeLlO WoRlD”
Input-2
“ABC aBc abC “ Output-2
“Abc Abc Abc “
문제 풀이
문제 설명을 보면 주어진 문자열은 한개 이상의 단어로 구성되어 있으며, 각 단어는 하나 이상의 공백문자로 구분된다고 한다.
각 단어별로 짝수번째 인덱스의 단어는 대문자로, 홀수번째 인덱스의 단어는 소문자로 변경된 문자열을 반환해야 한다.
여기서 핵심은 “각 단어는 하나 이상의 공백문자로 구분된다.” 이라고 생각한다.
그럼 공백문자를 기준으로 문자열을 잘라 각 단어들에 접근하는 방법을 알아보자.
1
2
3
String str = "try hello world";
String[] arr = str.split(" ");
for(String s : arr) System.out.println(s);
먼저 java.lang.String 클래스의 split() 메서드의 regex 인자에 “ “ 값을 넣어준다면 어떤 결과가 나올까?
1
2
3
4
// "try hello world"
try
hello
world
공백값을 기준으로 문자열을 잘랐기에 위와 같은 문자열 배열을 이룰 것이다.
만약 “try hello world” 라는 입력값의 경우는 단어 사이에만 공백이 존재하기에 위 방법으로 각 단어들에 접근이 가능하다.
하지만 “try hello world” 라는 입력값의 경우 단어 사이에 여러개의 공백이 존재한다.
1
2
3
4
// "try hello world"
try
hello
world
위 방법으로는 각 단어 사이의 존재하는 여러개의 공백문자를 찾아낼 수 없다.
우리가 원하는 것은 각 단어 사이의 공백문자까지 포함한 문자열을 반환하는 것이다.
어떻게 단어 사이의 공백문자를 찾을까?
해답은 split() 메서드에 있다. split() 메서드는 사용하는 방식이 2가지가 있다.
- public String[] split(String regex)
- public String[] split(String regex, int limit)
regex라는 문자를 구분자로, limit는 나눠지는 배열의 길이를 제한한다.
나는 2번째 방식으로 limit 인자를 추가로 전달하여 문제를 해결하려 한다.
또한 limit에 어떤 값이 들어가냐에 따라 3가지로 나뉜다.
-
limit가 0일 경우
단순하게 split(String regex) 메서드를 사용하는 것과 같은 기능을 한다.
split(“ “,0)과 split(“ “)은 동일하다. - limit가 양수일 경우
limit에 지정한 수만큼 배열의 크기가 결정된다.(String[]의 크기)
1 2 3
String str = "a,b,c,,,"; String[] arr = str.split(",", 2); // output: ["a", "b,c,,"]
예를 들어 “a,b,c,,,”라는 문자열이 있으면 [“a”, “b,c,,”]로 저장된다.
- limit가 음수일 경우
limit가 음수일 경우 구분자에 따라 전부 나눠주며 공백 또한 데이터로 보고 배열에 저장된다.
1 2 3
String str = "a,b,c,,,"; String[] arr = str.split(",", -1); // output: ["a", "b", "c", "", "" ,""]
예를들어 “a,b,c,,,”라는 문자열이 있으면 [“a”, “b”, “c”, “”, “”, ““]로 저장된다.
limit에 음수값을 넣어 주어진 문자열에 있는 각 단어사이의 공백문자가 들어간 경우를 해결할 수 있게 된다.
그러면 split() 메서드에 limit를 음수값으로 넣어 주어진 문자열의 각 단어 사이의 공백문자도 포함하여 찾을 수 있다.
1
2
String[] str = s.split(" ", -1); // 주어진 문자열을 공백문자 기준으로 공백문자를 포함하여 배열에 저장한다.
// input:"try hello world", output:["try", " ", "hello", " ", "world"]
공백문자를 기준으로 잘라 배열의 저장하니 공백문자 개수가 -1개임을 확인하였다.
이제 각 단어별로 짝수번째 인덱스인지, 홀수번째 인덱스인지를 확인하여 대소문자로 치환하는 코드를 작성해보자.
1
2
3
4
5
6
for(int i=0; i<str.length; i++) {
for(int j=0; j<str[i].length(); j++) {
if(j%2 == 0) sb.append(String.valueOf(str[i].charAt(j)).toUpperCase());
else sb.append(String.valueOf(str[i].charAt(j)).toLowerCase());
}
}
1
2
3
4
5
6
// input:"try hello world"
try -> TrY
hello -> HeLlO
world -> WoRlD
위와 같이 배열만큼 반복문을 돌며 짝수번째 인덱스는 대문자, 홀수번째 인덱스는 소문자로 치환되도록 작성하였다.
1
2
3
4
5
6
7
8
9
10
11
// input:"try hello world"
i=0, str[i]="try"
// sb="TrY"
i=1, str[i]=" "
// sb="TrY "
i=2, str[i]="hello"
//sb="TrY HeLlO"
i=3, str[i]=" "
//sb="TrY HeLlO "
i=4, str[i]="world"
//sb="TrY HeLlO WoRlD"
또한 입력값과 동일한 공백문자를 포함해야 하는데 현재는 공백값이 -1개로 포함되어 있기에 공백문자도 추가로 포함시켜야 한다.
1
2
3
4
5
6
7
for(int i=0; i<str.length; i++) {
for(int j=0; j<str[i].length(); j++) {
if(j%2 == 0) sb.append(String.valueOf(str[i].charAt(j)).toUpperCase());
else sb.append(String.valueOf(str[i].charAt(j)).toLowerCase());
}
if(i < str.length-1) sb.append(" "); // i가 배열의 길이-1보다 작을 때 공백문자 추가
}
대소문자 치환과 공백문자를 추가로 포함시킨 코드를 작성하였다.
작성코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
solution(s);
}
public static String solution(String s) {
String[] str = s.split(" ", -1);
StringBuilder sb = new StringBuilder();
for(int i=0; i<str.length; i++) {
for(int j=0; j<str[i].length(); j++) {
if(j%2 == 0) sb.append(String.valueOf(str[i].charAt(j)).toUpperCase());
else sb.append(String.valueOf(str[i].charAt(j)).toLowerCase());
}
if(i < str.length-1) sb.append(" ");
}
String answer = sb.toString();
return answer;
}
}
회고
- java.lang.String 클래스에서 split()메서드의 limit 인자를 통해 주어진 문자열의 구분자를 허용하도록 할 수 있음을 알게되었다.
- 문제 설명에서 모든 제약사항을 알려주지 않으니 나름대로 꼼꼼히 제약사항을 파악할줄 알아야 함을 느꼈다.