## A Codepen coding challenge challenge

Given two strings `a` and `b` , `return true` if they are equal when both are entered into text editors. But: a `#` means a backspace character (deleting backwards), and a `%` means a delete character (deleting forwards).

### Example:

    pine####apple => apple
    %%%%pineapple => apple

This seems pretty straightforward, so let's create a function that works for the above example...

## The function

We are given the first part of the function:

    function equalWithDeletions(a, b) {
      // do something
      return a === b
    }

So now we need to work out a way to delete the characters. We can use `String.replace()` combined with some regex wizardry (regex confuses me) to delete the characters. Then we just need to loop over the string until all the deletes have been made. Which should look a little something like this:

    function equalWithDeletions(a, b) {
      let regex = /[^#]#|%[^%]/g;
      while(/#|%/.test(a)) {
        a = a.replace(regex, '')
      }
      while(/#|%/.test(b)) {
        b = b.replace(regex, '')
      }
      return a === b
    }

A quick explanation of this regex*; `/[^#]#|%[^%]/`
The bracketed part `[^#]` is a non-capturing group, which looks for anything that is NOT a #, then it looks for a # to follow that `[^#]#` , which gives us our backspace selection. The opposite order for the forwards delete is required; `%[^%]` . The `|` is an OR, so the full regex looks for a non-# followed by a # OR a % followed by a non-%.

* This regex was from Zed Dash - it was a lot nicer than mine :)

This seems easy enough, and at this point you might be thinking, sweet, DONE. But there are some edge cases this doesn't answer and we can simplify this code, as the while loop is repeated twice, which is a lil messy and can be extracted into it's own function. Nobody likes repeated code.

### Edge cases:

    #pine####apple%

What if there is a # at the beginning of the code or a % at the end? The current regex won't account for those and we don't want to ouput a string with those symbols remaining in it. We can look for something at the beginning of the code using `/^#/` , and simlarily at the end of the code using `/%$/`

So let's add those to the regex and extract that function:

    function equalWithDeletions(a, b) {
      let regex = /^#|[^#]#|%[^%]|%$/g;
      function edit(str) {
        while(/#|%/.test(str)) {
          str = str.replace(regex, '')
        }
        return str;
      }
      return edit(a) === edit(b)
    }

We're getting there, but there is one final quandary, a question as old as time (or at least since this challenge came out) and that is...

## Can a delete delete a delete?

Or in simpler terms, what happens when a forward delete meets a backspace?

### Example:

    pine%#apple => pinpple | pineapple ?

The question is do they cancel each other out, or do they ignore each other and only affect non-deletey characters. The results as shown in the example above give pretty different outputs, and with no clear indication from the challenge which one is right, this is upto the coder to decide.

In my opinion, I don't think a delete character should affect another delete character, because; `%%%%pineapple => apple` the stack of four forward deletes here, don't affect each other, so why would a backspace affect a forward delete? It's all open to interpretation and I'd be keen to know what people think.

So given my stance (and the fact I like to make things harder for myself), we have to change the function to account for this edge case. This is also a fairly simple change, and we can use what we have so far, with a slight modification, and more magical regex!

So let's start with the theory, given the scenario where a % is before a # we want to just swap them around, so `%#` becomes `#%` . We can use regex with capturing groups and then swap the groups using `String.replace()` . This looks something like this...

    str.replace(/(%)(#)/, '$2$1')

Then the last step is to add a test for this in the while loop before the current replace. So the complete function looks like:

    function equalWithDeletions(a, b) {
      let deleteChars = /^#|[^#]#|%[^%]|%$/g;
      let swapDeletes = /(%)(#)/g;
      function edit(str) {
        while(/#|%/.test(str)) {
          if (swapDeletes.test(str)) {
            str = str.replace(swapDeletes, '$2$1');
          } else {
            str = str.replace(deleteChars, '')
          }
        }
        return str;
      }
      return edit(a) === edit(b)
    }

## Final Function

I added some more test conditions to the Jest for the conditions covered in this, you can see them in the JS and the test results are below.

    const deleteSymbols = /#|%/;
    const deleteChars = /^#|[^#]#|%[^%]|%$/g;
    const swapDeletes = /(%)(#)/g;

    function equalWithDeletions(a, b) {
      function edit(str) {
        if (typeof str !== 'string') return str;
        while (deleteSymbols.test(str))
          str = swapDeletes.test(str)
              ? str.replace(swapDeletes, '$2$1')
              : str.replace(deleteChars, '');
        return str
      };
      return edit(a) === edit(b)
    }