알고리즘 문제 풀기

프로그래머스: 주차 요금 계산 - javascript(구현 , 객체 구조 활용)

Fo_rdang 2024. 3. 21. 19:21
반응형

문제 출처 

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

 

프로그래머스

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

programmers.co.kr

문제 풀이 힌트 

01. 주어진 records 배열을 순회하면서 내가 원하는 정보의 형태로 저장할 것이다. 

=> cars라는 객체 생성 후, 차량번호key로 설정하고 으로는 "누적시간"IN일 때 임시로 시간(OUT일 땐 저장되어있는 IN 값과 시간 차이를 구하고 누적시간에 더해줄 것임)을 저장할 것.

02. 출차 하지 않은 차량이 있다면 23:59 로 누적시간을 구해줘야 한다. 

03. 내가 정리한 cars 객체로 누적시간에 따른 요금을 계산하고, 배열의 형태로 return 할 것.  

정답 풀이 코드

function solution(fees, records) {
    const cars = {}; // 주차된 차량 정보를 저장할 객체

    // 01. records 배열 순회하면서 내가 원하는 정보의 형태로 값을 저장
    records.forEach(r => {
        const [time, carNum, action] = r.split(' '); // 시간, 차량 번호, 입차/출차 여부 분리
        if (!(carNum in cars)) { //carNum을 key로 저장 
            // 차량이 객체에 없으면 초기화
            cars[carNum] = { time: 0, in: [] }; // 누적시간을 time의 값으로, IN일 때 시간을 임시로 저장할 in의 배열
        }
        if (action === 'IN') {// 입차인 경우
            const [m, s] = time.split(':');
            cars[carNum].in = [+m * 60 + +s]; // in의 값으로 임시로 시간을 저장한다. 
        } else {    // 출차인 경우
            const [m, s] = time.split(':');
            const spendTime = (+m * 60 + +s) - cars[carNum].in.shift(); //in에 저장되어있는 값을 빼서(입차시간임) 출차시간과의 차이를 구한다. 
            cars[carNum].time += spendTime; // time에 총 주차 시간 누적
        }
    });

    // 출차하지 않은 차량 체크
    Object.entries(cars).forEach(([carNum, record]) => {
        if (!record.in.length) return; // 입차 기록이 없으면 건너뜀
        record.time += 1439 - record.in.shift(); // 23:59는 1439시간임 거기서 입차 시간을 빼준다.
    });

   //차 번호에 따른 누적시간이 저장되어있는 객체를 sort 함수로 낮으번호 부터 정렬한 후, 주차 요금 계산한 값을 새로운 배열을 반환할 것임
    return Object.keys(cars).sort().map(carNum => {
        if (cars[carNum].time <= fees[0]) return fees[1]; // 기본 시간 내에 주차한 경우
        const time = cars[carNum].time - fees[0]; // 초과 시간 계산
        return fees[1] + (Math.ceil(time / fees[2]) * fees[3]); // 초과 요금 계산 후 반환
    });
}

Only 문제 풀이 코드 

function solution(fees, records) {
    const cars = {};
    records.forEach(r => {
        const [time, carNum, action] = r.split(' ');
        if(!(carNum in cars)){
            cars[carNum] = {time: 0, in: []}
        }
        if(action === 'IN'){
            const [m, s] = time.split(':');
            cars[carNum].in = [+m * 60 + +s];
        }
        else {
            const [m, s] = time.split(':');
            const spendTime = (+m * 60 + +s) - cars[carNum].in.shift();
            cars[carNum].time += spendTime;
        }
    });
    // 출차안한차량 체크
    Object.entries(cars).forEach(([carNum, record]) => {
        if(!record.in.length) return;
        record.time += 1439 - record.in.shift();
    });
    return Object.keys(cars).sort().map(carNum => {
        //요금계산
        if(cars[carNum].time <= fees[0]) return fees[1];
        const time = cars[carNum].time - fees[0];
        return fees[1] + (Math.ceil(time / fees[2]) * fees[3]);

    });
}

 

알고가는 ppoint

00. Object.entires(cars)로 가져오는 [carNum, record]의 모습 

 

 

01.

02. 런타임 에러 나는 코드(내가 작성한 코드) ) 

function solution(fees, records) {
   let carRecords = new Map(); 
    let answer = []; 
    for(let i=0; i<records.length; i++){
     const [time, num, inout] = records[i].split(' '); 
        if(!carRecords.has(num)){
            carRecords.set(num, {carnum:num, total: 0, temp: 0, state: ""})
        }
        if(inout === 'IN'){
            carRecords.get(num).temp = time;
            carRecords.get(num).state = "IN";  
        }else if(inout === 'OUT'){
            carRecords.get(num).total += calculate(carRecords.get(num).temp, time); 
             carRecords.get(num).state = "OUT";  
        }
    }
 for(let record of carRecords){
   const [carnum, total, temp, state] = record
     if(record.inout === "IN"){
          carRecords.get(carnum).total += calculate(carRecords.get(num).temp, "23:59"); 
          carRecords.get(carnum).state = "OUT";  
     }
 }
    
   function calculate(entryTime, exitTime) {
    var entry = entryTime.split(":");
    var exit = exitTime.split(":");

    var entryMinutes = parseInt(entry[0]) * 60 + parseInt(entry[1]);
    var exitMinutes = parseInt(exit[0]) * 60 + parseInt(exit[1]);

    // Calculate parking time in minutes
    var parkingTime = exitMinutes - entryMinutes;

    return parkingTime;
}
    
    function calculateParking(total){
        let answer = 0; 
        if(total > fees[0]){
            answer += fees[1];
            answer += Math.ceil((total-fees[0])/fees[2]) * fees[3]; 
        }else{
            answer += fees[1]
        }
        return answer; 
    }
    //OUT으로 끝나있으면 __계산하기 IN으로 끝나있으면 out23:59 계산해주기 
    for(let record of carRecords){
        if(record.state === "OUT"){
          let totalCal = calculateParking(record.total); 
           answer.push([record.carnum, totalCal]); 
        }
    }
    
   answer = answer.sort((a[0], b[0]) => {
       return a[0]- b[0]; 
    }); 
    let answer2 = []; 
    for(let ans of answer){
        answer2.push(ans[1]); 
    }
}

 

런타임 에러를 수정하기 위해 코드를 변경하겠습니다. 먼저 맵(Map)을 순회할 때 맵의 엔트리를 가져와야 합니다. 또한, 새로운 변수에 결과를 할당하지 않았기 때문에 결과를 반환하거나 다른 용도로 사용되지 않는 문제가 있습니다. sort 부분도 에러 수정. 아래는 수정된 코드입니다.

function solution(fees, records) {
   let carRecords = new Map(); 
    let answer = []; 
    
    for(let i=0; i<records.length; i++){
     const [time, num, inout] = records[i].split(' '); 
        if(!carRecords.has(num)){
            carRecords.set(num, {carnum:num, total: 0, temp: 0, state: ""})
        }
        if(inout === 'IN'){
            carRecords.get(num).temp = time;
            carRecords.get(num).state = "IN";  
        }else if(inout === 'OUT'){
            carRecords.get(num).total += calculate(carRecords.get(num).temp, time); 
            carRecords.get(num).state = "OUT";  
        }
    }
    
 for(let record of carRecords.entries()){
   const [carnum, recordData] = record;
     if(recordData.state === "IN"){
          carRecords.get(carnum).total += calculate(carRecords.get(carnum).temp, "23:59"); 
          carRecords.get(carnum).state = "OUT";  
     }
 }
    
   function calculate(entryTime, exitTime) {
    var entry = entryTime.split(":");
    var exit = exitTime.split(":");

    var entryMinutes = parseInt(entry[0]) * 60 + parseInt(entry[1]);
    var exitMinutes = parseInt(exit[0]) * 60 + parseInt(exit[1]);

    // Calculate parking time in minutes
    var parkingTime = exitMinutes - entryMinutes;

    return parkingTime;
}
    
    function calculateParking(total){
        let answer = 0; 
        if(total > fees[0]){
            answer += fees[1];
            answer += Math.ceil((total-fees[0])/fees[2]) * fees[3]; 
        }else{
            answer += fees[1]
        }
        return answer; 
    }
    
    //OUT으로 끝나있으면 __계산하기 IN으로 끝나있으면 out23:59 계산해주기 
    for(let record of carRecords.values()){
        if(record.state === "OUT"){
          let totalCal = calculateParking(record.total); 
           answer.push([record.carnum, totalCal]); 
        }
    }
    
   answer = answer.sort((a, b) => {
       return a[0]- b[0]; 
    }); 
    
    let answer2 = []; 
    for(let ans of answer){
        answer2.push(ans[1]); 
    }
    return answer2; 
}
반응형