본문 바로가기
코딩테스트/백준

[백준 2941] 크로아티아 알파벳 - Java (+23.09.05)

by naahy 2022. 10. 21.

https://www.acmicpc.net/problem/2941

 

2941번: 크로아티아 알파벳

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다. 크로아티아 알파벳 변경 č c= ć c- dž dz= đ d- lj lj nj nj š s= ž z=

www.acmicpc.net

 

 



금방 풀 수 있을 거라 생각했는데 자잘한 문제에 막혀서 몇 시간을 고생했다.
처음엔 [ic]System.in.read()[/ic]로 한 글자씩 입력 받도록 코드를 작성했는데,
그렇게 하니 \r, \n이 들어오는 경우도 생각해야 해서 코드가 난잡해져 [ic]BufferedReader[/ic]를 이용해 풀어보려 했다.
그렇게 이클립스로 코드를 작성하고 테스트 해보니 잘 돌아가는 것 같아서 백준에 제출했더니 오답...


결국 구글링을 통해 다른 사람들의 코드를 본 후 풀었다.

 

✨ 참고

https://st-lab.tistory.com/68

 

[백준] 2941번 : 크로아티아 알파벳 - JAVA [자바]

https://www.acmicpc.net/problem/2941 2941번: 크로아티아 알파벳 문제 예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다. 크

st-lab.tistory.com


풀이(오답) (+ 23.09.05)

  • BufferedReader로 한 줄 입력 받기
  • 문자열 길이만큼 for문을 반복해서 한 글자씩 확인 후 단어 개수 증감 여부 체크
  • 표에 나와있는 알파벳으로 시작하는 경우 for문 순서 건너뛰기

사실 지금도 어디가 틀렸는지 잘 모르겠다.

꾸준히 문제 풀어보고 나중에 다시 확인했을 땐 깨닫지 않을까 싶어 일단 코드를 올려본다.

이유 알아냄

case 코드 내 else if문에서 다음 문자가 case 변수와 같을 경우만 처리했기 때문이었음

표에 나와있는 문자의 첫 알파벳인 경우도 다 처리해야 한다.

  • d로 시작하는 경우 다음 문자가 z인 경우는 따로 처리 해야함.
    • StringIndexOutOfBounds 오류가 발생할 수 있기 때문에 문자열이 dz로 끝나는 경우 인덱스의 크기를 더 키우면 안 됨

 

오류난 코드

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CroatiaAlphabet2941 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String word = br.readLine();
		char alphabet;
		
		int count = 0;
		
		for (int i=0; i<word.length(); i++) {
			alphabet = word.charAt(i);
			
			if (i == word.length()-1) {
				count++;
				break;
			}
			
			switch(alphabet) {
			case 'c':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '=' || alphabet == '-')
					count++;
				else if (alphabet == 'c') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			case 'd':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '-')
					count++;
				else if (alphabet == 'd') {
					count++;
					i--;
				}
				else if (alphabet == 'z') {
					i++;
					alphabet = word.charAt(i);
					
					if (alphabet == '=')
						count++;
					else if (alphabet == 'd') {
						count += 2;
						i--;
					}
					else
						count += 3;
				}
				else
					count += 2;
				
				break;
				
			case 'l': case 'n':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == 'j')
					count++;
				else if (alphabet == 'l' || alphabet == 'n') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			case 's': case 'z':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '=')
					count++;
				else if (alphabet == 's' || alphabet == 'z') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			default:
				count++;
			}
		}
		
		System.out.println(count);
	}

}

 

수정한 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String word = br.readLine();
		char alphabet;
		
		int count = 0;
		
		for (int i=0; i<word.length(); i++) {
			alphabet = word.charAt(i);
			
			if (i == word.length()-1) {
				count++;
				break;
			}
			
			switch(alphabet) {
			case 'c':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '=' || alphabet == '-')
					count++;
				else if (alphabet == 'c' || alphabet == 'd' || alphabet == 'n'
						 || alphabet == 'l' || alphabet == 's' || alphabet == 'z') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			case 'd':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '-')
					count++;
				else if (alphabet == 'c' || alphabet == 'd' || alphabet == 'n'
						 || alphabet == 'l' || alphabet == 's') {
					count++;
					i--;
				}
				else if (alphabet == 'z') {	// 다음 문자 z인 경우 따로 처리
					if (i == word.length()-1) {	// StringIndexOutOfBounds 방지
						count += 2;
						break;
					}
					i++;
					alphabet = word.charAt(i);
					
					if (alphabet == '=')
						count++;
					else if (alphabet == 'c' || alphabet == 'd' || alphabet == 'n'
							 || alphabet == 'l' || alphabet == 's' || alphabet == 'z') {
						count += 2;
						i--;
					}
					else
						count += 3;
				}
				else
					count += 2;
				
				break;
				
			case 'l': case 'n':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == 'j')
					count++;
				else if (alphabet == 'c' || alphabet == 'd' || alphabet == 'n'
						 || alphabet == 'l' || alphabet == 's' || alphabet == 'z') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			case 's': case 'z':
				i++;
				alphabet = word.charAt(i);
				
				if (alphabet == '=')
					count++;
				else if (alphabet == 'c' || alphabet == 'd' || alphabet == 'n'
						 || alphabet == 'l' || alphabet == 's' || alphabet == 'z') {
					count++;
					i--;
				}
				else
					count += 2;
				
				break;
				
			default:
				count++;
			}
		}
		
		System.out.println(count);
	}

}

 


 

풀이(정답)

위 풀이와 방식은 동일하지만 차이점이 있다.

위에선 표에 나와있는 알파벳으로 시작하는 경우 무조건 순서를 건너뛰었지만, 아래의 정답 코드에선 먼저 그 다음 문자를 확인한 후 건너뛸지 말지 정한다.

이렇게 하면 코드도 훨씬 더 간결하게 짤 수 있다.

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CroatiaAlphabet2941 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String word = br.readLine();
		char alphabet;
		
		int count = 0;
		
		for (int i=0; i<word.length(); i++) {
			alphabet = word.charAt(i);
			
            // StringIndexOutOfBoundsException 방지
			if (i == word.length()-1) {
				count++;
				break;
			}
			
			switch(alphabet) {
			case 'c':
				alphabet = word.charAt(i + 1);
				
				if (alphabet == '=' || alphabet == '-')
					i++;
				
				count++;
				break;
				
			case 'd':
				alphabet = word.charAt(i + 1);
				
				if (alphabet == '-')
					i++;
				else if (alphabet == 'z' && i<word.length()-2) {	// StringIndexOutOfBoundsException 방지
					alphabet = word.charAt(i+2);
					
					if (alphabet == '=')
						i += 2;
				}
				
				count++;
				break;
				
			case 'l': case 'n':
				alphabet = word.charAt(i + 1);
				
				if (alphabet == 'j')
					i++;
				
				count++;
				break;
				
			case 's': case 'z':
				alphabet = word.charAt(i + 1);
				
				if (alphabet == '=')
					i++;
				
				count++;
				break;
				
			default:
				count++;
			}
		}
		
		System.out.println(count);
	}

}

 


 

(+ 23.09.05)

풀이2

위의 풀이들보다 시간은 오래 걸렸지만 다른 방법이니까 기록해본다.

  • 크로아티아 알파벳들이 요소로 들어가있는 리스트 생성
  • 입력받은 단어를 앞부터 2글자 혹은 3글자씩 자른 후 해당 부분이 리스트에 포함 되어있는지 확인
    • 2글자로 자른 단어가 리스트에 포함되어 있지 않으면 뒤의 1글자를 더 포함해 총 3글자 단어로 다시 확인
    • 2글자 단어가 포함된 경우 인덱스+1, 3글자 단어가 포함된 경우 인덱스+2
    • StringIndexOutOfBounds 오류가 발생할 수 있으므로 단어 자르기 전에 확인

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class Main {

	public static void main(String[] args) throws IOException {
		List<String> croatia = Arrays.asList("c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=");
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String word = br.readLine();
		
		int count = 0;
		
		for (int i=0; i<word.length(); i++) {
			if (i < word.length()-1 && croatia.contains(word.substring(i, i+2))) {
				count++;
				i++;
				continue;
			}
			else if (i < word.length()-2 && croatia.contains(word.substring(i, i+3))) {
				count++;
				i += 2;
				continue;
			}
			count++;
		}
		
		System.out.println(count);
	}

}

댓글