문제 해결 연습 | 기사단원의 무기

주싱·2023년 1월 14일
0

링크 : 프로그래머스 > Level 1 > 기사단원의 무기

문제

숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다. 각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다. 예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다. 기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.

소요 시간

20분

문제 해결 코드

import java.util.stream.IntStream;

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

public class TemplarWeaponTest {
    @Test
    void tester() {
        int solution = solution(5, 3, 2);
        Assertions.assertEquals(10, solution);
    }

    public int solution(int number, int limit, int downward) {
        return IntStream.range(1, number + 1) // 1 - number 까지 약수의 개수를 구한다.
                        .map(this::toDivisorNumber) // 약수의 개수는 n번 기사가 구매하려는 무기의 공격력이 된다.
                        .map(power -> power > limit ? downward : power) // 만약 구매하려는 무기의 공격력이 limit를 초과하는 경우 downward 공격력을 가진 무기를 구매하도록 한다.
                        .sum(); // 모든 기사가 구매하려는 공격력을 다 더한다.
    }

    private int toDivisorNumber(int number) {
        int divisorNumber = 0;

        for (int i = 1; i * i <= number; i++) {
            if (i * i == number) {
                divisorNumber ++;
            } else if (number % i == 0) {
                divisorNumber +=2;
            }
        }
        return divisorNumber;
    }
}

해결과정 회고

이번 문제는 문제 자체를 이해하는데 어려움을 겪었습니다. limit를 초과하는 무기를 구매하려는 경우 협약에서 지정한 공격력을 가지는 무기를 구매해야한다는 내용이 처음에 잘 이해되지 않았습니다. 그리고 중고등학교 때 배우고 현업에서 만난적이 없는 약수라는 용어의 개념이 순간 기억나지 않았습니다. 그리고 약수를 구하는 직관적인 방법(직접 나누어 보는 방법) 말고 성능을 높이는 방법이 있다는 것을 예전에 코딩테스트 문제를 풀다가 접한적이 있는데 당장 생각이 나지 않아 구글링해서 코드를 보고 따라 작성했습니다.

개선할점

약수의 개수를 카운팅하는 개념과 성능이 좋은 약수의 개수를 구하는 코드를 안보고도 쭉 작성할 수 있도록 익숙해 져야겠습니다.

잘한점

문제 해결 단계를 함수 내에 주석으로 달고, 각 단계를 Stream 파이프라인 단계 단계가 되도록 처리햇는데 코드를 이해하기도 좋고, 안정적으로 작성된 것 같습니다.

학습한 것

  • N의 약수란 N을 M으로 나누었을 때 나머지가 0이 되는 M의 개수입니다.
  • 약수를 구하는 직관적인 방법과 좋은 성능을 내는 방법에 대해 학습하였습니다.
profile
소프트웨어 엔지니어, 일상

0개의 댓글