복's

[ Programmers - LV2 ] 호텔 대실 본문

알고리즘/Programmers

[ Programmers - LV2 ] 호텔 대실

나복이 2024. 9. 11. 00:37
728x90

https://school.programmers.co.kr/learn/courses/30/lessons/155651

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

프로그래머스 문제 풀이할 때 시간 관련 문제가 나오면 LocalTime 을 먼저 사용하는데 계속해서 날짜가 넘어가는 케이스를 생각 못해서 엣지 케이스가 생기고, 그 때 마다 LocalDateTime 으로 변경하는 작업을 반복했다...

 

앞으로는 바로 LocalDateTime 을 사용 하던가, 아니면 시간을 쫌 더 편한 int 단위로 변경해서 풀이하는게 나을 것 같다.

(분 * 60) + 초

[ 📌 분석 ]

문제에서 요구하는 요구 사항이 명확하기 때문에 헷갈리는 부분은 없다고 생각 된다.

  • 체크인 한 객실이 가장 많을 때 최대 몇 개?
  • 체크 아웃시 10분의 청소 시간이 필요하다.

요구한 대로 구현하는 문제로 방법이야 많지만 나는 손님들이 시간에 맞춰서 찾아왔다가 시간이 되면 체크 아웃하고 나가는 그대로 구현했다.


[ 📌 부분 코드 - Java ]

⚙️ 선언부

Queue<Customer> waitingQ = new PriorityQueue<>(Comparator.comparing(a -> a.srtTime));
Queue<Customer> roomQ = new PriorityQueue<>(Comparator.comparing(a -> a.endTime));
int maxSize = 0;
  • waitingQ: 호텔 체크인 대기 손님들 (체크인 시간으로 정렬)
  • roomQ: 객실 사용중인 손님들 (체크아웃 시간으로 정렬)

⚙️ Customer

class Customer {
    private final int CLEAN_TIME = 10;
    LocalDateTime srtTime;
    LocalDateTime endTime;

    public Customer(int[] srtTime, int[] endTime) {
        LocalDate nowDate = LocalDate.now();

        this.srtTime = LocalDateTime.of(nowDate, LocalTime.of(srtTime[0], srtTime[1]));
        this.endTime = LocalDateTime.of(nowDate, LocalTime.of(endTime[0], endTime[1])).plusMinutes(CLEAN_TIME);
    }
}
  • 생성자: Date 는 now() 를 기준으로 넣었고, Time 은 주어진 문자열 데이터를 파싱 해서 넣었는데, endTime 의 경우 10 분의 청소 시간을 미리 더해주었다.

⚙️ 메인 로직

while(!waitingQ.isEmpty()) {
    Customer cus = waitingQ.poll();

    // 사용중인 호텔방 존재 && (체크인과 체크아웃 동시간 || 현 고객 체크인 시간보다 늦은 체크 아웃방)
    while(!roomQ.isEmpty() && (roomQ.peek().endTime.equals(cus.srtTime) || cus.srtTime.isAfter(roomQ.peek().endTime))) {
        roomQ.poll();
    }

    roomQ.add(cus);
    maxSize = Math.max(maxSize, roomQ.size());
}
  • 대기중인 손님이 전부 체크인 할 때 까지 조건으로 두었다. (중요한건 손님들 체크인 후 객실 사용이 가장 몰릴 때이기 때문에 전부 체크아웃 했는지 여부는 필요 없음)
  • isAfter 만 사용했을 때, 시간이 동일한 경우가 잡히지 않아서 equals 를 이용해서 체크인 & 체크아웃이 겹치는 시간도 포함해서 확인 후 현재 체크인 하는 고객의 시간을 기준으로 이미 체크아웃 시간이 지난 고객들은 체크아웃 시킨다.
  • 현 고객을 넣고, 최대 객실 갱신한다.

[ 📌 전체 코드 - Java ]

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

class Solution {
    public int solution(String[][] book_time) {
        Queue<Customer> waitingQ = new PriorityQueue<>(Comparator.comparing(a -> a.srtTime));
        Queue<Customer> roomQ = new PriorityQueue<>(Comparator.comparing(a -> a.endTime));
        int maxSize = 0;

        for(String[] times : book_time) {
            waitingQ.add(new Customer(getMinAndSec(times[0]), getMinAndSec(times[1])));
        }

        while(!waitingQ.isEmpty()) {
            Customer cus = waitingQ.poll();

            // 사용중인 호텔방 존재 && (체크인과 체크아웃 동시간 || 현 고객 체크인 시간보다 늦은 체크 아웃방)
            while(!roomQ.isEmpty() && (roomQ.peek().endTime.equals(cus.srtTime) || cus.srtTime.isAfter(roomQ.peek().endTime))) {
                roomQ.poll();
            }

            roomQ.add(cus);
            maxSize = Math.max(maxSize, roomQ.size());
        }

        return maxSize;
    }

    private int[] getMinAndSec(String times) {
        return Arrays.stream(times.split(":")).mapToInt(Integer::parseInt).toArray();
    }

    class Customer {
        private final int CLEAN_TIME = 10;
        LocalDateTime srtTime;
        LocalDateTime endTime;

        public Customer(int[] srtTime, int[] endTime) {
            LocalDate nowDate = LocalDate.now();

            this.srtTime = LocalDateTime.of(nowDate, LocalTime.of(srtTime[0], srtTime[1]));
            this.endTime = LocalDateTime.of(nowDate, LocalTime.of(endTime[0], endTime[1])).plusMinutes(CLEAN_TIME);
        }
    }
}

[ 📌 결과 ]

[ 결과 - Java ]


[ 📌 마치며... ]

LocalTime... 항상 코드 전부 짜고, 정답 돌려본 후 후회 중이다..

이제는 무조건 LocalDateTime 으로 가도 되지 않을까?

 

사실 이 문제도 오래전에 처음 봤을 때는 어떻게 풀지 감도 안잡혔는데, 지금은 쉽게 풀어서 놀랐다.

어찌저찌 계속해서 역량이 올라가고 있다는 증거...게...ㅆ...지...? 

728x90