문제

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.

 

단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.

 

출력

첫째 줄에 그룹 단어의 개수를 출력한다.

 

전체 코드(Java)

import java.io.*;

public class Main {
    public static void main (String [] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());
        int[] check = new int[26];
        int ans = 0;
        boolean isBreak = false;

        for (int i = 0; i < N; i++) {
            String s = br.readLine();

            isBreak = false;
            for (int j = 0; j < check.length; j++) {
                check[j] = 0;
            }

            check[s.charAt(0) - 'a']++;
            for (int j = 1; j < s.length(); j++) {
                if (check[s.charAt(j) - 'a'] != 0 && s.charAt(j) != s.charAt(j - 1)) {
                    isBreak = true;
                    break;
                }

                check[s.charAt(j) - 'a']++;
            }
            if (!isBreak)
                ans++;
        }

        System.out.println(ans);
        br.close();
    }
}

 

풀이

  1. N개의 단어를 입력 받을 때 br.readLine()은 스트링 형태로 반환하기 때문에 Integer.parseInt()를 사용해 int로 변환
  2. N번 String s에 문자열을 입력받음. 또한 check 배열과 isBreak 변수는 매 회 초기화
  3. int[] check 배열이 핵심 포인트
    • 해당 배열은 어떤 알파벳이 사용되었는지를 체크하기 위한 정수형 배열
    • 만약 'a'가 사용되었다면 check[0] >= 1이 됨 : [s.charAt(j) - 'a']++을 통해 기록
    • 따라서 check[s.charAt(j) - 'a']의 값이 0이 아니고, 이전의 문자( charAt(j-1) )가 현재의 문자( charAt(j) )와 같지 않다면 그룹 단어가 아님
    • 그룹 단어가 아닌 경우 2중 for문에서 break가 일어나게 되고, isBreak가 true가 되어 ans의 값이 증가하지 않음
    • 그룹 단어인 경우 break가 일어나지 않아 ans가 +1됨
  4. 최종적으로 ans의 값을 출력하면 정답

문제

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.

 

크로아티아 알파벳 변경
č c=
ć c-
dz=
đ d-
lj lj
nj nj
š s=
ž z=

예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.

 

입력

첫째 줄에 최대 100글자의 단어가 주어진다. 알파벳 소문자와 '-', '='로만 이루어져 있다.

단어는 크로아티아 알파벳으로 이루어져 있다. 문제 설명의 표에 나와있는 알파벳은 변경된 형태로 입력된다.

 

출력

입력으로 주어진 단어가 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

 

전체 코드(Java)

import java.io.*;

public class Main {
    public static void main (String [] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String input = br.readLine();

        int count = 0;

        for (int i = 0; i < input.length(); i++, count++) {
            if (i == input.length() - 1) {
                count++;
                break;
            }
            char nextChar = input.charAt(i+1);

            switch(input.charAt(i)) {
            case 'c':
                if (nextChar == '=' || nextChar == '-')
                    i++;
                break;
            case 'd':
                if ((i+2 < input.length() && nextChar == 'z' && input.charAt(i+2) == '='))
                    i += 2;
                else if (nextChar == '-')
                    i++;
                break;
            case 'l':
                if (nextChar == 'j')
                    i++;
                break;
            case 'n':
                if (nextChar == 'j')
                    i++;
                break;
            case 's':
                if (nextChar == '=')
                    i++;
                break;
            case 'z':
                if (nextChar == '=')
                    i++;
                break;
            default:
                break;
            }
        }
        System.out.println(count);
        br.close();
    }
}

 

풀이

  1. 문자열을 입력받는다.
  2. for문과 charAt을 이용하여 문자열의 원소를 하나씩 읽어들인다. for 문은 한 번 돌때마다 count를 증가시킨다
    • 단, 크로아티아 알파벳이 되는 경우의 수는 switch 문으로 처리한다
    • 예를 들어, 문자 'c'가 온다면 그 다음 인덱스의 원소(nextChar)가 '=' 또는 '-'일 때 한 문자 취급한다
    • 한 문자 취급하기 위해 i의 인덱스를 for문 내부에서 +1하여 다음 원소를 읽지 않는 것이다
    • 해당 방법 사용시 문자열의 마지막 인덱스를 넘어선 접근을 하지 않도록 예외 처리가 필요하다
  3. count를 출력한 것이 정답이 된다

문제

상근이의 할머니는 아래 그림과 같이 오래된 다이얼 전화기를 사용한다.

전화를 걸고 싶은 번호가 있다면, 숫자를 하나를 누른 다음에 금속 핀이 있는 곳 까지 시계방향으로 돌려야 한다.

 

숫자를 하나 누르면 다이얼이 처음 위치로 돌아가고, 다음 숫자를 누르려면 다이얼을 처음 위치에서 다시 돌려야 한다.

 

숫자 1을 걸려면 총 2초가 필요하다. 1보다 큰 수를 거는데 걸리는 시간은 이보다 더 걸리며, 한 칸 옆에 있는 숫자를 걸기 위해선 1초씩 더 걸린다.

 

상근이의 할머니는 전화 번호를 각 숫자에 해당하는 문자로 외운다. 즉, 어떤 단어를 걸 때, 각 알파벳에 해당하는 숫자를 걸면 된다. 예를 들어, UNUCIC는 868242와 같다.

 

할머니가 외운 단어가 주어졌을 때, 이 전화를 걸기 위해서 필요한 최소 시간을 구하는 프로그램을 작성하시오.

 

전체 코드(By Java)

import java.io.*;

public class Main {
    public static void main (String [] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String input = br.readLine();
        int result = 0;
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);

            switch(c) {
            case 'A': case 'B': case 'C':
                result += 3;
                break;
            case 'D': case 'E': case 'F':
                result += 4;
                break;
            case 'G': case 'H': case 'I':
                result += 5;
                break;
            case 'J': case 'K': case 'L':
                result += 6;
                break;
            case 'M': case 'N': case 'O':
                result += 7;
                break;
            case 'P': case 'Q': case 'R': case 'S':
                result += 8;
                break;
            case 'T': case 'U': case 'V':
                result += 9;
                break;
            case 'W': case 'X': case 'Y': case 'Z':
                result += 10;
                break;
            }
        }
        System.out.println(result);
        br.close();
    }
}

해결 방법

  1. BufferedReader로 문자열을 읽음 - input 변수
  2. for문을 통해 charAt으로 문자열의 각 원소를 저장 - c 변수
  3. switch문으로 각 문자에 알맞는 숫자를 result에 더함
  4. 결과값(result) 출력

 

생각해볼것

  • 문자열을 String으로 받은 후 charAt() 메소드로 인덱스 접근을 했다.
  • 하지만 toCharArray() 메소드를 이용해 char형 배열로 바로 받을 수 있다.
    • 속도적인 면에서는 별 차이가 없어보인다.

문제

상근이의 동생 상수는 수학을 정말 못한다. 상수는 숫자를 읽는데 문제가 있다. 이렇게 수학을 못하는 상수를 위해서 상근이는 수의 크기를 비교하는 문제를 내주었다. 상근이는 세 자리 수 두 개를 칠판에 써주었다. 그 다음에 크기가 큰 수를 말해보라고 했다.

 

상수는 수를 다른 사람과 다르게 거꾸로 읽는다. 예를 들어, 734와 893을 칠판에 적었다면, 상수는 이 수를 437과 398로 읽는다. 따라서, 상수는 두 수중 큰 수인 437을 큰 수라고 말할 것이다.

 

두 수가 주어졌을 때, 상수의 대답을 출력하는 프로그램을 작성하시오.


전체 코드(By Java)

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main (String [] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        StringBuilder A = new StringBuilder(st.nextToken());
        StringBuilder B = new StringBuilder(st.nextToken());

        A.reverse();
        B.reverse();

        System.out.println(Math.max(Integer.parseInt(A.toString()), Integer.parseInt(B.toString())));

        br.close();
    }
}

해결 방법

  • 해당 코드의 구현은 크게 3부분으로 나누어진다.
    • StringTokenizer로 입력값을 공백으로 구분하여 StringBuilder 클래스의 A, B에 할당
    • A와 B를 StringBuilder의 메소드인 reverse()로 문자열을 반대로 뒤집음
    • 더 큰 값을 비교하여 출력 - Math.max() 사용

+ Recent posts