https://www.acmicpc.net/problem/2588
문제
(세 자리 수) × (세 자리 수)는 다음과 같은 과정을 통하여 이루어진다.
(1)과 (2)위치에 들어갈 세 자리 자연수가 주어질 때 (3), (4), (5), (6)위치에 들어갈 값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 (1)의 위치에 들어갈 세 자리 자연수가, 둘째 줄에 (2)의 위치에 들어갈 세자리 자연수가 주어진다.
출력
첫째 줄부터 넷째 줄까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.
내 생각 :
최근 단계별 백준 문제를 풀기 시작하면서 궁금한 부분들이 많아졌다.
(다양한 접근 방법, 효율적인 코드 작성, 타인의 코드)
이 문제 역시 그 중 하나였다.
우선 내가 맨 처음 접근한 방법은 수학적 접근으로, 자연수 B의 자릿수를 이용해 연산하고 출력하는 방법이였다.
예시로 위의 예제 입력과 동일하게 출력하고자 한다면 (472 x 5) + (472 x 80) + (472 x 300) 이런 식으로 나눌 수 있는데,
(3)번 출력이 (472 x 5)이라 연산하고 그대로 출력하면 되고, 다음 (4)번 같은 경우엔 (472 x 80)인데, 80을 472에 곱해야 하니까 385로부터 80을 분리해야한다. 그래서 385%100/10을 하게 되면 80이 분리가 된다. (4)도 마찬가지다.
이렇게 접근을 하거나 혹은 배열을 사용할까? 라는 생각이 들었다.
3칸의 배열을 만들어서 값을 저장하고.. 출력하는 방식으로 해야하나? 라는 생각이 들었는데 배열을 통해 이 문제를 풀게될 경우 불필요한 자원들이 낭비되지는 않을까, 성능상으로 비효율적이지 않나? 라는 생각이 들었다.
수학적 접근을 통해 답을 제출했고 풀긴 했으나 다른 사람들은 어떻게 코드를 작성했는지 궁금해서 확인하게 되었다.
내 코드와 다른 사람의 코드의 다른점
1) 입력과 출력부분
나는 스캐너 함수를 사용했지만 타인은 버퍼를 사용했다는 점이 가장 큰 특징이였다.
2) 접근방식의 차이
수학적 접근 방식과 배열을 이용한 접근방식
1)번 같은 경우엔 성능의 이슈가 가장 컸다. (스캐너와 버퍼) 우선 결과부터 말하자면 버퍼가 스캐너보다 성능면에서 우수했다.
백준 사이트에서 확인한 입력 속도 비교 : https://www.acmicpc.net/blog/search/%EC%9E%85%EB%A0%A5+%EC%86%8D%EB%8F%84
명확한 속도차이를 보인다.
우선 bufferedReader는 우선 동기식이고, 스캐너는 동기식이 아니다. 여러 스레드를 사용하려면 bufferedReader를 사용해야 한다.
bufferedReader는 스캐너보다 더 큰 메모리 버퍼를 가지고 있다
스캐너는 bufferedReader와 정반대로 작은 버퍼를 가지고 있다(스캐너 : 1KB 문자 버퍼, 버퍼 : 8KB 바이트 버퍼) 근데 이건 충분하다?
bufferedReader가 좀 더 빠르다 스캐너와 비교하면, 이유는 스캐너는 입력 데이터를 비교하고, bufferedReader는 단지 순서의 특징에 의해 읽기만 해서
쉽게 말해 buffer 사용 여부의 차이인데, 윗 문서에서 보면 Scanner는 1KB의 문자 버퍼를 갖기에 입력이 바로 전달되고, bufferedReader는 buffer에 입력들을 저장했다가 한 번에 전송해 속도가 더 빠르다는데
(바로 전달되는거랑 vs 저장했다 한번에 전송하는것 중 후자가 더 빠르다고?)
또한 Scanner는 입력을 읽는 과정에서 정규 표현식 적용, 파싱 과정, 분할 등의 과정을 거친다고 한다. 그래서 속도가 느리다. (Scanner 같은 경우 1024 chars의 버퍼 사이즈를 가지고, BufferedReader는 8192의 버퍼 사이즈를 가짐)
외에도 Scanner와 BufferedReader의 특징을 보면 다음과 같다.
Scanner는 데이터 형을 받기 편한데, 이유는 입력하면서 바로 형변환이 일어나기 때문이다.
Scanner는 IOException을 숨긴다. 또한 입력값의 경계로 공백, 엔터 모두 인식이 가능하다.
동기화 되지 않는다.
BufferedReader는 데이터가 문자열로 먼저 저장되서 형변환이 필수다.
그리고 입력값이 엔터만 인식하기에 한 라인에 여러가지 입력을 필요로 할 시 stringtokenize가 필수다.
또한 IOException을 던져야 하며 입력과 동시에 동기화 된다.
2) 접근 방식의 차이에서는 나는 수학적으로 접근을 해서 문제를 풀었지만 외에도 다양한 방식들이 있었다.
1) 문자열로 입력받아서 charAt()으로 꺼내쓰는 방식
2) 배열 이용하는 방식
이 두 방식은 형변환이 필요하다(문자형으로 입력 받기에)
문자열로 입력받아 charAt()은 반환값이 아스키코드여서 다시 Integer.charAt()으로 형변환을 하면 된다.
배열에 넣어서 하나씩 비교하면서 답을 구하면 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int A = Integer.parseInt(bufferedReader.readLine());
int B = Integer.parseInt(bufferedReader.readLine());
System.out.println(A*(B%10));
System.out.println(A*(B%100/10));
System.out.println(A*(B/100));
System.out.println(A*B);
}catch (IOException e){
}
}
}
작성한 코드는 다음과 같다.
'알고리즘 및 자료구조 > 백준(BackJoon)' 카테고리의 다른 글
백준 - 3052번 (0) | 2022.08.08 |
---|---|
백준 - 1546번 (0) | 2022.08.07 |
백준 - 2577번 (0) | 2022.08.05 |
백준 -2562번 (0) | 2022.08.05 |
백준 - 10818번 (0) | 2022.08.05 |