티스토리 뷰

서론
오늘 아침 + 오후 3시까지 하다 하다 안 되서 결국 st-lab님의 티스토리를 참고하고 문제를 겨우 풀 수 있었다.
그렇지만, 같은 실수를 되풀이하면 안 되기에 복기를 하나하나 꼼꼼히 해볼 계획이다.
문제
예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.

예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.
dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.
입력
첫째 줄에 최대 100글자의 단어가 주어진다. 알파벳 소문자와 '-', '='로만 이루어져 있다.
단어는 크로아티아 알파벳으로 이루어져 있다. 문제 설명의 표에 나와있는 알파벳은 변경된 형태로 입력된다.
출력
입력으로 주어진 단어가 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.
풀이(Solution)
1. 입력 처리는 BufferReader 또는 Scanner 이용법 둘 중 하나를 선택하면 될 것 같다.
나는 BufferedReader를 이용해서 입력값을 받았다.
2. 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력해야 한다.
예를 들어,
9개의 단어가 이루어졌다 하더라도, 크로아티아 알파벳이 포함되어 있다면, 한 글자로 계산해야 한다.
"예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다."
크로아티아 알파벳을 입력할 수 없기 때문에 임의의 두 글자(또는 세 글자)의 단어로 해당 알파벳을 표현했다.
알파벳과 문자 '=' '-'로 이루어진 단어 중
{"c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="};
위 목록에 없는 알파벳은 한 글자씩 센다. 라고 문제에 제시되어 있다.
3. for문을 이용해 입력받은 글자 하나하나 살펴봐야 한다.
for(int i = 0; i < input.length(); i++) {
int ch = input.charAt(i);
크로아티아 알파벳은 'c, d, l, n, s, z'로 시작하는 글자 뿐이기 때문에, 이들을 분기의 기준으로 삼으면 된다.
if(ch == 'c') {
...
}
else if(ch == 'd') {
...
4. '크로아티아 알파벳'은 두 글자 또는 세 글자로 표현되기 때문에, i번째 글자와 i+1번째 글자 또는 i+2번째 글자와 비교해야 한다.
이때, i의 범위를 조건문으로 제한해야 한다. 제한하지 않을 시 StringIndexOutOfBounds에러가 발생한다.
if(ch == 'c') {
if(i < input.length() - 1) {
...
}
}
5. 'c' 다음 글자가 '-'이거나 '='라면, 이는 크로아티아 알파벳에 해당한다. 조건문으로 분기해줘야 한다.
조건문이 참일 경우. i++ 연산을 해줌으로써 다음 회차를 생략하도록 만들어줘야 한다.
단, 'dz='의 경우 세 글자 이므로 i++ 대신 i += 2 연산을 해주어야 한다.
마찬가지로, 'dz='의 경우, i번째 글자와 i+2번째 글자를 비교해야하기 때문에, i는 마지막에서 두 번째 글자보다 앞 순서에 있어야 한다.
따라서, 조건식을 i < input.length() - 2로 작성해야 한다.
나머지 글자도 같은 원리로 작성해준다.
if(ch == 'c') {
if(i < input.length() - 1) {
if(input.charAt(i+1) == '=' || input.charAt(i+1) == '-')
i++;
}
}
else if(ch == 'd') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == '-')
i++;
else if (input.charAt(i + 1) == 'z') {
if(i < input.length() - 2) {
if (input.charAt(i + 2) == '=')
i += 2;
}
}
}
}
6. for문의 마지막에는 글자수를 저장하는 변수 cnt에 대해 cnt++ 연산을 해준다.
시행착오(Trial&Error)

51761795 - 틀렸습니다
contains메서드를 사용해서, 특정 단어들을 포함할 경우를 따져서 문제를 풀어보려고 시도했었다.
하지만, 특정 '크로아티아 알파벳'이 중복되는 경우를 조건문으로 분기하지 못해서 결국 포기했다.
또한, 알파벳이 하나만 쓰이는 것도 아닌데, 여러 알바펫이 쓰일경우를 어떻게 처리할지... 고민하다가 포기했다.
그리고, 글자수를 0부터 세어나가는 게 아니라, 입력받은 단어의 글자 수(length())로 초기화를 해놓고,
빼는 식으로 작성했더니 더욱 복잡해졌다.
51762163 - 컴파일 에러
Main.java:7: error: cannot find symbol
int cnt = input.length();
^
symbol: variable input
location: class Main
input을 초기화하지 않아 '컴파일 에러'가 발생했다. 왜 안 했지..?🤔
51762182 - 틀렸습니다
"dz="는 세 글자인데, 내가 똑같이 cnt--;처리를 해줘서 틀렸었구나 생각하고
위의 경우에만 cnt -= 2로 처리했었다. 하지만 틀렸쥬~? 🙅♂️
51772235 - 컴파일 에러
Main.java:12: error: variable cnt might not have been initialized
cnt++;
^
int cnt; <- 이게 왜 초기화를 안 한거지?
iv는 자동초기화 아닌가? 생각하다가
지금 쓰면서 생각난건데, main메서드 내에서 선언한 변수니까 cnt는 지역변수(lv)이다.
무슨 말이냐면, 지역변수는 반드시 '수동 초기화'해주어야 한다는 말씀... 배워놓고 써먹지 못 하면 무슨 소용일까?
class Main {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
br.close();
int cnt; // <- 현행범 체포
그리고 int cnt = 0;으로 수동 초기화 해주었다.
혹시 미래의 까먹었을 나를 위해 좌표를 남겨두자. => 좌표
51772261 - 런타임 에러 (StringIndexOutOfBounds)
풀이(Solution)의 4.에서 언급한 내용 때문에 실행 중 에러가 발생했다.
i의 범위를 마지막 요소 바로 앞 인덱스
또는 크로아티아 알파벳이 세 글자("dz=")인 경우
마지막 요소 앞에서 두 글자까지로 범위를 제한해야 한다.
하지만 나는 전~혀 조건문을 작성하지 않았다.
51772653 - 런타임 에러 (StringIndexOutOfBounds)
이 단계에서 하나 바로잡은 것은,
'크로아티아 알파벳'일 경우, 글자수를 깎아내려가는 방법을 사용한 것이 잘못됐다는 점이다.
if(input.charAt(i+1) == '-' && i < input.length() - 1)
cnt--;
이와 같이 문제에 접근하는 게 아니라,
조건식이 참일 경우, i(for문의 index)에 대해 i++ 또는 i += 2 연산을 해서
다음 글자 차례를 건너 뛰는 방법을 택하는 방식으로 문제를 풀어야 한다.
if(input.charAt(i+1) == '-' && i < input.length() - 1)
i++;
고백하자면, 사실 이 단계에서 도저히 모르겠어서 아까 말했던 st-lab님의 티스토리를 참고했다. 🧎
51773070 - 컴파일 에러
for문 선언문 뒤에 중괄호 시작({)을 빼먹어서 컴파일 에러가 발생했다.(실수)
51773098 - 컴파일 에러
문자열의 특정 글자의 인덱스를 저장한 변수 ch를 초기화할 때 타입을 빼먹어서 컴파일 에러가 발생했다(실수2222)
51773115 - 런타임 에러 (StringIndexOutOfBounds)
cnt 대신 i(인덱스)를 건드려야 한다는 것까지 알았지만 여전히 에러가 발생했다.
if(input.charAt(i+1) == '-' && i < input.length() - 1)
i++;
조건식 두 개를 작성하고 위 모두 참일 경우를 표현하기 위해 논리 연산자 &&를 사용했다.
그런데, 앞의 조건식은 i의 범위를 제한하지 않은 상태이지 않은가.
근데 이미 i+1이라고 적었으니 i가 마지막 요소일 경우, 문자열 인덱스 범위 밖으로 벗어난 셈이 된다.
따라서, i의 범위를 먼저 제한하기 위해 뒤에 작성한 조건문을 앞에다 써주었다.
if(ch == 'c') {
if(i < input.length() - 1) {
if(input.charAt(i+1) == '=' || input.charAt(i+1) == '-')
i++;
}
}
코드
import java.io.*;
class Main {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
br.close();
int cnt = 0;
for(int i = 0; i < input.length(); i++) {
int ch = input.charAt(i);
if(ch == 'c') {
if(i < input.length() - 1) {
if(input.charAt(i+1) == '=' || input.charAt(i+1) == '-')
i++;
}
}
else if(ch == 'd') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == '-')
i++;
else if (input.charAt(i + 1) == 'z') {
if(i < input.length() - 2) {
if (input.charAt(i + 2) == '=')
i += 2;
}
}
}
}
else if(ch == 'l') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == 'j')
i++;
}
}
else if(ch == 'n') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == 'j')
i++;
}
}
else if(ch == 's') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == '=')
i++;
}
}
else if(ch == 'z') {
if(i < input.length() - 1) {
if (input.charAt(i + 1) == '=')
i++;
}
}
cnt++;
}
System.out.println(cnt);
} catch(IOException e) {}
}
}
참고
'알고리즘 > 문제풀이 - 백준' 카테고리의 다른 글
| [백준 2750번] 수 정렬하기(JAVA) (1) | 2022.11.18 |
|---|---|
| [백준 1361번] 그룹 단어 체커(JAVA) (2) | 2022.11.17 |
| [백준 5622번] 다이얼(JAVA) (0) | 2022.11.15 |
| [백준 2908번] 상수(JAVA) (0) | 2022.11.14 |
| [백준 1152번] 단어의 개수(JAVA) (0) | 2022.11.13 |
