춤
4836번: 춤
입력은 여러개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 창영이가 춘 춤이 주어진다. 각 춤은 1000스텝을 넘지 않는다. 각 스텝 알파벳 소문자로 이루어져
www.acmicpc.net
문제가 무척 길어서 읽다가 이해를 포기하는 사람이 많아서
제출 횟수가 적지 않을까? 하는 생각이 든다.
문제를 풀기 위해 알고리즘적으로 알아야 하는 개념은 딱히 없었던 것 같고
자바의 문법을 어느정도 다루느냐와 문제를 읽는 끈기가 중요한 것 같다.
규칙
1. dip은 jiggle을 춘 다음이나 다다음, 또는 twirl을 추기 전에 출 수 있다.
2. 모든 춤은 clap stomp clap으로 끝나야 한다.
3. 만약 twirl을 췄다면, hop도 춰야 한다.
4. jiggle로 춤을 시작할 수 없다.
5. 반드시 dip을 춰야 한다.
위 규칙만 성립되게 해 주면 무난히 문제를 풀 수 있다.
문제 풀기에 앞서
잘못된 오류를 알기 위해 Queue를 이용하였고,
1번 규칙에서 잘못된 "dip"의 위치를 알기 위해 List도 이용했다.
Queue<Integer> wrongNumber = new ArrayDeque<>();
String[] strArr = step.split(" ");
List<Integer> wrongDip = new ArrayList<>();
1. dip은 jiggle을 춘 다음이나 다다음, 또는 twirl을 추기 전에 출 수 있다.
//1번 규칙
int strArrLen = strArr.length;
for (int i = 0; i < strArrLen; i++) {
if (!strArr[i].equals("dip")) continue;
boolean case1 = false;
boolean case2 = false;
boolean case3 = false;
if (strArr.length != i + 1) {
if (strArr[i].equals("dip") && strArr[i + 1].equals("twirl")) {
case1 = true;
}
}
if (i >= 1) {
if (strArr[i].equals("dip")) {
if (strArr[i - 1].equals("jiggle")) {
case2 = true;
}
}
}
if (i >= 2) {
if (strArr[i].equals("dip")) {
if (strArr[i - 2].equals("jiggle")) {
case3 = true;
}
}
}
if (!(case1 || case2 || case3)) {
wrongDip.add(i);
strArr[i] = "DIP";
}
}
if (wrongDip.size() != 0) {
wrongNumber.offer(1);
}
step = String.join(" ", strArr);
1번 규칙이 제일 복잡했는데
세 가지의 조건 중에 "또는"이기 때문에 한 가지만 만족하면 된다.
"else if"를 최대한 적게 쓰고 싶어서 위처럼 작성하였다.
계속 문제가 되었던 부분은
순환으로 "dip"이라는 문자열을 찾은 뒤
해당 조건을 통과하고 그다음 조건에서도 걸리게 되어 의도한 "또는"이라는 조건이 되지 않았다.
고민을 하다가 각각의 case마다 boolean을 주어 하나라도 "true"가 된다면 1번을 만족하게끔 했다.
해당 케이스를 검사한 뒤 잘못된 "dip"이 있다면
strArr[i] = "DIP";
위의 코드로
"dip" -> "DIP"으로 바꿔주었다.
1번 이후의 조건을 통과하기 위해서는 배열보다는 String 형태가 더 편할 것 같아서
step = String.join(" ", strArr);
위의 코드로
배열 -> 문자열 형태로 바꿔주었다.
2. 모든 춤은 clap stomp clap으로 끝나야 한다.
String finalStep = " clap stomp clap";
//2번 규칙
if (step.length() >= 16) {
if (!step.substring(step.length() - 16, step.length()).equals(finalStep)) {
wrongNumber.offer(2);
}
} else {
wrongNumber.offer(2);
}
2번 규칙의 "clap stomp clap"의 글자수를 세어
그 글자수가 안되면 잘못된 것이라고 먼저 조건을 주면서 예외처리를 했다.
이후는 substring으로 필요한 만큼 문자를 자른 뒤
위에서 미리 선언해 둔 "finalStep"과 비교를 해주었다.
3. 만약 twirl을 췄다면, hop도 춰야 한다.
//3번 규칙
if (step.contains("twirl")) {
if (!step.contains("hop")) {
wrongNumber.offer(3);
}
}
문제의 말대로 구현한다면 크게 문제 될 것이 없다.
contains를 이용하면 쉽게 구현이 가능했다.
4. jiggle로 춤을 시작할 수 없다.
//4번 규칙
if (step.startsWith("jiggle")) {
wrongNumber.offer(4);
}
startWith()를 이용하면 아주 손쉽게 구현이 가능하다.
() 안의 글자로 시작하는지를 boolean 타입으로 반환한다.
5. 반드시 dip을 춰야 한다.
//5번 규칙
if (!step.contains("dip") && !step.contains("DIP")) {
wrongNumber.offer(5);
}
contains를 이용하여 앞서 바꾼 "dip"과 "DIP"을 포함하는지 안 하는지만
검사하면 된다.
"Dip"은 틀린 답으로 되니 "DIP"으로 반드시 해주어야 한다.
여기서도 많이 헤맸다.
6. 출력 form
if (wrongNumber.size() == 0) {
System.out.println("form ok: " + step);
} else if (wrongNumber.size() == 1) {
System.out.println("form error " + wrongNumber.peek() + ": " + step);
} else if (wrongNumber.size() == 2) {
System.out.println("form errors " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else if (wrongNumber.size() == 3) {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else if (wrongNumber.size() == 4) {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
}
위 방법 말고도
여러 가지 형태로 할 수 있을 듯하다.
출력 form의 경우의 수는 6가지 밖에 되지 않고,
가독성에도 좋으면서 컴퓨터가 연산을 덜할 것이라는 생각을 하여
위처럼 작성했다.
문제의 입력에서 정해진 입력의 개수가 없다고 생각하여 아래와 같은
while문의 형태로 감싸주었다.
bufferedReader에 입력값이 null이 아니라면 while은 계속해서
반복하여 아래의 수행문을 수행하게 될 것이다.
while((step = bufferedReader.readLine()) != null) {
}
제출하면서 맞지 않을지 확신은 들지 않았지만
일단 저대로 작성하고 제출을 해봤다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String step;
String finalStep = " clap stomp clap";
while ((step = bufferedReader.readLine()) != null) {
Queue<Integer> wrongNumber = new ArrayDeque<>();
String[] strArr = step.split(" ");
List<Integer> wrongDip = new ArrayList<>();
//1번 규칙
int strArrLen = strArr.length;
for (int i = 0; i < strArrLen; i++) {
if (!strArr[i].equals("dip")) continue;
boolean case1 = false;
boolean case2 = false;
boolean case3 = false;
if (strArr.length != i + 1) {
if (strArr[i].equals("dip") && strArr[i + 1].equals("twirl")) {
case1 = true;
}
}
if (i >= 1) {
if (strArr[i].equals("dip")) {
if (strArr[i - 1].equals("jiggle")) {
case2 = true;
}
}
}
if (i >= 2) {
if (strArr[i].equals("dip")) {
if (strArr[i - 2].equals("jiggle")) {
case3 = true;
}
}
}
if (!(case1 || case2 || case3)) {
wrongDip.add(i);
strArr[i] = "DIP";
}
}
if (wrongDip.size() != 0) {
wrongNumber.offer(1);
}
step = String.join(" ", strArr);
//2번 규칙
if (step.length() >= 16) {
if (!step.substring(step.length() - 16, step.length()).equals(finalStep)) {
wrongNumber.offer(2);
}
} else {
wrongNumber.offer(2);
}
//3번 규칙
if (step.contains("twirl")) {
if (!step.contains("hop")) {
wrongNumber.offer(3);
}
}
//4번 규칙
if (step.startsWith("jiggle")) {
wrongNumber.offer(4);
}
//5번 규칙
if (!step.contains("dip") && !step.contains("DIP")) {
wrongNumber.offer(5);
}
if (wrongNumber.size() == 0) {
System.out.println("form ok: " + step);
} else if (wrongNumber.size() == 1) {
System.out.println("form error " + wrongNumber.peek() + ": " + step);
} else if (wrongNumber.size() == 2) {
System.out.println("form errors " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else if (wrongNumber.size() == 3) {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else if (wrongNumber.size() == 4) {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
} else {
System.out.println("form errors " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + ", " + wrongNumber.poll() + " and " + wrongNumber.poll() + ": " + step);
}
}
bufferedReader.close();
}
}
'알고리즘 탐구' 카테고리의 다른 글
백준) (자바)1085 직사각형에서 탈출 (0) | 2023.05.04 |
---|---|
백준) (자바)11656 접미사 배열 (0) | 2023.05.03 |
프로그래머스) (자바) 직사각형 별 찍기 (0) | 2023.04.09 |
프로그래머스) (자바)핸드폰 번호 가리기 (0) | 2023.04.07 |
백준) (자바)1935 후위 표기식 2 (0) | 2023.04.04 |