suheang

[백준] | JAVA, 자바 | 1735번 - 분수 합 본문

알고리즘

[백준] | JAVA, 자바 | 1735번 - 분수 합

suheang 2024. 3. 21. 20:08

https://www.acmicpc.net/problem/1735

 

1735번: 분수 합

첫째 줄과 둘째 줄에, 각 분수의 분자와 분모를 뜻하는 두 개의 자연수가 순서대로 주어진다. 입력되는 네 자연수는 모두 30,000 이하이다.

www.acmicpc.net


문제 요약 :

분수 A/B는 분자가 A, 분모가 B인 분수를 의미한다. A와 B는 모두 자연수라고 하자.

두 분수의 합 또한 분수로 표현할 수 있다. 두 분수가 주어졌을 때, 그 합을 기약분수의 형태로 구하는 프로그램을 작성하시오. 기약분수란 더 이상 약분되지 않는 분수를 의미

 

( 첫째 줄에 구하고자 하는 기약분수의 분자와 분모를 뜻하는 두 개의 자연수를 빈 칸을 사이에 두고 순서대로 출력 )


문제 풀이 :

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

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

        for (int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            a[i] = Integer.parseInt(st.nextToken());
            b[i] = Integer.parseInt(st.nextToken());
        }

        int x = b[0], y = b[1];

        while (y != 0) {
            int temp = x % y;
            x = y;
            y = temp;
        }

        int c = b[0] * b[1] / x;

        a[0] *= c / b[0];
        a[1] *= c / b[1];
        int sum = a[0] + a[1];
        int x1 = c, y1 = sum;

        while (y1 != 0) {
            int temp = x1 % y1;
            x1 = y1;
            y1 = temp;
        }

        System.out.println(sum/x1 + " " + c/x1);
    }
}

 

1. 첫째 줄과 둘째 줄에 주어진 분수의 분자와 분모를 입력받음

2. 분모의 최소공배수를 구하고 분자를 최소공배수가 된 만큼 곱해줌

3. 곱한 분자를 더해주고 더한 분자와 분모의 최대 공약수를 구함

4. 분자와 분모를 최대 공약수로 나눠 기약분수 형태로 출력


리팩토링

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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());
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine());
        int c = Integer.parseInt(st.nextToken());
        int d = Integer.parseInt(st.nextToken());
        
        int numerator = a * d + b * c;
        int denominator = b * d;
        int gcd = gcd(numerator, denominator);

        StringBuilder sb = new StringBuilder();
        sb.append(numerator/gcd).append(" ").append(denominator/gcd);
        System.out.println(sb);
    }

    public static int gcd(int a, int b) {
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }
}

 

처음 풀 때는 최대 공약수를 두 번 구했다. 최소 공배수를 구하기 위해 한번, 기약분수로 만들기 위해 한번

하지만 분수를 계산할 때 아래와 같은 방법으로 계산하면 기약분수로 만들기 위해 한 번만 최대 공약수를 구해도 된다

위 코드에서는 분자와 분모를 한 번에 계산하고 그 뒤에 최대 공약수로 기약분수를 만들었다.

 

그동안 백준 문제를 풀면서 Main 메서드 안에서만 문제를 해결하려고 했었다. 그러다가 이 문제를 처음 풀 때처럼 최대 공약수를 두 번 구하는 등의 여러 반복을 해결해야 한다면 메서드를 사용해 가독성을 높이기 위해 사용하는 게 맞겠다는 생각이 들었다. 이제부터는 메서드를 사용할 문제가 있다면 메서드를 사용할 생각이다.

 

 

 

코드 길이는 조금 늘어났지만 성능은 훨씬 좋아졌다.