본문 바로가기
개발자 전향 프로젝트

[백준] [알고리즘 8958번: OX퀴즈] JAVA

by 샘오리 2022. 7. 10.

OX퀴즈 

한국어   
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 162910 80771 67013 49.792%

문제

"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

예제 출력 1 복사

10
9
7
55
30

풀이

============================================================================================

 

이 문제는 기본적으로 배열, 문자열 분리,  중첩 덧셈을 할줄 알아야 풀 수 있는 문제이다. 물론 배열을 사용하지 않고도 풀 수 있는 방법이 있다. 바로 GetBytes라는 함수를 이용한 것인데 일단은 배열을 사용하여 풀이를 진행하겠다.

스캐너보다는 속도가 빠른 BufferedReader를 사용하여 시작!

BufferedReader 일단 소환해서 값 입력받을 수 있게 해주고

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

그 입력받은 값을 정수로 변환해서 N이라는 변수에 저장한다. (왜 변환해야 하는지는 이전 글 참조)

int N = Integer.parseInt(br.readLine());

이제 입력 받은 값들을 배열에 담기 위해 빈 배열을 만들어준다. 대신 입력받은 값이 배열의 크기가 돼야 한다. 어떻게?

String arr[] = new String[N];

요렇게.

 

그리고 입력할 한 뭉텅이의 값 (예: "OOXXOXXOOO")을 빈 배열에 하나씩 때려 박아야 한다. 반복적이니 반복문으로!

for (int i = 0; i < N; i++) {
  arr[i] = br.readLine();
}

여기까지 했으면 일단 기본적으로 배열에 입력한 값을 모두 넣은 것이다. 

다만 문제는 배열 각각의 인덱스의 값이 한 뭉텅이로 그 자체로는 우리가 원하는 연산을 할 수가 ? 없다.

그러면 어떻게 해야하느냐? 분리를 해줘야 한다. 

 

이중 반복문을 이용할 것인데 외부 for문에는  N번 ( 배열의 크기) 만큼 내부 for문에는 그 한 뭉텅이의 값들을 분리해서 연산하고 숫자 값을 저장하는 행위를 하는 것이다. 

 

즉 arr 이라는 배열에 0번째 인덱스의 값이  "OOXXOXXOOO" 라면, "OOXXOXXOOO" 를 각각 나누고 문제에 나온대로 연산하여 정수 값으로 저장한 뒤 다음 순서인 1번째 인덱스로 넘어가는 반복문인 것이다.

 

먼저 "O" 가 나오면 카운트를 해줘야해서 cnt라는 변수와 이들이 X로 끊기지 않고 연속으로 나오게 되면 중첩 덧셈해야 하므로 sum이라는 변수를 선언해준다.

for (int i = 0; i < N; i++) {
  int cnt = 0;
  int sum = 0;

이후 내부 반복문에서는 인덱스의 크기만큼 반복하며 charAt 함수를 통해 문자열을 분리했다. 

그리고 조건문을 통해 분리된 문자열이 "O" 와 동일하다면 cnt라는 변수에 숫자 1을 더하라는 뜻이고 

그렇지 않다면 == "X"를 만났다면 0으로 초기화 하라는 뜻이다.

그리고 sum+= cnt 가 중요한데 +=는 중첩 덧셈으로 sum = sum + cnt 의 단축어이다.

 

예를 들어 "O"가 3개가 나오면 1+2+3 이 되어 6이 나와야 하는데 \

 

중첩 덧셈 (sum = sum + cnt) 의 작동원리

1. O를 발견했으니 cnt는 1이 올라가서 1

     sum은 아직 값이 안더해졌으니 0

     0 = 0 + 1; 

     0 = 1; => sum은 이제 1

 

2. O를 발견했으니 cnt는 다시 1이 올라가서 2

    1 = 1 + 2;

    1 = 3;  => sum은 이제 3

 

3.O를 발견했으니 cnt는 다시 1이 올라가서 3

    3 = 3+3 ;

    3 = 6; => sum은 이제  6

 

우리가 구하려고 하는 것과 같다는 것을 알 수 있다. 

이렇게 하면 연속으로 나오는 "O"를 중첩으로 덧셈할 수 있는 것이다. 

for (int j = 0; j < arr[i].length(); j++) {
  if (arr[i].charAt(j) == 'O') {
    cnt++;
  } else {
    cnt = 0;
  }
  sum += cnt;
}

이제 이것을 출력해줘야 하는데 출력문을 반복해서 써도 되지만 이번에는 간지나게 한꺼번에 모아서 쏘겠다.

마치 원기옥?

원기옥

바로 StringBuilder라는 친구를 외부 for문 안에 소환해서 출력하고자 하는 값들을 연결시켜주면 된다. 마치 연결고리처럼. 

먼저 소환하기 

StringBuilder sb = new StringBuilder();

출력해야 할것들을 연결시켜서 저장해두기. '\n' 으로 개행해두는 것은 센스

sb.append(sum).append('\n');

그리고 반복문을 아예 빠져나와서 바깥에서 출력문은 단 한번만 쓰기

System.out.print(sb);

끝.

 

전체코드 

 

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

public class Main {
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringBuilder sb = new StringBuilder();
    int N = Integer.parseInt(br.readLine());
    String arr[] = new String[N];

    for (int i = 0; i < N; i++) {
      arr[i] = br.readLine();
    }
    br.close();
    for (int i = 0; i < N; i++) {
      int cnt = 0;
      int sum = 0;

      for (int j = 0; j < arr[i].length(); j++) {
        if (arr[i].charAt(j) == 'O') {
          cnt++;
        } else {
          cnt = 0;
        }
        sum += cnt;
      }

      sb.append(sum).append('\n');
    }
    System.out.print(sb);
  }
}