[프로그래머스] 주차 요금 계산 - LEVEL2

Doorbals·2023년 1월 7일
0

프로그래머스

목록 보기
4/10

🔗 문제 링크

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


✍️ 문제 풀이

1) 먼저 데이터들을 저장할 vector 변수들을 여러 개 마련했다.

  • 입차한 모든 차량 번호 - carNumbers
  • 차량들의 가장 최근 입차 시간 - inTime
  • 모든 차량의 (차량 번호, 누적 시간, 요금, 입출차 여부) 한 번에 저장 - totalData
  • 모든 차량 요금 - result

2) 입출차기록인 records를 처음부터 끝까지 확인하기 시작한다.
3) 각 기록들에서 차량 번호 / 시간 / / 입출차타입을 따로 추출한다.
4) carNumbers에서 차량 번호가 있는지 확인한다.

  • 없으면 (아직 들어온 적 없는 차면) 데이터들을 처음으로 입력해준다.
    • carNumbers차량 번호 push
    • inTime에 (시간, ) push
    • totalData에 (차량 번호, 누적 시간 = 0, 요금 = 0, 입출차여부 = false) push

=> 이렇게 되면 모든 컨테이너들에 차량이 처음 입차한 순서대로(동일한 인덱스로) 데이터가 저장된다.

  • 있으면 (이미 들어왔던 차면) 차량 번호 목록에서 인덱스를 찾아 이미 있던 데이터들을 갱신해준다.
    • 입출차타입이 IN이면
      • inTime시간/으로 입차 시간을 갱신한다.
      • totalData입출차여부를 false(출차 안 했음 표시)로 바꿔준다.
    • 입출차타입이 OUT이면
      • {totalData에 저장되어있던 누적 시간 + (출차 시간 - 입차 시간)}으로 누적 시간을 갱신
      • totalData입출차여부를 true(출차 했음 표시)로 바꿔준다.

5) 모든 records를 돌고 난 이후, 마지막으로 totalData의 입출차여부만 처음부터 끝까지 확인하여 출차 안 한차가 있는지 확인해서 있으면 23:59에 출차한 것으로 처리해주고, 이제 모든 차량의 누적 시간이 확인되었으므로 이를 토대로 모든 차량의 요금을 계산해 totalData요금을 갱신한다.

6) totalData의 차량 번호 오름차순으로 totalData를 정렬한다.
7) 정렬된 순서대로 totalData요금result 벡터에 삽입한다.
8) result를 반환한다.


🖥️ 풀이 코드

#include <iostream>
#include <tuple>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;
typedef pair<int, int> pii;     				// (시간, 분)
typedef tuple<string, int, int, bool> tsiib;    // (차량 번호, 누적 시간, 요금, 출차 여부)

// 차량번호 오름차순으로 sort 하기 위한 함수
bool Compare(tsiib a, tsiib b)
{
    return stoi(get<0>(a)) < stoi(get<0>(b));
}

vector<int> solution(vector<int> fees, vector<string> records) 
{
    vector<string> carNumbers;      // 입차한 차량 번호 목록
    vector<pii> inTime;             // 차량들의 가장 최근 입차 시간 목록
    vector<tsiib> totalData;        // 모든 차량의 (차량 번호, 누적시간, 요금, 출차 여부)
    vector<int> result;             // 모든 차량 요금 목록

    int recordsLen = records.size();
    for (int i = 0; i < recordsLen; i++)
    {
        string numSubStr = records[i].substr(6, 4);        // 차량 번호 부분 추출
        int hourSubStr = stoi(records[i].substr(0, 2));    // 시간 부분 추출
        int minSubStr = stoi(records[i].substr(3, 2));     // 분 부분 추출
        string passType = records[i].substr(11, 3);        // 통과 타입 부분 추출

        // carNumbers에 현재 차례 차량 번호 없으면
        if (find(carNumbers.begin(), carNumbers.end(), numSubStr) == carNumbers.end())
        {
            // 따로 마련된 vector에 차량 번호 및 입차 시간 저장
            carNumbers.push_back(numSubStr);
            inTime.push_back(pii(hourSubStr, minSubStr));
            totalData.push_back(tsiib(numSubStr, 0, 0, false));
        }
        // 이미 들어왔던 번호의 차량이면
        else
        {
            // iterator끼리 빼면 두 iterator 사이의 거리(distance)가 반환 == 찾는 원소의 인덱스
            int index = find(carNumbers.begin(), carNumbers.end(), numSubStr) - carNumbers.begin();
            
            // IN이면 입차 시간 갱신
            if (passType == "IN")
            {
                inTime[index] = pii(hourSubStr, minSubStr);
                get<3>(totalData[index]) = false;   // 출차 안 했음 표시
            }
                
            // OUT이면 출차 시간 - 입차 시간 해서 시간 누적
            else
            {
                int totalTime = get<1>(totalData[index]); // 이전에 저장되어있던 총 누적 시간
                // 이전 누적 시간에 현재 (출차시간 - 입차시간) 누적 및 출차 표시
                totalData[index] = tsiib(numSubStr, totalTime + ((hourSubStr - get<0>(inTime[index])) * 60) + minSubStr - get<1>(inTime[index]), 0, true);  
            }
        }
    }

    // 마지막으로 출차 안 한 차 없는지 확인해서 있으면 최종 출차 23:59로 처리 및 요금 계산
    int totalDataLen = totalData.size();
    for (int i = 0; i < totalDataLen; i++)
    {
        if(!get<3>(totalData[i]))
            get<1>(totalData[i]) += ((23 - get<0>(inTime[i])) * 60 + 59 - get<1>(inTime[i]));
        
        // 기본 시간보다 적게 있었으면 기본 요금만 부과, 아니면 기본 요금 + 단위 요금 부과
        if (get<1>(totalData[i]) < fees[0])
            get<2>(totalData[i]) = fees[1];
        else
            get<2>(totalData[i]) = fees[1] + ceil((get<1>(totalData[i]) - fees[0]) / (float)fees[2]) * fees[3];
    
    }

    // 차량 번호 오름차순으로 totalData 벡터 정렬
    sort(totalData.begin(), totalData.end(), Compare); 

    // result에 차례대로 차량 별 요금 삽입
    for (int i = 0; i < totalDataLen; i++)
    {
        result.push_back(get<2>(totalData[i]));
        cout << result[i] << endl;
    }

    return result;
}
profile
게임 클라이언트 개발자 지망생의 TIL

0개의 댓글