// Here's the explanation of the challenge -- when you're done reading it,
// click on `main.js` above to get started with the challenge!
// Getting around in a big city is no easy task! With so many options to get
// from point A to point B, it's easy to get confused. Fortunately, we can use
// code to figure out the best way to travel.
// ## Description
// In this challenge, you will write a `shortestTrip` function that receives a
// map (object) as an argument. Each key in the map is the name of a mode of
// transit between two places, and its value is an array containing the
// departure and arrival times for that mode of transit, represented as
// strings. The map represents the different modes of transit available
// between two points in a city.
// For example, if the trip can be done by taking the train, a bus, or
// walking, your function could be invoked like:
// shortestTrip({
// bus: ["09:15", "09:36"],
// train: ["09:30", "09:42"],
// walk: ["09:02", "09:40"]
// })
// Your function should return the name of the transit method in which the
// trip takes **the least time to complete** -- _not_ the transit method that
// arrives earlier, but the one in which you spend the least time travelling.
// The list of modes of transit will always contain at least one mode, and
//t he time will always be represented in the `hh:mm` format, using two
// digits for the hours and for the minutes.
// The times will never represent starting and ending on different days,
// meaning the travel times will never cross midnight. The departure time will
// always be earlier than the arrival time. No two trips will take the same
// amount of time.
/* Check out README.md for instructions! */
// Procedural-style solution
function proceduralShortestTrip(modes) {
const modeNames = Object.keys(modes)
// We'll use these variables to store the shortest travel
// mode and time as we iterate through the different modes.
let shortestMode = null;
// We initialise the `shortestTime` variable with a time
// larger that any possible travel time, so that any travel
// time we first encounter when iterating is considered
// the shortest.
let shortestTime = 24 * 60 + 1;
for (i = 0; i < modeNames.length; i++) {
const modeTimes = modes[modeNames[i]]
// Since we know the time is always of the form `hh:mm`,
// we can rely on the first two digits representing the
// hours and the last two digits representing the minutes.
const departureHours = parseInt(modeTimes[0].slice(0, 2))
const departureMinutes = parseInt(modeTimes[0].slice(-2))
// To obtain the number of minutes since the beginning of
// the day, multiply the hours by 60 and add the minutes.
const departureTime =
departureHours * 60 + departureMinutes
const arrivalHours = parseInt(modeTimes[1].slice(0, 2))
const arrivalMinutes = parseInt(modeTimes[1].slice(-2))
const arrivalTime =
arrivalHours * 60 + arrivalMinutes
// The travel time is the difference in the number
// of minutes between the arrival time and the
// departure time.
const travelTime = arrivalTime - departureTime;
if (travelTime < shortestTime) {
// If this is a shorter travel time than the
// shortest travel time we've seen so far, store
// it as the shortest travel mode and time.
shortestMode = modeNames[i]
shortestTime = travelTime
}
}
return shortestMode
}
// Functional-style solution
function functionalShortestTrip(modes) {
// Define a function that, given a time as a string
// of the form `hh:ss`, returns the number of minutes
// since the beginning of the day that it represents
const parseMinutes = (time) => {
// Split the time string by the `:` in the middle,
// parse each time as an integer, and store those as
// the "hours" and "minutes" variables.
[hours, minutes] = time.split(":")
.map((unit) => parseInt(unit))
return hours * 60 + minutes
}
// Produce an array of the keys and values of the
// `modes` object.
// (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries)
return Object.entries(modes)
// From each array of key and value, where the key
// is the mode and the value is an array containing
// the arrival and departure times, produce an object
// containing the mode and the travel time.
.map(([mode, times]) => {
// Use the function defined earlier to parse
// the minutes out of the departure and arrival
// time strings.
[departure, arrival] = times.map(parseMinutes)
return { mode, time: arrival - departure }
})
// Sort the elements of this array by their travel time
// (shorter is first) and take the first one's mode.
.sort((a, b) => a.time - b.time)[0].mode
}
for (const solution of [
proceduralShortestTrip,
functionalShortestTrip
]) {
/* Test runner (do not modify this line!) */
const expect = require("./expect")(solution)
/* Test cases (remember to add more!) */
// i walk a lonely road...
expect("walk", {
"walk": ["09:10", "10:47"]
})
// picks the shortest travel time
expect("bus", {
"walk": ["08:13", "08:53"],
"bus": ["08:45", "09:02"]
})
// your test case here!
// expect(expectedMode, modes)
}
/* Test runner (do not modify this!) */
module.exports = (run) => function expect(expected, ...inputs) {
const stringify = (value) => {
const serialised = JSON.stringify(value, undefined, 2)
|| "undefined"
const lines = serialised.split('\n')
for (i = 1; i < lines.length; i++) {
lines[i] = "\t" + lines[i]
}
return lines.join('\n')
}
const serialisedInputs = inputs
.map(stringify)
.join(", ")
const actual = run(...inputs)
if (expected !== actual) {
console.log(
` ❌ ${run.name}(${serialisedInputs})\n\n` +
`\texpected: ${stringify(expected)}\n` +
`\tbut instead got: ${stringify(actual)}\n\n`
)
} else {
console.log(
` ✅ ${run.name}(${serialisedInputs}) === ${stringify(actual)}\n`
)
}
}