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
foreach(KeyValuePair<> kv in dic)
dic.OrderBy(x => x.Key).ToDictionary(x=>x.Key, x=>x.Value);