 # Subsequence explainer

Aim of the puzzle: Create a function that determines if a string is a subsequence of an object mapped from a separate string.
Walk through of solution: The `isSubsequence()` function will serve as a helper function for a function you will write in the last puzzle in this course. For a step by step walkthrough of the solution, take a look at the lesson preceding this puzzle, ‘Updating the Word Search’.

`isSubsequence()` will take a string and a mapped object, and return `true` or `false` depending whether the string is a subsequence of the mapped object.

Let’s look at an example that checks the string `'boon'` against a mapped form of the string `'balloon'`:

``````let word = 'boon';
let mappedObject = {
b: ,
a: ,
l: [2, 3],
o: [4, 5],
n: 
}
isSubsequence(word, mappedObject)
``````

This should return `true`, because ‘boon’ is a subsequence of ‘balloon’. All of the letters in ‘boon’ appear in balloon, and are in the same order.

This puzzle may be the trickiest one in the course! Leave any questions you have below, along with screenshots of your code, and our staff can help walk you through to the solution.

Again, also take a look at the lesson preceding this puzzle, which will break down the function step by step.

Good luck, Grasshoppers!
Additional Code (hidden code that runs before the puzzle’s code):

``````let dictionaryWord = pickRandom(['lull', 'hub', 'boo', 'quack', 'balloon', 'hall']);

function findNextIndex(mappedIndices, lastMatchedIndex) {
for (let index of mappedIndices) {
if (index >= lastMatchedIndex) {
return index + 1;
}
}
return false;
};

function makeMap(string) {
let map = {};
for (let i = 0; i < string.length; i++) {
map[string[i]]
? map[string[i]].push(i)
: map[string[i]] = [i];
}
return map;
};

let stringSequence ='hullaballoo';
``````

I went back to the guide right before this and I still don’t get it

Hey there, thanks for your patience. These walkthroughs take some time to write.

This puzzle’s a tricky one, so if my explanation is unclear at all, be sure to let me know.

Let’s say we want to check if `'boo'` is a subsequence of `'balloon'`. We can tell just by looking at it that it is a subsequence because there is a `'b'` and 2 `'o'` s in both strings, and in the same order.

This function is going to do the same thing, except one of the strings is already mapped to an object. For example, the string `'balloon'` will look like: `{ b: , a: , l: [2, 3], o: [4, 5], n:  }`, showing that there is a `'b'` at index 0, an `'a'` at index `1`, etc.

The function will need to look at each letter in a string, like `'boo'`, and then look at the object to determine if each letter (1) exists and (2) is in the right order.

When the puzzle loads, it already has code that determines if each letter exists. Now we need to add new code to the function to check if each letter is in the right order.

First, we’ll need to keep track of an index number.

At the start of the function, declare a variable to store the index of the last letter checked. Because we haven’t started checking letters yet, just set it to `0` for now, like this:

``````let lastIndex = 0; // you can name the variable whatever you want.
``````

Why do we need to store this?

Let’s say we’re looking at the 2nd `'o'` in `'boo'`. In the object, we see that `'balloon'` has 2 `'o'`s that are located at index 4 and 5. We need our function to remember that the last letter checked (the 1st `'o'` in `'boo'`) was at index `4` in `'balloon'`, so it has to find a 2nd `'o'` that has an index greater than `4`.

This variable will store that index.

Next, we’ll need to program the function to check the order of the letters.

The function’s starter code has an if statement that checks if a letter in the string exists in the map object, but its code block is empty, so it doesn’t do anything if the letter is found. It looks like this:

``````if (map[letter]) {

} else {
return false
}
``````

We want to add code to that empty code block, to tell the function what to if a letter is found.

In a previous puzzle, you created the `findNextIndex()` function. We’ll use that function here to check the order of the letters.

That function will look at the array stored in the current letter (for example, the `[4, 5]` if the current letter were `'o'`) and the index of the last letter checked, and return either an index number or `false`.

``````{
b: , // findNextIndex looks in these arrays for a number that is greater than lastIndex
a: ,
l: [2, 3],
o: [4, 5],
n: 
}
``````

Let’s call the function, and store the value that it returns in the variable we declared earlier:

``````if (map[letter]) {
lastIndex = findNextIndex(map[letter], lastIndex);
} else {
return false;
}
``````

If the `findNextIndex()` function finds a valid index number, it returns that number + 1, or else returns `false`. This means we should tell the `isSubsequence()` function what to do if `findNextIndex()` returns false.

If `findNextIndex()` returns false, then we know the string is not a subsequence of the mapped object, so we can return false from the `isSubsequence()` function:

``````if (map[letter]) {
lastIndex = findNextIndex(map[letter], lastIndex);

if (lastIndex === false) {
return false;
}
} else {
return false;
}
``````

This is a tricky one to explain, so if you need any clarification, don’t hesitate to ask questions.

Hope this helps!
Ben

3 Likes

I’m sorry I’m trying to figure out how to do this part Hey there, no need to apologize!

I put that illustration in there as a reminder of what the `findNextIndex()` function is doing when you call it. You actually already coded the `findNextIndex()` function in the puzzle “In the Right Place”!

That function does all the work of looking in the arrays for a valid index.

All that’s left to do in this puzzle is to call the function here, like this:

``````if (map[letter]) {
lastIndex = findNextIndex(map[letter], lastIndex);

if (lastIndex === false) {
return false;
}
} else {
return false;
}
``````

Hope that makes sense!
Ben

Hi, I got stuck with

Hey there,

There’s a bug in the feedback logic that resulted in the wrong feedback message being shown, and also showing `null` instead of the right variable name. It’s been fixed now, and I believe it’s already been released, so you can try updating the app to get the right feedback message.

In any case, even with the bugged feedback, the puzzle will still complete with the right code. Let’s take a look at yours:

It looks like you have 2 different variables with the same name `lastIndex`. You are declaring one outside the for loop, and then declaring a separate one inside the for loop.

The for loop is looping through a string, so a better name for the 2nd variable would be something like `letter`.

Then, in the if statement, you want to see if there is a property in `map` with the same name as the letter, so you’d want to change that to `map[letter]`.

Let me know if you have any questions!
Ben

Can you show a final picture of the code?

So I’m just writing this piece of code only?

I’m going to edit that, as it’s a bit misleading. Take a look at the post that’s highlighted in yellow. That gives the full overview.

There are 3 steps:

1. You’ll start this puzzle by putting `let lastIndex = 0` at the top of the function (you can name the variable whatever you want, but that’s the name I use when I do the puzzle).

2. After that, add the `lastIndex = findNextIndex(map[letter], lastIndex)` to the if statement.

3. If that function call returns `false`, we know the word is not a subsequence, so we should return `false` from our function, like this:

``````if (map[letter]) {
lastIndex = findNextIndex(map[letter], lastIndex);

if (lastIndex === false) {
return false;
}
} else {
return false;
}
``````

Hope that helps!
Ben

1 Like

Hi,
I have a problem with this puzzle and I get stuck with it, can you help me please?
Thanks

Hey there, you’re very close! It looks like the issue is with the if else statement:

You have an if else statement inside an if statement, like this:

``````if (map[letter]) {
minIndex = findNextIndex(map[letter], minIndex);

if (minIndex === false) {
return false;
} else {
return false;
}
}
``````

What you want is an if statement inside an if else statement, like this:

``````if (map[letter]) {
minIndex = findNextIndex(map[letter], minIndex);

if (minIndex === false) {
return false;
}
} else {
return false;
}
``````

Fixing that should solve the problem.

Hope this helps!
Ben

1 Like