C/BaekJoon

[C] 백준 8958 - OX퀴즈 | BaekJoon

sngsp 2023. 7. 28. 02:44

문제

"OOXXOXXOOO"와 같은 OX퀴즈의 결과가 있다. O는 문제를 맞은 것이고, X는 문제를 틀린 것이다. 문제를 맞은 경우 그 문제의 점수는 그 문제까지 연속된 O의 개수가 된다. 예를 들어, 10번 문제의 점수는 3이 된다.

"OOXXOXXOOO"의 점수는 1+2+0+0+1+0+0+1+2+3 = 10점이다.

OX퀴즈의 결과가 주어졌을 때, 점수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 길이가 0보다 크고 80보다 작은 문자열이 주어진다. 문자열은 O와 X만으로 이루어져 있다.

출력

각 테스트 케이스마다 점수를 출력한다.

예제 입력 1

5
OOXXOXXOOO
OOXXOOXXOO
OXOXOXOXOXOXOX
OOOOOOOOOO
OOOOXOOOOXOOOOX

예제 출력 2

10
9
7
55
30

예상 풀이방법

문자 배열 선언 후 해당 배열마다 O인지 X인지 판독하는 for문을 기점으로 if 조건문을 달아 O일 경우와 X일 경우를 구별해가며 풀어낸다.

1차 코드

#include <stdio.h>
#include <string.h>

int main() {
    // 테스트 케이스의 갯수를 n이라고 가정하여 입력받기
    int n;
    scanf("%d", &n);

    // 테스트 케이스의 갯수만큼의 반복문을 사용하여 OX를 문자열로 입력받기
    for (int i = 0; i < n; i++) {
        // 0보다 크고 80보다 작은 문자열 생성
        char arr[80];
        scanf("%s", arr);
        // 입력받은 문자열의 길이 strlen(a)만큼을 반복문으로 사용하고 if문을 사용하여 각 배열에 저장된 O or X를 판독하기
        for (int j = 0; j < strlen(arr); j++) {
            int score = 0;
            // 가장 먼저 선언되어야 할 X일 경우 아무것도 하지 않고 넘어간다.
            if (arr[j] == 'X') {
                continue;
            }
            // 두 번째로 선언되어야 할 if문은 'O'일 경우 점수를 증가시킬 수 있어야 한다.
            else if (arr[j] == 'O') {
                // if문 내에서 score를 선언할 경우 매 if문마다 초기화되므로 상위 개념인 for문에 int score를 선언하고 score++로 1 증가시킨다.
                score++;
                // j를 기준으로 이전 문자열이 O일 경우 1씩 추가 점수를 부여해야하기에 for문을 사용하여 이전 문자열을 찾아내지만 X를 발견하면 중단하는 반복문을 작성한다.

                // j - 1이 0일 경우까지 전부 찾아내야하므로 int k를 j - 1로 지칭하여 점점 감소하는 반복문을 작성한다.
                for (int k = j - 1; k >= 0; k--) {
                    int sum = 0;
                    // 가장 먼저 들어가야하는 경우는 X를 찾아낼 경우 for문을 그만 돌리고 나오는 것이다.
                    if (arr[k] == 'X') {
                        break;
                    }
                    // 그 다음으로는 O일 경우 추가 점수를 주어야하는데 이 추가 점수가 몇 점일지 모르기 때문에 int sum이라는 함수를 추가하여 거기에 더해놓고
                    // for문이 끝날 때 score에 합산하는 방식을 사용한다. 그러면 만약 OOOO(마지막 O가 j라면)
                    /*

                    1 1 1
                    1 1
                    1

                    + 맨 처음 j가 도는 함수에서 score++로 1점이 더해지기 때문에
                    4 + 3 + 2 + 1점이 완성되는 방식으로 계산할 수 있게 된다.
                    */
                    else if (arr[k] == 'O') {
                        // int sum은 if마다 초기화되는게 아니라 해당 for문 내에서는 값이 유지되어야하기에 for문 바로 아래에 선언한다.
                        // 그리고 O일 경우마다 sum에 ++로 더해주고 그 값을 for문이 끝날 때, score에 합산한다.
                        sum++;
                    }

                    score += sum;

                }

            }
            // 마지막으로 O or X가 아닐 경우 전부 예외처리를 하고 즉시 프로그램을 종료시킬 수 있도록 변수를 차단한다.
            else
                return 0;
            // 모든 연산이 끝난 후 score값을 프린트한다.
            printf("%d\n", score);
        }

    }
}

1차 결과

5
OOXXOXXOOO
1
2
1
1
2
3
OOXXOOXXOO
1
2
1
2
1
2
OXOXOXOXOXOXOX
1
1
1
1
1
1
1
OOOOOOOOOO
1
2
3
4
5
6
7
8
9
10
OOOOXOOOOXOOOOX
1
2
3
4
1
2
3
4
1
2
3
4

1차 진단

OX에 대한 점수는 잘 계산되었으나 각 O의 점수가 따로따로 출력되는 문제가 있다.
여기서 두 가지의 문제점을 짐작할 수 있었다.

  1. sum을 사용하여 점수를 합산하는 과정에서 문제가 있을 가능성
  2. printf("%d", score); 명령어가 잘못된 부분에 들어가있어서 반복적으로 출력했을 가능성

1차 해결 노력

우선 반복출력을 없애야 합산의 문제점도 추려내기 쉬워질 것 같았다.
그래서 1번이 아니라 2번 문제점부터 해결해보기로 했다.

  1. printf 명령어의 위치를 옮기기
    printf 명령어를 for문 밖으로 옮겨보니 score가 정의된 위치 밖이었다.
    그렇기에 해당 int score = 0;을 int j 반복문이 아닌 int i 반복문에 지정해놓았다.
    어차피 매 테스트 케이스마다 초기화되는 곳이니 상관없었다.

2차 코드

#include <stdio.h>
#include <string.h>

int main() {
    // 테스트 케이스의 갯수를 n이라고 가정하여 입력받기
    int n;
    scanf("%d", &n);

    // 테스트 케이스의 갯수만큼의 반복문을 사용하여 OX를 문자열로 입력받기
    for (int i = 0; i < n; i++) {
        int score = 0;
        // 0보다 크고 80보다 작은 문자열 생성
        char arr[80];
        scanf("%s", arr);
        // 입력받은 문자열의 길이 strlen(a)만큼을 반복문으로 사용하고 if문을 사용하여 각 배열에 저장된 O or X를 판독하기
        for (int j = 0; j < strlen(arr); j++) {
            // 가장 먼저 선언되어야 할 X일 경우 아무것도 하지 않고 넘어간다.
            if (arr[j] == 'X') {
                continue;
            }
            // 두 번째로 선언되어야 할 if문은 'O'일 경우 점수를 증가시킬 수 있어야 한다.
            else if (arr[j] == 'O') {
                // if문 내에서 score를 선언할 경우 매 if문마다 초기화되므로 상위 개념인 for문에 int score를 선언하고 score++로 1 증가시킨다.
                score++;
                // j를 기준으로 이전 문자열이 O일 경우 1씩 추가 점수를 부여해야하기에 for문을 사용하여 이전 문자열을 찾아내지만 X를 발견하면 중단하는 반복문을 작성한다.

                // j - 1이 0일 경우까지 전부 찾아내야하므로 int k를 j - 1로 지칭하여 점점 감소하는 반복문을 작성한다.
                for (int k = j - 1; k >= 0; k--) {
                    int sum = 0;
                    // 가장 먼저 들어가야하는 경우는 X를 찾아낼 경우 for문을 그만 돌리고 나오는 것이다.
                    if (arr[k] == 'X') {
                        break;
                    }
                    // 그 다음으로는 O일 경우 추가 점수를 주어야하는데 이 추가 점수가 몇 점일지 모르기 때문에 int sum이라는 함수를 추가하여 거기에 더해놓고
                    // for문이 끝날 때 score에 합산하는 방식을 사용한다. 그러면 만약 OOOO(마지막 O가 j라면)
                    /*

                    1 1 1
                    1 1
                    1

                    + 맨 처음 j가 도는 함수에서 score++로 1점이 더해지기 때문에
                    4 + 3 + 2 + 1점이 완성되는 방식으로 계산할 수 있게 된다.
                    */
                    else if (arr[k] == 'O') {
                        // int sum은 if마다 초기화되는게 아니라 해당 for문 내에서는 값이 유지되어야하기에 for문 바로 아래에 선언한다.
                        // 그리고 O일 경우마다 sum에 ++로 더해주고 그 값을 for문이 끝날 때, score에 합산한다.
                        sum++;
                    }

                    score += sum; // 주의

                }

            }
            // 마지막으로 O or X가 아닐 경우 전부 예외처리를 하고 즉시 프로그램을 종료시킬 수 있도록 변수를 차단한다.
            else
                return 0;
        }
        // 모든 연산이 끝난 후 score값을 프린트한다.
        printf("%d\n", score);

    }
}

2차 결과

5
OOXXOXXOOO
10
OOXXOOXXOO
9
OXOXOXOXOXOXOX
7
OOOOOOOOOO
55
OOOOXOOOOXOOOOX
30

미흡했던 점

  1. int score = 0;의 선언과 pritnf("%d", score); 명령어를 테스트 케이스의 갯수마다 반복해야하는데 (int i 반복문마다 해야하는데)
    문자열의 길이만큼 반복되는 반복문(int j 반복문)에 넣어놓으니 당연히 X일 경우 실행중지하고 O일 경우 해당 점수를 계산하여
    반복적으로 출력했던 것이다.

개선 방안

  1. 각 반복문 및 모든 명령어, 함수 사용에 있어서 어느 부분에서 정의되어야하는지 위치를 정확히 알고 사용한다.

최종 코드

#include <stdio.h>
#include <string.h>

int main() {

    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i++) {
        int score = 0;
        char arr[80];
        scanf("%s", arr);
        for (int j = 0; j < strlen(arr); j++) {
            if (arr[j] == 'X') {
                continue;
            }
            else if (arr[j] == 'O') {
                score++;
                for (int k = j - 1; k >= 0; k--) {
                    int sum = 0;
                    if (arr[k] == 'X') {
                        break;
                    }
                    else if (arr[k] == 'O') {
                        sum++;
                    }

                    score += sum;

                }

            }
            else
                return 0;
        }
        printf("%d\n", score);
    }
}

백준 실행 결과