CodeSignal challenge — is admissible overpayment

Liron Navon
Fun with algorithms

--

Today we are going to solve the test from CodeSignal challenge isAdmissibleOverpayment, we will take a look at the test and solve it step by step while explaining how such a test can be solved.

If you haven’t tried the test yet, please go to CodeSignal and try the test before reading, it will be more interesting that way, always try to solve the test before looking at the solutions 😇.

*The full solution is at the bottom of the post*

The challenge states the following:

After recently joining Instacart’s beta testing developer group, you decide to experiment with their new API. You know that the API returns item-specific display-ready strings like 10.0% higher than in-store or 5.0% lower than in-store that inform users when the price of an item is different from the one in-store. But you want to extend this functionality by giving people a better sense of how much more they will be paying for their entire shopping cart.

So we start with an empty function that receives 3 arguments:

prices — an array of numbers, which are the current prices of the given items.
notes — an array of strings which have 3 different templates: “x.x% higher than in-store”, “x.x% lower than in-store”, “Same as in-store”.
x — which is a number that tells us how much the customer is willing to pay more than the original price, so if all the discounts/price increases increase the total price by 10, and the customers indicated he’s willing to pay 5 over the price, we should return false.

function isAdmissibleOverpayment(prices, notes, x) {}

Let’s break it down

We have 3 things to solve mainly:

  1. Get the percentage change from the notes.
  2. Calculate the reverse percentage.
  3. Put it all together.

Get the percentage change from the notes.

So The first step would be to take the string and making it into a number that we can work with and write some calculations with, to define “5% lower” I will use -5, and to define “5% higher...” I will use +5.

The code for this is quite simple, we break the text into tokens separated by a space, then we know that if the first token is “Same” we can return 0, as in there is 0% increase/decrease from the original price.
Then I know that my other option is that the second token is “higher” or “lower” which I describe as +/-1.
For the last part, we will use parseFloat() which can take in a string and return a number with a decimal place.

// get the percentage from the text note
function parsePercentageFromNote(note) {
const tokens = note.split(' ');
if (tokens[0] === 'Same') {
return 0
}
const multipier = tokens[1] === 'higher' ? +1 : -1;
return multipier * parseFloat(tokens[0]);
}

Calculate the reverse percentage.

The next thing we need to be able to do is to reverse the percentage, honestly, I didn’t know how it’s done and I looked online for the formula, the pseudo code to do so is as follows, with the code under it.

For example, if you have to work out the original price of an item that is being sold at 25% off, let’s say the current price is 200.

  1. work out the current price as a percentage of the original price (100%): current price is 100% — 25% (75%)
  2. Find 1% by dividing the current price by 75 (200 / 75 =2.666 )
  3. Multiply this 1% by 100 to find the original price (266.6)
function reversePercentage(currentPrice, percentageChange) {
// (1)
const percentageFromOriginalPrice = 100 + percentageChange;
// (2)
const onePercent = currentPrice / percentageFromOriginalPrice;
// (3)
return onePercent * 100;
}

Let’s put it all together.

The last part would be to loop over the prices and calculate the sum of the differences, we can use the array reducer here, and we use our parsePercentageFromNote()andreversePercentage() functions to get the original price.
One thing to notice is the toPercision()function, which allows us to make sure all of our divisions didn’t ruin the calculations.

function isAdmissibleOverpayment(prices, notes, x) {
const difference = prices.reduce((sum, currentPrice, index) => {
const percentageChange = parsePercentageFromNote(notes[index]);
const originalPrice = reversePercentage(
currentPrice,
percentageChange
);
// difference between the prices
return sum = sum + currentPrice - originalPrice;
}, 0);
return difference.toPrecision(5) <= x;
}

And the full code with syntax highlights and full comments:

https://gist.github.com/liron-navon/4215b84a8294de39f1f06a569b5ad114

Last words

This challenge was quite nice, we had to implement some string manipulation and math, I always love thinking of this kind of problem in terms of functions, breaking them into smaller parts, and solve these parts individually.

Please clap and follow as I will publish content every couple of weeks, I truly appreciate every follower, clapper, and commenter 🙂.

--

--