[BaekJoon] 11365번 - !밀비 급일 (java)

1. 문제

👉 문제 바로가기

- 조건

시간 제한 메모리 제한
1초 256MB


- 문제

당신은 길을 가다가 이상한 쪽지를 발견했다. 그 쪽지에는 암호가 적혀 있었는데, 똑똑한 당신은 암호가 뒤집으면 해독된다는 것을 발견했다.
이 암호를 해독하는 프로그램을 작성하시오.


- 입력

한 줄에 하나의 암호가 주어진다. 암호의 길이는 500을 넘지 않는다.
마지막 줄에는 "END"가 주어진다. (END는 해독하지 않는다.)

- 출력

각 암호가 해독된 것을 한 줄에 하나씩 출력한다.

- 예제

  입력      출력  
!edoc doog a tahW
noitacitsufbo
erafraw enirambus detcirtsernu yraurbeF fo tsrif eht no nigeb ot dnetni eW
lla sees rodroM fo drol eht ,ssertrof sih nihtiw delaecnoC
END
What a good code!
obfustication
We intend to begin on the first of February unrestricted submarine warfare
Concealed within his fortress, the lord of Mordor sees all





2. 풀이

while 반복문을 사용해 “END” 입력전까지 무한 반복한다.

while (조건식) {
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문 작성;
}




2개의 입력방식을 사용해서 결과를 출력한다.

  1. Scanner 클래스
  2. BufferedReader 클래스



2-1. Scanner 클래스

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        
        while(true){
            String str = sc.nextLine();
            char[] c = new char[str.length()];
            
            if(str.equals("END")){
                break;
            }
            
            for(int i=0;i<c.length;i++){
                c[c.length - 1 - i] = str.charAt(i);
            }
            for(int i=0;i<c.length;i++){
                System.out.print(c[i]);
            }
            System.out.println();
        }
    }
}

위와같이 객체를 생성할 때, Scanner(System.in) 에서 System.in 은 입력한 값을 Byte 단위로 읽는 것을 뜻한다.

int형 데이터를 입력받기 위해 nextInt() 메서드를 사용한다.

break; 는 감싸고 있는 제어문의 블록을 빠져 나오는 기능이다.
반복문에서는 주로 조건문(if)와 같이 사용하여 조건에 해당되는 경우 반복 수행을 종료한다.
여러 반복문이 중첩되어 있는 경우엔 break 문이 포함되어 있는 가장 가까운 반복문만 빠져 나온다.

charAt() 을 사용해 입력받은 문자열 str 에서 순서대로 문자(char)를 추출한다.
추출한 문자를 char[] 배열에 마지막 인덱스부터 넣어준다.



[여기서 잠깐!]

Scanner에 대해 더 자세히 알고싶다면 여기 를 클릭하세요





2-2. BufferedReader 클래스 사용

3가지 출력 방식으로 문제를 풀어보고 비교해보자.

     ① StringBuilder
     ② BufferedWriter
     ③ System.out.println()



① BufferedReader + StringBuilder

String클래스에서는 reverse()를 제공하지 않아 변환해서 reverse()를 사용해야 한다.

StringBuilder, StringBuffer, Collection 클래스에서 reverse() 메서드를 제공한다.


StringBuilder 의 reverse() 를 사용해 문자열을 거꾸로 뒤집어서 출력한다.

StringBuffer sb = new StringBuffer(str);
String reverse = sb.reverse().toString();
System.out.println(reverse);




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();
        
        while(true){
            String str = br.readLine();
            
            if(str.equals("END")){
                break;
            }
            
            StringBuilder r = new StringBuilder(str);
            sb.append(r.reverse()).append("\n");
        }
        System.out.println(sb);
    }
}

StringBuilder 클래스는 문자열을 동적으로 조작하기 위한 클래스로, append() 를 사용해 문자열을 추가하여 새로운 문자열을 생성한다.
생성자 매개변수에 문자열을 전달 해서 객체를 생성해도 된다.

reverse() 메소드문자열을 거꾸로 뒤집어주는 함수 이다.
r.reverse().toString() 에서 toString() 은 생략해도 된다.
출력할 때 자동으로 toString() 를 실행시켜 문자열로 출력해준다.

append() 를 위와 같이 나눠서 쓰면 타입 변환과 문자열 연결 연산이 추가적으로 발생하지 않고 StringBuilder에 직접 추가하기 때문에 보다 더 효율적이고 빠르다.





② BufferedReader + BufferedWriter

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.StringTokenizer;

public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        
         while(true){
            String str = br.readLine();
            char[] c = new char[str.length()];
            
            if(str.equals("END")){
                break;
            }
            
            for(int i=0;i<c.length;i++){
                c[c.length - 1 - i] = str.charAt(i);
            }
            for(int i=0;i<c.length;i++){
                bw.write(c[i]);
            }
            bw.write("\n");
        }
        bw.flush();
        bw.close();
    }
}

BufferedWriter 클래스의 write() 메소드는 데이터를 내부 버퍼에 저장하고, flush() 메소드 를 사용해 버퍼를 비우고 데이터를 출력한다.



[여기서 잠깐!]

BufferedWriter 클래스에 대해 더 알아보고 싶으면 여기를 클릭하면 된다.





③ BufferedReader + System.out.println()

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));
        
        while(true){
            String str = br.readLine();
            char[] c = new char[str.length()];
            
            if(str.equals("END")){
                break;
            }
            
            for(int i=0;i<c.length;i++){
                c[c.length - 1 - i] = str.charAt(i);
            }
            for(int i=0;i<c.length;i++){
                System.out.print(c[i]);
            }
            System.out.println();
        }
    }
}





3. 성능 비교

image

위에서 부터 순서대로

BufferedReader + StringBuilder
BufferedReader + BufferedWriter
BufferedReader + System.out.println()
Scanner

위와같이 입력 메소드와 알고리즘 구현 방법에 따라 시간이 달라질 수 있다.

입력의 경우 확실히 Scanner 보다는 BufferedReader 가 빠른 것을 볼 수 있다.

출력의 경우 System.out.println() 가 제일 느리다.
BufferedWriter 보다는 StringBuilder 가 빠른 것을 볼 수 있다.
(그러나 데이터 양이 커지면 커질 수록 BufferedWriter 가 더 빠르다.)

BufferedWriter는 일반적으로 I/O 작업으로 인해 비교적 느릴 수 있다.
반면에 StringBuilder는 문자열 조작에 최적화된 클래스로, 문자열 연산은 일반적으로 메모리 상에서 수행되므로 상대적으로 빠를 수 있다.





관련 페이지

Categories:

Updated:

Leave a comment