Coding History

2024. 06. 07 문제 풀이

BlackBirdIT 2024. 6. 7. 14:59

내가 여태껏 나에게 굉장히 어렵게 다가왔던 문제들이 아마도 내게 아직 "개발자적 사고"가 부족하기 때문이라고 생각한다. 프로그래머스 코딩 테스트 0레벨을 하고 있는데 가만 생각해보니까 문제를 순서대로 풀지 않고 있었다. 오른쪽 배너를 확인해보니까 문제 푸는 순서가 있더라. 그래서 오늘은 그냥 순서대로 풀려고 한다.. 오늘은 좀 무난하게 넘어가지 않을까 싶다.

아니다 지금 분수 더하기 문제 풀고 있는데 분수 덧셈 공식부터 찾아보고 있다. 초등 교육에서 아마 배울텐데 도대체 이걸 코드로 어떻게 표현해야되는지 지금 감조차 잡히지 않는다. 분수 덧셈을 할 줄 모르는게 아니라, 이걸 어떻게 자바랑 연동하는지 감이 잡히지 않는다는거다.

//첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로
// 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록
// solution 함수를 완성해보세요.
class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) { // numer1 / denom1 + numer2 / denom2 = n / d
        int[] answer = new int[2];
        int d = denom1 * denom2; // 통분
        int n1 = numer1 * denom2;
        int n2 = numer2 * denom1;
        int x = d / n1 + d / n2; // x 값은 문제처럼 분수를 더한 값이 되긴함.
        return answer;
    }
}

이렇게 통분해서 더한 값 자체를 찾긴했다. 문제는 더한 값을 return하는게 아니라, 분자와 분모를 순서대로 담은 배열을 return해야된다. 그러면 저렇게 통분해서 계산해도 만약 분수가 더 줄일 수 있는 상태라면 그런 걸 할 수 있는 코드도 짜야되는건데 뭘 어떻게 해야될지 감도 안잡힌다. 아니면 최소공배수를 찾는 로직을 찾아볼까? 어 이거 치면서 뭔가 아이디어가 번쩍하긴 했는데 뭔가 희미하다 느낌이. 일단 최소공배수를 찾는 코드를 구글링 해보았다.

public static int lcm(int a, int b) {
    return a * b / gcd(a, b);
}

오케이 이걸 활용해보자.
아, 이걸 활용하려면 gcd = 최대공약수를 구하는 코드도 알아야한다. 그 코드가

// 재귀 방식
public static int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

이런 코드다.

class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) { // numer1 / denom1 + numer2 / denom2 = n / d
        int[] answer = new int[2];
        int lcm = denom1 * denom2 / gcd(denom1, denom2); //최소공배수

        int d1 = denom1 * lcm;
        int d2 = denom2 * lcm;
        int n1 = d1 * numer1;
        int n2 = d2 * numer2;

        answer[0] = n1 + n2;
        answer[1] = d1 + d2;
        return answer;
    }

    private int gcd(int a, int b) { // 최대공약수 로직
        return gcd(b, a % b);
    }
}

일단 이렇게 구색을 갖춰보았다. 당연 답은 아닐거라 생각은 하고 있고 테스트 케이스를 돌리려고 하는데 테스트 케이스에 기댓값을 두개를 넣는거에서 좀 문제가 생겨서 이걸 해결할 방법을 찾아봐야겠다.

아 기댓값에 두개를 넣는게 문제가 아니고 기댓값에 배열이라고 설명을 해줘야되는게 문제였다.

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class Tests { //수정 전,
    @Test
    @DisplayName("값 9, 4")
    void t1() {
        assertThat(new Solution().solution(1, 2, 3, 4)).isEqualTo(9, 4); //여기가 문제
    }
}
public class Tests { //수정 후
    @Test
    @DisplayName("값 9, 4")
    void t1() {
        assertThat(new Solution().solution(1, 2, 3, 4)).isEqualTo(new int[]{9, 4}); //new int[]와 배열로값을 넣어줌.
    }
}  

자 이제 테스트 돌려보자.

아 오류가 뜬다... 코드 자체에 뭔가 문제가 있는 것 같다.. 그냥 싹 지우고 다시 해봐야겠다.

class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int lcm = denom1 * denom2 / gcd(denom1, denom2); // 최소공배수

        // 분모를 최소공배수로 맞추기 위해 분자도 변경
        int n1 = numer1 * (lcm / denom1);
        int n2 = numer2 * (lcm / denom2);

        // 합친 분자
        int numer = n1 + n2;

        // 약분하기 위해 최대공약수 계산
        int gcdValue = gcd(numer, lcm);

        // 결과 분자와 분모를 약분한 값을 저장
        return new int[]{numer / gcdValue, lcm / gcdValue};
    }

    private int gcd(int a, int b) { // 최대공약수 로직 -> 내 맘대로 if문을 뺐었는데 다시 써 넣음
        if (b == 0) return a;
        return gcd(b, a % b);
    }
}

처음 저 위에 코드는 오류는 둘째 치고 계산부터가 틀려먹었다 코드 쓰면서 깨달았다. 최소공배수 구해놓고 또 같은 작업을 하려고 했었던 나 자신을, 그럴 수도 있지.. 지금 이 문제 11시 반부터 현재 시각 2시 20분까지 잡고 있으니 정신이 온전할리가.

아무튼 구글링을 좀 하긴 했지만 풀긴 풀었다. 문제 하나씩 풀 때 마다 내가 이걸 잘 할 수 있을까 의문이 계속 든다.. 그래도 꾸준히 하다보면 더 나아지겠지. 잘 하려고도 하지 말고 일단 하자. 다음 문제는 좀 쉽게 쉽게 갔으면 좋겠다.

그러므로 일단 다음문제.

뭔가 풀 수 있을 것 같은 느낌이 든다!

//정수 배열 numbers가 매개변수로 주어집니다. numbers의 각 원소에 두배한 원소를 가진 배열을 return하도록
//solution 함수를 완성해주세요.
class Solution {
    public int[] solution(int[] numbers) {
        //반복문선언 반복문의 길이 만큼 1씩 증가.
        for (int i = 1; i <= numbers.length; i++) {
            numbers[i - 1] *= 2; // => 반복할 때 마다 2를 곱한 값을 배열에 저장.
        }

        return numbers; // => 배열 출력
    }
}

휴 그렇게 오래 걸리지는 않았다. 처음엔 return에 배열을 어떻게 넣을지 고민하다가 numbers 자체가 배열인걸 깨달고 저렇게 써 넣었고 처음엔 테스트 케이스를 통과하지 못했다. 논리 변수 <= 이게 이렇게 >= 반대로 되어있어서 내가 넣은 값이 그대로 나온거였다. 어찌됐든 풀어냈다!! 다행이다.

음 다음문제는 중앙 값을 구해라는데.. 솔직히 오래 걸릴 것 같다. 그냥 다음에 하련다. 이제 곧 애들 가르치러 가야된다. 주말은 그냥 쉬고 싶긴한데 내가 또 포스팅 할 수도 있다. 그럼 오늘도 좋은 하루.