ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 10/5 TIL | 잘게 쪼개서 나아가기.
    📝 기록/매일의 기록 2022. 10. 5. 23:55

    오늘 코딩 도장 문제는 부족한 금액 계산하기였는데, 문제의 내용은 아래와 같다.

    문제 설명

    새로 생긴 놀이기구는 인기가 매우 많아 줄이 끊이질 않습니다. 이 놀이기구의 원래 이용료는 price원인데, 놀이기구를 N 번 째 이용한다면 원래 이용료의 N배를 받기로 하였습니다. 즉, 처음 이용료가 100이었다면 2번째에는 200, 3번째에는 300으로 요금이 인상됩니다.
    놀이기구를 count번 타게 되면 현재 자신이 가지고 있는 금액에서 얼마가 모자라는지를 return 하도록 solution 함수를 완성하세요.
    단, 금액이 부족하지 않으면 0을 return 하세요.

    제한 사항

    - 놀이기구의 이용료 price : 1 ≤ price ≤ 2,500, price는 자연수
    - 처음 가지고 있던 금액 money : 1 ≤ money ≤ 1,000,000,000, money는 자연수
    - 놀이기구의 이용 횟수 count : 1 ≤ count ≤ 2,500, count는 자연수

    입출력 예

    price money count result
    3 20 4 10

    나의 문제 풀이

    [📃 SolutionTest.java - 테스트 코드]

    import org.junit.jupiter.api.Test;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    class SolutionTest {
        // 원하는 횟수만큼 놀이기구를 타려면 드는 금액 구하기
        @Test
        void totalPrice() {
            Solution solution = new Solution();
    
            assertEquals(30, solution.computeTotalPrice(3, 4));
        }
    
        // 내가 가지고 있는 돈과 비교하기
        @Test
        void checkMoney() {
            Solution solution = new Solution();
    
            assertEquals(10, solution.checkMoney(20, 30));
        }
    
        // 만약에 돈이 충분하다면 0을 반환하는지 테스트
        @Test
        void enoughMoney() {
            Solution solution = new Solution();
    
            assertEquals(0, solution.checkMoney(40, 30));
            assertEquals(0, solution.checkMoney(30, 30));
        }
    }

    오늘 작성한 테스트 코드는 위와 같다!

    public class Solution {
        public long solution(int price, int money, int count) {
            // 횟수만큼 타면 드는 비용을 구하고
            long totalPrice = computeTotalPrice(price, count);
    
            // 현재 가지고 있는 돈과 비교하고
            long answer = checkMoney(money, totalPrice);
            
            // 정답을 반환한다.
            return answer;
        }
    
        public long computeTotalPrice(int price, int count) {
            long totalPrice = 0;
    
            for (int i = 0; i <= count; i += 1) {
                totalPrice += price * i;
            }
    
            return totalPrice;
        }
    
        public long checkMoney(int money, long totalPrice) {
            // 만약 가지고 있는 돈이 충분하다면 0을 반환
            if (money >= totalPrice) {
                return 0;
            }
    
            return totalPrice - money;
        }
    }

    그렇게 해서 나온 풀이는 바로 위와 같다. 근데 이번 주 학습에서는 기존에 for문을 Stream API를 활용해서 개선했기에 나도 computeTotalPrice에서 for문으로 돌리던 내용을 steam으로 바꿔서 다시 풀어보았다.

    public long computeTotalPrice(int price, int count) {
    	return LongStream.rangeClosed(1, count).sum() * price;
    }

    다시 테스트를 돌려보니 Stream API가 시간이 더 오래걸린다는 사실을 알게 되었다.

    좌) for-loop / 우) Stream API

    정확한 이유는 아직 더 읽고 이해해야겠지만, 우선 오늘 이해한 바로는 JIT Compiler for-loop 거진 40 이상 다뤘기에 for-loop 대한 internal optimization 이미 되어 있는데 반해 스트림은 2015 이후에 도입되었으므로 아직 컴파일러가 최적화를 제대로 하지 못했다는 것이다.

    근데 Stream의 속도 개선을 위해서는 병렬 처리를 한다든지의 방법도 있다고 하는데 이것도 한번 찾아봐야할 거 같고, 어떤 연산을 하느냐에 따라 for-loop이 빠를지, stream이 빠를지 다르다고 하니 한번 계속 써보면서 경험해보려고 한다. (이제 for문은 익숙하니...)

    이외에도 뚜루님이 더 자세히 비교한 포스팅을 추천해주셔서 한번 읽어보려고 한다. (오늘은 과제하느라 바빠서 아직 읽지 못하였다.. 😅)

     

    Java Stream Api 에 대한 이런저런 고찰

    Stream 은 java8 부터 등장한 문법으로 기존에 사용하던 for-loop보다 가독성이 좋다는 점에서 많이 쓰인다. 하지만 for-loop 보다 느리며, 알고리즘 효율성 테스트에서 가끔 영향을 줄 때가 있다. 그렇

    intrepidgeeks.com


    당연한 소리지만 코딩 도장 문제는 오로지 내 힘으로 풀 때 항상 뿌듯하다. 매번 풀다가 막혀서 정답 찾아본 적 꽤 있을 유(有)인 사람으로서..^^ 오늘 문제는 온전히 내 머리로 해결하였고!! 통과되지 않던 케이스도 동기들 덕분에 해결할  있었다!! 그리고 첨엔 for문으로 문제 풀이를 하고, 두번째는 Stream 활용해서 한번 풀어보았던 것도 좋았고!👍🏻

    코딩 도장 문제 풀 때는 테스트도 잘 만들고 쪼개서 해결하면서.. 항상 퀘스트 과제 앞에만 서면... 나는 왜 작아지는가.....🎶 ㅠ 어제도 영속성 있는 투두리스트를 구현하려고 저녁에 책상 앞에 앉았다가 확 막막해져서 그냥 HTTP 책만 읽고 자버렸다..ㅎ 근데 오늘 아침에 코딩 도장 문제를 풀면서 퀘스트 과제도 이렇게 쪼개서 가자는 마음이 들었고 우선 영속성을 제외한 나머지 기능을 구현해보려고 한다. 오늘도 강의 반복 과제 인출이랑 HTTP 오답 노트 정리에 온 정신을 쏟았더니 아직도 투두리스트 과제를 시작하지 못했다.. 그래도 마카오뱅크보다는 스케일이 조그만 것에 위안 삼으며 이제 작업하러 가보자!


     

    어제자 TIL가 티스토리 메인에 또!

    그리고 어제자 TIL이 티스토리 메인에 올랐다. 이 영광을 내 옆자리 쥬쥬에게 바칩니다.🌹