[프로그래머스 lev3/JS] [1차] 셔틀버스

woolee의 기록보관소·2023년 2월 5일
0

알고리즘 문제풀이

목록 보기
157/178

문제 출처

프로그래머스 lev3 - [1차] 셔틀버스

나의 풀이 (성공)

// (1)
"시:분" 형태의 문자열로 된 timetable을 숫자로 변환한뒤, 오름차순 정렬을 진행했다.

  • 해당 오름차순 정렬의 경우 직접 로직을 구현해야 하는데, 로그를 찍어보면 알겠지만, (a,b)에서 a가 뒷 요소이고 b가 앞 요소이다. 그러므로 오름차순이 되려면 뒤에 있는 a가 앞에 있는 b보다 크면 1을 반환한다.
  • 시간 개념이므로 ":"를 기준으로 시간과 분을 구분한 뒤, 시간에 대한 오름차순 로직을 먼저 구현한다. 그리고 시간 오름차순 로직이 a==b일 때 분에 대한 오름차순 로직을 구현한다.

// (2)
주어진 버스 간격과 횟수를 통해 셔틀버스 운행시간을 배열 op로 정리했다.

// (3)
각 운행시간에 탑승할 수 있는 크루원들 목록을 list로 저리했다.
op 배열을 반복하면서 내부에서 timetable을 다시 반복하며 탑승할 수 있는 목록 list를 채워넣는다.

// (4)
문제의 조건에서 "콘"은 항상 마지막에 탈 수 있으므로, list의 가장 늦은 운행 시간만 고려하면 된다.

  • 가장 늦은 운행 시간에 목록이 꽉 차 있으면 가장 뒤에 있는 인원보다 1분 늦게 도착하면 된다.
  • 가장 늦은 운행 시간에 목록에 남는 자리가 있으면 해당 운행시간까지 도착하면 된다.

마지막으로 이렇게 구한 최종 시간을 "시:분" 형태로 다시 변환해서 정답으로 반환하면 된다.

이런 유형의 문제는 최대한 빨리 정보가 담긴 list를 만드는 게 가장 중요한 것 같다. 심지어 문제를 잘 살펴보면, 전체 list 중 일부 list만 필요한 경우 더 빠르게 답을 구할 수도 있으므로 이런 쪽으로 생각해보자.

const ascendingOrder = (target) => {
  target.sort((a,b) => {
    let ah = Number(a.split(":")[0]);let am = Number(a.split(":")[1])
    let bh = Number(b.split(":")[0]);let bm = Number(b.split(":")[1]) 
  
    if(ah > bh) return 1;
    else if(ah < bh) return -1; 
    else if(ah === bh){
      if(am > bm) return 1; 
      else if(am < bm) return -1; 
      else if(am === bm) return 0;
    }
  })

  return target 
}

function solution(n, t, m, timetable) {
  const len = timetable.length
  // (1)
  timetable = ascendingOrder(timetable)
  
  // (2)
  let op = Array.from({length: n}, (_,i) => 1*60*9 + i*t)

  // (3)
  let list = {}
  let check = Array.from({length: timetable.length}, () => false)

  op.map(v => {
    list[v] = []

    timetable.map((time,i) => {
      
      let ch = Number(time.split(":")[0])
      let cm = Number(time.split(":")[1])
      let curTime = (ch*60) + cm
      
      if(
        check[i] == false && 
        v >= curTime && 
        list[v].length < m
      ){
        check[i]=true 
        list[v].push(curTime)
      }
    })
  })

  // (4)
  list = [...Object.entries(list)]
  const [strd, li] = list[list.length-1]

  if(li.length < m) {
    let [h, m] = [parseInt(strd/60), strd%60]

    if(h<10) h = String(h).padStart(2, '0')
    if(m<10) m = String(m).padStart(2, '0')

    return `${h}:${m}`
  }
  else {
    let [h, m] = [parseInt((li[li.length-1]-1)/60), (li[li.length-1]-1)%60]
    
    if(h<10) h = String(h).padStart(2, '0')
    if(m<10) m = String(m).padStart(2, '0')

    return `${h}:${m}`
  }
}

console.log(solution(1, 1, 5, ["08:00", "08:01", "08:02", "08:03"])) // "09:00"
console.log(solution(2, 10, 2, ["09:10", "09:09", "08:00"])) // "09:09"
console.log(solution(2, 1, 2, ["09:00", "09:00", "09:00", "09:00"])) // "08:59"
console.log(solution(1, 1, 5, ["00:01", "00:01", "00:01", "00:01", "00:01"])) // "00:00"
console.log(solution(1, 1, 1, ["23:59"])) // "09:00"
console.log(
  solution(10, 60, 45, ["23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59"])); // "18:00"

다른 풀이

오름차순 정렬을 이렇게 짧은 코드로 할 수 있다니.

function solution(n, t, m, timetable) {
  const getTime = time => time.substr(0, 2) * 60 + +time.substr(3);

  let answer = getTime('09:00'),
      last = (n - 1) * t + answer,
      crews = timetable.map(getTime).sort((a, b) => a - b).filter(v => v <= last);

      console.log(crews)

  for (let i = 0; i < n; i++) {
    let crewsNum = crews.filter(crew => answer >= crew).length;

    if (i === n - 1) {
      if (crewsNum >= m) answer = crews[m - 1] - 1;
    } else {
      crews.splice(0, crewsNum > m ? m : crewsNum);

      answer += t;
    }
  }

  return String(Math.floor(answer / 60)).padStart(2, '0') + ':' + String(answer % 60).padStart(2, '0');
}
profile
https://medium.com/@wooleejaan

0개의 댓글