알고리즘🅰/프로그래머스

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

개발조각 2022. 4. 22. 13:45
728x90
반응형

1번 문제는 어렵다기보다는 코드가 길어져서 제 머릿속도 복잡해지는 그런 문제였습니다.

실상은 단순 주차 요금 계산 문제에요.😉

 

문제가 너무 길어서 더이상 다 안 붙였습니다.

 

문제가 길어서 헉!!!😲 하겠지만 단순 주차요금 계산이라

어떠한 차량번호가 입차, 출고한 사이의 시간(몇 분동 안 있었는지)을 구하고 그 시간을 토대로 주차요금을 구하면 됩니다.


주의할 점

1.result에 담을 주차요금은 차량번호의 오름차순으로 넣어야 됩니다.

5961, 0000, 0148 이렇게 3개의 차량번호가 있으면 result에는 아래와 같이 담아야 된다.

  • result = [0000의 주차요금, 0148의 주차요금, 5961 주차요금]

 

2. 어떤 차량이 입차 된 후에 출차된 내역이 없다면, 23:59에 출차된 것으로 간주한다.

 

3. 특정 차량이 입차, 출고를 두 번 하면 각각의 주차요금을 구하고 더하는 게 아니라 

그동안 입차, 출고한 시간을 다 더해서(총 몇 분 동안 있는지 다 더한 후) 주차요금을 구한다.

[ '06:00', '0000', 'IN' ], [ '06:34', '0000', 'OUT' ],
[ '18:59', '0000', 'IN' ], [ '23:59', '0000', 'OUT' ],

34 + 300 = 334

  • 334분에서의 주차요금을 구해야 된다.

 

4. 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림 합니다.

(이건 당연한 사실이라 패스합니다.)


해결방안

function solution(fees, records) {
    var answer = [];
    let lastTime = 1439;
    let recordsArr = records.map(a => a.split(' '));
    let carNum = new Set(recordsArr.map(a => a[1]));
    carNum = [...carNum].sort((a,b)=> a-b)
    
    for(let i=0; i<carNum.length; i++){
        let cnRcd = recordsArr.filter((a)=> a[1] === carNum[i]);
        let accTime = 0;
        
        if(cnRcd.length % 2) accTime = lastTime;
        for(let j=0; j<cnRcd.length; j++){
            let time = cnRcd[j][0].substring(0, 2)/1*60 + cnRcd[j][0].substring(3)/1;
            cnRcd[j][2] === 'IN' ? accTime -= time : accTime += time;
        }
        
        let addTime = accTime - fees[0];
        let addCharge = 0;
        if(addTime > 0){
            addTime % fees[2] 
            ? addCharge = Math.ceil(addTime/fees[2]) 
            :  addCharge= addTime/fees[2];
            
            answer.push(fees[1] + addCharge*fees[3]);
        }else answer.push(fees[1]);
    }
    return answer;
}

해결방안 순서

  1. 필요한 변수 및 배열 만들기(answer, lastTime, recordsArr, carNum)
  2. recordsArr에서 해당 차량번호의 기록만 가져오기
  3. 몇 분 있었는지 총합 구하기
  4. fees와 accTime을 조합해서 주차요금 구하기

 

 

 

1단계. 필요한 변수 및 배열 만들기(answer, lastTime, recordsArr, carNum)

var answer = [];
let lastTime = 1439;
let recordsArr = records.map(a => a.split(' '));
let carNum = new Set(recordsArr.map(a => a[1]));
carNum = [...carNum].sort((a,b)=> a-b)
  • answer : 해당 차량의 주차요금을 담을 배열
  • lastTime : 만약에 출차된 내역이 없을 경우를 대비해서 23:59을 분(23*60 + 59 = 1439)으로 바꾼 값
  • recordsArr : records배열에서 "시각 차량번호 내역"을 뽑아 쓰기 불편해서 2차원 배열로 바꾸어주었습니다.
  • carNum  :  차량번호의 오름차순을 담은 배열(answer배열에 주차요금은 차량번호의 오름차순으로 담아주어야 돼서)
테스트 1
recordsArr = [
[ '05:34', '5961', 'IN' ],
[ '06:00', '0000', 'IN' ],
[ '06:34', '0000', 'OUT' ],
[ '07:59', '5961', 'OUT' ],
[ '07:59', '0148', 'IN' ],
[ '18:59', '0000', 'IN' ],
[ '19:09', '0148', 'OUT' ],
[ '22:59', '5961', 'IN' ],
[ '23:00', '5961', 'OUT' ]
]
carNum = [ '0000', '0148', '5961' ]


테스트 2
recordsArr = [
[ '16:00', '3961', 'IN' ],
[ '16:00', '0202', 'IN' ],
[ '18:00', '3961', 'OUT' ],
[ '18:00', '0202', 'OUT' ],
[ '23:58', '3961', 'IN' ]
]
carNum  = [ '0202', '3961' ]

테스트 3
recordsArr = [ [ '00:00', '1234', 'IN' ] ]
carNum =[ '1234' ]

 

 

 

2단계부터는 for문에서 진행됩니다.

2단계. recordsArr에서 해당 차량번호의 기록만 가져오기

let cnRcd = recordsArr.filter((a)=> a[1] === carNum[i]);

filter을 이용해서 recordsArr에서 해당 차량번호의 기록만 추출했습니다.

테스트 1
i=0
carNum = [ [ '06:00', '0000', 'IN' ], [ '06:34', '0000', 'OUT' ], [ '18:59', '0000', 'IN' ] ]
i=1
carNum = [ [ '07:59', '0148', 'IN' ], [ '19:09', '0148', 'OUT' ] ]
i=2
carNum= [ [ '05:34', '5961', 'IN' ], [ '07:59', '5961', 'OUT' ], [ '22:59', '5961', 'IN' ], [ '23:00', '5961', 'OUT' ] ]

테스트 2
i=0
carNum = [ [ '16:00', '0202', 'IN' ], [ '18:00', '0202', 'OUT' ] ]
i=1
carNum = [ [ '16:00', '3961', 'IN' ], [ '18:00', '3961', 'OUT' ], [ '23:58', '3961', 'IN' ]]

테스트 3
i=0
carNum = [ [ '00:00', '1234', 'IN' ] ]

 

 

 

3단계. 몇 분 있었는지 총합 구하기

let accTime = 0;
        
if(cnRcd.length % 2) accTime = lastTime;
for(let j=0; j<cnRcd.length; j++){
    let time = cnRcd[j][0].substring(0, 2)/1*60 + cnRcd[j][0].substring(3)/1;
    cnRcd[j][2] === 'IN' ? accTime -= time : accTime += time;
}
  • accTime : 몇 분동안 주차했는지
  • time : 해당 시간을 분으로 바꾸기

 

몇분 있었는지 구하기 위해 해당 시간을 분으로 바꾸고 IN이면 빼기(-)를 해주고 OUT이면 더하기(+)를 해주었습니다.

 

[ '06:00', '0000', 'IN' ], [ '06:34', '0000', 'OUT' ],
[ '18:59', '0000', 'IN' ], [ '23:59', '0000', 'OUT' ],

이렇게 차량번호 0000의 기록이 4개가 있다고 하면 이 4 기록의 분은

  • 6*60 = 360(IN)
  • 6*60+34 = 394(OUT)
  • 18*60+59 = 1139(IN)
  • 23*60+59 = 1439(OUT)

이렇게 됩니다. 

 

IN이면 빼기(-)를 해주고 OUT이면 더하기(+)를 해주면

  • -360 +394 -1139 +1439 = 334

이렇게 됩니다.

3단계에서는 위의 과정을 코드로 적었습니다.

 

if(cnRcd.length % 2) accTime = lastTime;

제한 사항에서 "어떤 차량이 입차 된 후에 출차된 내역이 없다면, 23:59에 출차된 것으로 간주한다."는 말이 있습니다.

그래서 1단계에서 미리 lastTime을 만들어 두었습니다.

만약 어떤 차량이 입차된 후에 출차된 내역이 없을 경우는 cnRcd배열의 길이가 홀수이고 OUT기록 하나가 없다는 말입니다.

그래서 cnRcd.length가 홀수일 경우 accTime = lastTime;을 해주면 됩니다.

 

for(let j=0; j<cnRcd.length; j++){
    let time = cnRcd[j][0].substring(0, 2)/1*60 + cnRcd[j][0].substring(3)/1;
    cnRcd[j][2] === 'IN' ? accTime -= time : accTime += time;
}

위 코드에서 미리 어떤 차량이 입차된 후에 출차된 내역이 없을 경우에 대해서는 해결을 했으니

cnRcd에 있는 기록을 IN이면 빼주고 OUT이면 더해주면 됩니다.

 

[ '06:34', '0000', 'OUT' ]에서 '06:34' -> 340으로 바꾸는 방법

  • cnRcd배열에서 시간만 추출 : cnRcd[j][0] -> '06:34'
  • '06:34'에서 시('06')만 추출하는 방법 : cnRcd[j][0].substring(0, 2) -> '06'
  • '06:34'에서 분('34')만 추출하는 방법 : cnRcd[j][0].substring(3) -> '34'
  • '06:34'에서 시('06')만 추출하고 그 시('06')를 숫자분으로 바꾸는 방법  : cnRcd[j][0].substring(0, 2)/1*60 -> 300
  • '06:34'에서 분('34')만 추출하고 숫자로 바꾸는 방법 : cnRcd[j][0].substring(3)/1 -> 34
테스트 1
i=0
accTime = 334
i=1
accTime = 670
i=2
accTime = 146

테스트 2
i=0
accTime = 120
i=1
accTime = 121

테스트 3
i=0
accTime = 1439

 

 

 

4단계. fees와 accTime을 조합해서 주차요금 구하기

let addTime = accTime - fees[0];
let addCharge = 0;
if(addTime > 0){
    addTime % fees[2] 
    ? addCharge = Math.ceil(addTime/fees[2]) 
    :  addCharge= addTime/fees[2];

    answer.push(fees[1] + addCharge*fees[3]);
}else answer.push(fees[1]);
  • addTime : 주차한 시간 - 기본시간(추가 요금이 붙을 시간)
  • addCharge : 추가요금이 붙을 시간 / 단위 시간

 

let addTime = accTime - fees[0];

if(addTime > 0){
}else answer.push(fees[1]);

먼저 추가 요금을 구하기 전 추가 요금이 붙는지 안 붙는지부터 알아야 됩니다.

추가 요금을 붙을 필요가 없으면 기본요금만 추출하면 됩니다.

 

 

if(addTime > 0){
    addTime % fees[2] 
    ? addCharge = Math.ceil(addTime/fees[2]) 
    :  addCharge= addTime/fees[2];

    answer.push(fees[1] + addCharge*fees[3]);
}

이제 추가 요금이 붙을 경우에 실행할 코드를 작성하면 끝납니다.

 

여기서는 "초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림 합니다."를 확인하면 됩니다.

  • addTime % fees[2] : 초과한 시간이 단위 시간으로 나누어 떨어지지 않는지
  • addCharge = Math.ceil(addTime/fees[2]) : 나누어 떨어지지 않을 경우 addTime/fees[2]에서 올림해주고 addCharge에 담아주기
  • addCharge= addTime/fees[2] : 나누어 떨어질 경우 addTime/fees[2]를 addCharge에 담아주기
  •  answer.push(fees[1] + addCharge*fees[3]); : answer에 주차 요금을 담아주면 됩니다.

프로그래머스 주차 요금 계산 해결방안 설명은 여기까지입니다.

728x90
반응형