[Programmers] 주차 요금 계산

ssu_hyun·2022년 10월 16일
0

Data Structure & Algorithm

목록 보기
67/67
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;

class record
{
        // 시각
        public DateTime time;
        // 입/출차
        public bool carIn;
        // 누적 시간
        public double timeSum;
        // 내야하는 요금
        public double totalFee;
}

/// <summary>
/// 차량별로 주차 요금 계산
/// 출차된 내역이 없다면 23:59에 출차로 간주
/// 기본시간 이하 : 기본 요금 
/// 기본시간 초과 : 기본요금 + 단위시간 초과시 단위요금 (나누어 떨어지지 않을 시 올림)
/// 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아 return
/// </summary>
/// <param name="fees">기본 시간, 기본 요금, 단위 시간, 단위 요금</param>
/// <param name="records">시각, 차량 번호, 입/출차</param>
/// <returns></returns>
public class Solution
{
        public int[] solution(int[] fees, string[] records)
        {
                // 주차요금 관련 기본 변수 설정
                int baseTime = fees[0];
                int baseRate = fees[1];
                int unitTime = fees[2];
                int unitRate = fees[3];

                // 딕셔너리 => 차량 번호 :  struct {시각, 입/출차 여부, 누적시간, 내야하는 요금} 
                Dictionary<int, record> dic = new Dictionary<int, record>();

                #region 1. Records 돌면서 dic에 데이터 저장
                // records를 for문을 통해 돌면서 하나씩 int로 만들며 쪼개서 검사
                foreach (string r in records)
                {
                        DateTime t = DateTime.ParseExact(r.Split()[0], "HH:mm", CultureInfo.InvariantCulture);
                        int carNum = int.Parse(r.Split()[1]);
                        bool isIn = r.Split()[2] == "IN" ? true : false;

                        // 만약 dic 안에 해당 차량 번호 Key가 없다면
                        if (!dic.ContainsKey(carNum))
                        {
                                // 생성해서 데이터 저장
                                record re = new record();
                                re.time = t;
                                re.carIn = isIn;
                                re.timeSum = 0;

                                dic[carNum] = re;
                        }
                        // 만약 차량 번호가 있다면
                        else
                        {
                                // 입/출차 여부 검사해서 true일 경우
                                if (dic[carNum].carIn == true)
                                {
                                        // 시간 차(새로 받아온 시각 - 저장되어있는 시각) 계산해서 누적 시간 저장
                                        TimeSpan timeDif = t - dic[carNum].time;
                                        // 시간 차의 totalMinute을 누적 시간에 더하기
                                        dic[carNum].timeSum += timeDif.TotalMinutes;
                                        // 출차 표시
                                        dic[carNum].carIn = false;
                                }
                                // 입 / 출차 여부 검사해서 false일 경우
                                else
                                {
                                        // 새로운 입차 시각 저장
                                        dic[carNum].time = t;
                                        // 입차 표시
                                        dic[carNum].carIn = true;
                                }
                        }
                }
                #endregion


                #region 2. 출차 안된 차량 검사 & 누적 시간에 따른 주차 요금 계산
                // 모든 Records 다 돌은 뒤에 
                //  dic의 입/출차 여부 중 true가 있을 경우(출차가 안된 경우)
                foreach (KeyValuePair<int, record> kv in dic)
                {
                        if (kv.Value.carIn == true)
                        {
                                //  23:59와 계산해서 누적 시간 저장
                                DateTime lastTime = DateTime.ParseExact("23:59", "HH:mm", CultureInfo.InvariantCulture);
                                TimeSpan timeDif = lastTime - kv.Value.time;
                                kv.Value.timeSum += timeDif.TotalMinutes;
                                // 출차 표시
                                kv.Value.carIn = false;
                        }
                        // 각 dic의 차량별 누적 주차 시간에 따른 주차 요금 계산
                        if (kv.Value.carIn == false)
                        {
                                // 기본 시간 이하인 경우 
                                if (kv.Value.timeSum <= baseTime)
                                {
                                        kv.Value.totalFee = baseRate;
                                }
                                // 기본 시간 초과인 경우
                                else
                                {
                                        // 초과된 분에 따라 요금 계산
                                        double overMin = kv.Value.timeSum - baseTime;
                                        double overRate = Math.Ceiling(overMin / unitTime) * unitRate;
                                        kv.Value.totalFee = baseRate + overRate;
                                }
                        }
                }
                #endregion


                #region 3. dic 정렬 후 answer 값 저장
                // 차량번호 기준 dic 정렬
                dic = dic.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
                // answer에 차례대로 저장
                int[] answer = new int[dic.Count];
                int idx = 0;
                foreach (KeyValuePair<int, record> kv in dic)
                {
                        answer[idx] = Convert.ToInt32(kv.Value.totalFee);
                        idx++;
                }
                #endregion

                return answer;

        }
}
  • DateTime.ParseExact()
  • bool isIn = r.Split()[2] == "IN" ? true : false;
  • TimeSpan, .TotalMinutes
  • Class vs Struct
  • foreach(KeyValuePair<> kv in dic)
  • dic.OrderBy(x => x.Key).ToDictionary(x=>x.Key, x=>x.Value);

0개의 댓글