// Here's the explanation of the challenge -- when you're done reading it,
// click on `main.js` above to get started with the challenge!
// Have you ever sat by the road and counted the cars as they pass by?
// Sometimes coincidences happen and you see three yellow cars in a row.
// Let's use code to keep track of the cars!
// ## Description
// In this challenge, you will write a `longestRun` function that receives a
// list (array) as an argument. Each element in the list is a string
// containing a color. The list represents the colors of the different cars
// you see running down the road.
// For example, if you see a red car, then two blue cars and then a yellow
// car, your function would be invoked like:
// longestRun(["red", "blue", "blue", "yellow"])
// Your function should return the name of the color that has the longest run.
// That is, the color that appears the most times in a row, next to itself,
// without other colors in between.
// For example, if you see two blue cars, then four red cars,
// and then three blue cars, the red cars are the ones that had the longest
// run, as there was a run of four red cars. Even if there were more blue
// cars _in total_, the longest **uninterrupted** run was that of the red cars.
// You can assume that the list will not be empty, and that a single color
// appears the most times in a row.
/* Check out README.md for instructions! */
// Procedural-style solution
function proceduralLongestRun(colors) {
// These variables will be used to keep track
// of the longest run of cars of the same color
// we've seen.
longestColor = null;
longestLength = 0;
// These variables will be used to keep track
// of the run of cars that we're currently seeing.
currentColor = null;
currentLength = 0;
colors.forEach((color) => {
// If the color of the current run has changed,
// save it as the new current run color and
// reset the length of the current run.
if (currentColor != color) {
currentColor = color;
currentLength = 0;
}
currentLength++;
// If the current run is longer than the
// known longest run, replace the known
// longest run and color with that of the
// current run.
if (currentLength > longestLength) {
longestLength = currentLength;
longestColor = currentColor;
}
})
return longestColor;
}
// Functional-style solution
function functionalLongestRun(colors) {
// Reduce the current list of colors into
// a list of objects representing each run,
// each containing its color and its length.
// (See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
return colors.reduce((runs, color) => {
// The current run is the last run on the
// accumulator.
let currentRun = runs[runs.length - 1]
if (!currentRun || currentRun.color != color) {
// If the current color is not that of the
// current run, add a new run to the accumulator.
return [...runs, {color, length: 1}]
} else {
// Otherwise, increase the length of the
// current run.
return [
...runs.slice(0, -1),
{color, length: currentRun.length + 1}
]
}
}, [])
// Sort the runs by length (longest first) and
// take the color of the first run.
.sort((a, b) => b.length - a.length)[0].color
}
for (const solution of [
proceduralLongestRun,
functionalLongestRun
]) {
/* Test runner (do not modify this line!) */
const expect = require("./expect")(solution)
/* Test cases (remember to add more!) */
// only one car
expect("red", ["red"])
// a long run
expect("blue", ["red", "blue", "blue", "yellow"])
// your test case here!
// expect(expectedColor, colors)
}
/* 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`
)
}
}