2
votes

The idea is to eliminate pointless travel in an array of directions:

'N' = North

'S' = South

'E' = East

'W' = West

So if we have the array ['S', 'E', 'W', 'W'], we'll want for the mapQuest function to return:

['S', 'W']

Since East and West are next to each-other, they'll cancel each-other out.

*NOTE The directions must be next to each-other in the array in order to get cancelled out.

Also, the array should continue to get reduced until the final array does not contain any opposites - i.e. it handles "complex cases":

['W', 'N', 'S', 'E', 'N']

should return

['N']

Because ['W', 'N', 'S', 'E', 'N'] => ['W', 'E', 'N'] => ['N']

Part of this challenge is that I must use the reduce method.

Based on my understanding of .reduce(), my thought is to do something like:

function mapQuest (array) {
	return array.reduce((accumulator, current, i) => {
		if ((array[i] === 'S' && array[i + 1] !== 'N' && array[i - 1] !== 'N')) {
			accumulator.push(array[i]);
		}

		if ((array[i] === 'N' && array[i + 1] !== 'S' && array[i - 1] !== 'S')) {
			accumulator.push(array[i]);
		}
		
		if ((array[i] === 'E' && array[i + 1] !== 'W' && array[i - 1] !== 'W')) {
			accumulator.push(array[i]);
		}

		if ((array[i] === 'W' && array[i + 1] !== 'E' && array[i - 1] !== 'E')) {
			accumulator.push(array[i]);
		}
		
		return accumulator;
	}, []);
}

console.log(mapQuest(['S', 'E', 'W', 'W']));

Works but doesn't pass the last test-spec - handing complex situations.

Expect ['N', 'N', 'E', 'W', 'S', 'S', 'E', 'W', 'N', 'N', 'W', 'S', 'E'] to equal ['N', 'N', 'W', 'S', 'E']

2
the check for undefined should be before checking the element. Also, match is used for matching regular expressions. For equality comparison you can use just current === 'S'. That way you can also avoid the check for undefined. - Slai
@Slai - what would it look like to check for undefined before checking the element? I tried if ((current !== undefined && current === 'S' && current[i + 1] !== 'N' || (current !== undefined && current === 'N' && current[i + 1] !== 'S'))) { accumulator.push(current); } - SpeakInCode43
no need for check for undefined. You just need return accumulator; after the if statements. Otherwise, the function returns undefined if nothing is returned, and accumulator becomes undefined for the next values. If you are not familiar with how reduce works, I would recommend starting with the basic for loops first. Also, your if statements don't seem to be handling all cases. I think you need at least two more. - Slai
@Slai I'm returning the accumulator now, and have 4 different if-statements which should be accounting for all "opposite direction scenarios". Something is still not working... - SpeakInCode43
I think you are pretty close. Some of the logical operators are wrong, and the value should be pushed only if all of the conditions are met. It should be easier with filter rather than reduce. - Slai

2 Answers

2
votes

One solution, though not very robust, is to assign the reduced array to a variable, and then reduce that array:

function mapQuest (array) {
	let first = array.reduce((accumulator, current, i) => {
		if ((array[i] === 'S' && array[i + 1] !== 'N' && array[i - 1] !== 'N')) {
			accumulator.push(array[i]);
		}

		if ((array[i] === 'N' && array[i + 1] !== 'S' && array[i - 1] !== 'S')) {
			accumulator.push(array[i]);
		}
		
		if ((array[i] === 'E' && array[i + 1] !== 'W' && array[i - 1] !== 'W')) {
			accumulator.push(array[i]);
		}

		if ((array[i]=== 'W' && array[i + 1] !== 'E' && array[i - 1] !== 'E')) {
			accumulator.push(array[i]);
		}
		
		return accumulator;
	}, []);
	let second = first.reduce((final, current, index) => {
		if ((first[index] === 'S' && first[index + 1] !== 'N' && first[index - 1] !== 'N')) {
			final.push(first[index]);
		}

		if ((first[index] === 'N' && first[index + 1] !== 'S' && first[index - 1] !== 'S')) {
			final.push(first[index]);
		}
		
		if ((first[index] === 'E' && first[index + 1] !== 'W' && first[index - 1] !== 'W')) {
			final.push(first[index]);
		}

		if ((first[index] === 'W' && first[index + 1] !== 'E' && first[index - 1] !== 'E')) {
			final.push(first[index]);
		}
		
		return final;
	}, []);
	return second;
}
console.log(mapQuest(['N', 'N', 'E', 'W', 'S', 'S', 'E', 'W', 'N', 'N', 'W', 'S', 'E']));

Passes all test-specs.

1
votes

I offer you this code snippet as a possible answer. Here is what I did:

  1. I used standard comparisons instead of match
  2. I added additional reduce parameters
  3. I used a recursive format to make sure the reducing happened to final answer
  4. I used a rather unconventional method of removing the pairs by marking them for delete 'X' and then filtering them out

function mapQuest(quest, last) {

  if (JSON.stringify(quest) === JSON.stringify(last)) return quest;

  var initialQuest = quest.map(x => x);

  var newest = quest.reduce((accumulator, current, index, array) => {
    if ((current === 'S' && array[index + 1] === 'N') ||
      (current === 'N' && array[index + 1] === 'S')) {
      accumulator[index] = 'X';
      accumulator[index + 1] = 'X';
    }
    if ((current === 'E' && array[index + 1] === 'W') ||
      (current === 'W' && array[index + 1] === 'E')) {
      accumulator[index] = 'X';
      accumulator[index + 1] = 'X';
    }
    return accumulator;
  }, initialQuest);

  var filtered = newest.filter(i => i !== 'X');

  return mapQuest(filtered, initialQuest);
}
var tests = [];
tests.push({
  input: ['S', 'E', 'W', 'W'],
  expected: ['S', 'W']
});
tests.push({
  input: ['W', 'N', 'S', 'E', 'N'],
  expected: ['N']
});
tests.push({
  input: ['N', 'N', 'E', 'W', 'S', 'S', 'E', 'W', 'N', 'N', 'W', 'S', 'E'],
  expected: ['N', 'N', 'W', 'S', 'E']
});

tests.forEach(test => {
  var output = mapQuest(test.input, []);
  var passed = JSON.stringify(test.expected) === JSON.stringify(output) ? 'passed' : 'failed';
  console.log(`${test.input} => ${output} : ${passed}`);
});