크로아티아 알파벳 8개를 키보드 입력키에 맞게 변환한 알파벳들이 있는데
크로아티아 알파벳+영어 소문자의 조합으로 이루어진 단어를 입력받고
그게 몇개의 크로아티아 알파벳으로 이루어졌는지를 알아내어 출력하는 문제.
헷갈리지 말 것이 표에 있는 크로아티아 알파벳들 말고 그냥 영어 소문자 (a,d,k 등등)도 세는게 맞음!
이 요상하게 생긴 크로아티아 알파벳으로 이루어진 문자열을 하나하나 문자 배열로 만들어 비교하는 식은 통하지 않겠다
왜냐하면 한 문자씩으로 이루어진게 아니라 두 문자열 이상씩으로 이루어져있기 때문
단순하게 떠오른 방법은 어차피 이 알파벳들이 8개로 얼마 되지 않으니까
각각의 알파벳들이 입력받은 문자열에 포함되어 있는지 확인한뒤 소거하는 일을 반복하고
(같은 문자가 여러개인 경우를 생각해서 while문으로 확인해야할듯..)
마지막 크로아티아 알파벳까지 확인했다면 남은건 공백 또는 a, d, k와같은 평범하게 생긴 한개의 문자들일테니
마지막에서는 이 남아있는 문자들이 몇개인지 세주면 될거라 생각했다.
우선 이렇게 풀려면 문자열에 특정 문자열이 포함되어 있는지 여부를 알려주는 함수, 해당 문자열을 소거해주는 함수
이렇게를 알아야하기 때문에 구글링해보자..아마 있을것이다 기억은 잘 안나지만
포함여부는 contains()함수를 쓰면 될듯하고
특정 크로아티아 알파벳을 문자열에서 제거하기 위해서는 replace((크로아티아), "")를 사용하면 될 듯 하다.
엇 그런데..이러면 replace로 알파벳 여러개가 한번에 없어질수도 있겠다..그러면 제대로 셀 수가 없다
다행히도 마침 가장 처음으로 등장한 알파벳만을 제거해주는 replaceFirst()라는 함수가 있다!
이제 이를 이용하여 코드를 짜보도록 하자..
오늘은 시간이 늦어서 여기까지 해결방법만 간략히 생각해두고 내일 코딩해야겠다 zz
.
.
그렇게 내일 한다고 해놓고 이제야 올린다..
다음과 같이 코드를 짰다. 이게 최선인가 싶지만 우선 생각나는 방식은 이러했다.
package Level6;
import java.io.*;
public class croatiaAlp {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String input = br.readLine();
int count = 0;
//boolean isCroaLeft = true; //크로아티아 알파벳이 남아있는지 확인
//false, 즉 더이상 남아있는 크로아티아 알파벳이 없을떄까지 반복
for (int i=0; i<input.length(); i++) { //그냥 문자열길이만큼 반복하기로 함
if (input.contains("c=")) {
count++;
input = input.replaceFirst("c=", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("c-")){
count++;
input = input.replaceFirst("c-", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("dz=")){
count++;
input = input.replaceFirst("dz=", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거;
}else if(input.contains("d-")){
count++;
input = input.replaceFirst("d-", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("lj")){
count++;
input = input.replaceFirst("lj", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("nj")){
count++;
input = input.replaceFirst("nj", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("s=")){
count++;
input = input.replaceFirst("s=", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}else if(input.contains("z=")){
count++;
input = input.replaceFirst("z=", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
}
}
//input.replaceAll(" ", ""); //공백 -> 빈 문자열
//위와같은 방법을 사용하면 공백이 제거되지 않았다..
//input.replaceAll("\\s+", ""); //따라서 정규식을 사용했다
//이것도 안된다..아 나 바본가??
input = input.replace(" ", "");
count += input.length(); //남은 문자열 갯수를 더한다
bw.write(Integer.toString(count));
bw.flush();
bw.close();
}
}
//설계잘못함..isCroaLeft를통해 문자열에 남아있는 크로아티아가 단 하나라도 있는지 확인하려 했던건데
// 이대로라면 앞서 true로 값이 들어가도 그 다음의 크로아티아가 포함되어있지 않다면 결국 false가 될 것 아니야..->for문으로바꿈
////isEmpty는 공백만 있는경우 false, isBlank는 공백만 있는경우 true 빈문자열의 경우 둘다 true 하다가 헷갈려서 찾아봄
//왜 ddz=z=로 했을때 결과가 2로 나오지? 아 헐...ddz=z=에서 처음 dz=가 빠지고 나면 앞뒤가 붙어서 dz=가 만들어져서 그런거엿슴
//해당 크로아티아 알파벳을 빈 문자열로 대체하는 대신에 공백으로 대체한다음에..input에서 공백을 제외한 문자들을 세야할듯
//replaceFirst에서 대체할 문자를 "\\s"로 하니까 공백이 들어가는게 아니라 문자 s가 들어간다..이게아닌가?
주석이 구구절절 지저분하게 달려있는것에서 볼 수 있듯이 몇번 시행착오 끝에 성공시키게 되었다..
왜 그랬냐면
1. 크로아티아 알파벳이 남아있는지의 여부를 파악하는 방식을 잘못 설계함
-> boolean형 변수 isCroaLeft를 두고 각각의 if문의 끝에다가 if조건에서 확인했던 크로아티아 알파벳이
input 문자열에 아직 남아있는지를 contains 함수를 통해 한번 더 확인하고 있으면 true/없으면 false값이 각각 들어가게 해놨었는데
완전 바보였다 이러면 앞에서 남아있다고 true값이 들어갔었어도 뒤에서 false로 되어버리면 소용없잔아..
원래 저 if-else문을 while(isCroaLeft == true)로 감싸놨었는데, 다른 방법을 알아봐야 했다.
그냥 while문을 포기하고 for문으로 문자열 길이만큼 반복되도록 바꾸었는데,
원래 코드 의도대로 "크로아티아 알파벳이 더이상 문자열에 포함되어있지 않을 때까지 반복"되도록 다시 코드를 작성해봤다..
//false, 즉 더이상 남아있는 크로아티아 알파벳이 없을떄까지 반복
while (isCroaLeft == true) { //그냥 문자열길이만큼 반복하기로 함
isCroaLeft = false;
if (input.contains("c=")) {
count++;
input = input.replaceFirst("c=", " "); //해당 크로아티아 알파벳을 빈문자열로 대체해 소거
if(input.contains("c=")) { isCroaLeft = true; }
}
if(input.contains("c-")){
count++;
input = input.replaceFirst("c-", " ");
if(input.contains("c-")) { isCroaLeft = true; }
}
if(input.contains("dz=")){
count++;
input = input.replaceFirst("dz=", " ");
if(input.contains("dz=")) { isCroaLeft = true; }
}
if(input.contains("d-")){
count++;
input = input.replaceFirst("d-", " ");
if(input.contains("d-")) { isCroaLeft = true; }
}
if(input.contains("lj")){
count++;
input = input.replaceFirst("lj", " ");
if(input.contains("lj")) { isCroaLeft = true; }
}
if(input.contains("nj")){
count++;
input = input.replaceFirst("nj", " ");
if(input.contains("nj")) { isCroaLeft = true; }
}
if(input.contains("s=")){
count++;
input = input.replaceFirst("s=", " ");
if(input.contains("s=")) { isCroaLeft = true; }
}
if(input.contains("z=")){
count++;
input = input.replaceFirst("z=", " ");
if(input.contains("z=")) { isCroaLeft = true; }
}
}
if-else if문으로 작성해놔서 잘 되지 않다가 if문으로 싹 바꾸고 제대로 실행되었다.
이렇게하면 1~8번째의 크로아티아 알파벳이 남아있는지를 확인하고 하나라도 남아있다면 반복되기때문에
while문이 끝나면 크로아티아 알파벳이 아닌 문자만이 남게 된다..
2. replace함수를 사용해놓고는 리턴값을 방치(?)함
왜 자꾸 크로아티아 알파벳에서 공백으로 대체된 값이 replace, replaceAll 함수를 써도 빈 문자열로 대체되지 않는건지 애먹었다.
" "라고 해서 안되는건가 해서 정규식도 써보고 별거 다해놨는데도 안돼서 왜그러나 싶었는데
input.replaceAll(" ", "");
여기서 끝내버려서 그런거였다..
input에다가 결괏값을 새로 할당해주니 문제 해결 ㅎ
아무튼 전체적인 방식을 다시 정리하자면
input값에서 크로아티아 알파벳이 더이상 없을때까지 while문으로 반복해 크로아티아 알파벳들을 공백으로 바꾸고
(공백대신 빈 문자열 ""로 해놨었는데, 이렇게 하면 ddz=z=와같은 두번째 예제에서 확인할 수 있듯이 처음의 dz=가 지워지고 나서
앞의 d와 뒤의 z=가 붙어버려서 dz=가 총 두개 있는것으로 오해가 생기더라..!!)
while문이 끝나면 input에 남아있는 문자열들의 개수와 아까 if문에서 카운트한 크로아티아 알파벳들의 개수를 합해서
답을 구할 수 있다.
다른 사람들은 어떻게 풀었나 궁금한데 몸이 좀 안좋아서
다음 시간에 백준에서 다른 코드들도 살펴보고 복습, 정리하는 시간을 가지기로 마음먹고 글을 마친다 ~.~
'알고리즘 > 문자열' 카테고리의 다른 글
[백준알고리즘] 문자열/그리디 - 1541번 잃어버린 괄호 문제 (1) | 2023.05.16 |
---|---|
[백준알고리즘] 문자열 문제 1316번 - 그룹 단어 체커 (0) | 2022.08.24 |
[백준알고리즘] 문자열 - 5622번 다이얼 문제 (0) | 2022.07.26 |
[백준알고리즘] 문자열 - 2908 상수 문제 (0) | 2022.07.26 |
[백준알고리즘] 문자열 - 1152번 단어의 개수 문제 (0) | 2022.07.22 |