Check out myGithubfor my free-to-read JavaScript Ebook that covers all the new features from ES6 to 2021. If you want find a great place for interactive tutorials, i recommendEducativewhere you can find my JavaScript course

This website contains affiliate links.

In this article we will solve together the *Pete the baker* challenge from CodeWars, you can find it at this link. The difficulty of this challenge is medium.

Let’s read the task together:

Pete likes to bake some cakes. He has some recipes and ingredients. Unfortunately, he is not good at maths. Can you help him to find out, how many cakes he could bake considering his recipes? Write a function cakes(), which takes the recipe (object) and the available ingredients (also an object) and returns the maximum number of cakes Pete can bake (integer). For simplicity, there are no units for the amounts (e.g. 1 lb of flour or 200 g of sugar are simply 1 or 200). Ingredients that are not present in the objects, can be considered as 0.

Examples: // must return 2 cakes({flour: 500, sugar: 200, eggs: 1}, {flour: 1200, sugar: 1200, eggs: 5, milk: 200}); // must return 0 cakes({apples: 3, flour: 300, sugar: 150, milk: 100, oil: 100}, {sugar: 500, flour: 2000, milk: 2000});

We can solve this problem in many ways but the logic behind it is simply to iterate over the keys in our Object, calculate for how many cakes an ingredient can be used, and then simply return the lowest number we got for any ingredient.

Let’s try to solve it using a `for..in`

loop.

function cakes(recipe, available) { let maxCakes; for(var ingredient in recipe){ } }

This is the skeleton of our loop, as you can see I’ve initialized a variable `maxCakes`

that will keep track of how many cakes we can make. Let’s continue the loop:

function cakes(recipe, available) { let maxCakes for (var ingredient in recipe) { if (available[ingredient]) { const possibleCakes = Math.floor( available[ingredient] / recipe[ingredient] || 0 ) if (!maxCakes || possibleCakes < maxCakes) { maxCakes = possibleCakes } } else { return 0 } } return maxCakes }

To recap:

- we iterate over each ingredient in the recipe
- we first check if we have that ingredient, if we don’t we return 0 as we will not be able to make any cake with a missing ingredient
- if we have the ingredient we calculate how many cakes we can create and we round it down to the lowest integer with
`Math.floor`

- if
`maxCakes`

is`undefined`

(meaning it’s the first iteration we make) or if the amount of possible cakes that this ingredient can provide us is less than the amount we calculated for another ingredient we update the value of`maxCakes`

There you have it, this is a simple solution using a `for..in`

loop, let’s try one more time with a `reduce`

method.

The logic behind this solution is the same as before, just the syntax will be maybe a bit harder to read at first but more concise.

function cakes(recipe, available) { return Object.keys(recipe).reduce(function (val, ingredient) { console.log(val) console.log(ingredient) return Infinity }, Infinity) } cakes( { flour: 500, sugar: 200, eggs: 1 }, { flour: 1200, sugar: 1200, eggs: 5, milk: 200 } )

In this implementation we are calling `reduce`

on the `Array`

of keys of our recipe `Object`

, passing `Infinity`

as the first value. We do that because we don’t know what’s gonna be the max value in any of our ingredients so we need to play safe and use that instead.

If you try running the code above you will see this output:

Infinity flour Infinity sugar Infinity eggs

We don’t want to return `Infinity`

, what we want is to return the lowest possible number of cakes possible to make, and to do that we can change our function to look like this:

function cakes(recipe, available) { return Object.keys(recipe).reduce(function (val, ingredient) { return Math.min( Math.floor(available[ingredient] / recipe[ingredient] || 0), val ) }, Infinity) } cakes( { flour: 500, sugar: 200, eggs: 1 }, { flour: 1200, sugar: 1200, eggs: 5, milk: 200 } )

What we changed is this line:

return Math.min( Math.floor(available[ingredient] / recipe[ingredient] || 0), val )

What this does is get the minimum (`Math.min`

) between the current number of cakes that we can make with this current ingredient (`Math.floor(available[ingredient] / recipe[ingredient] || 0`

) or the value returned by the previous iteration that we are passing via the `val`

variable.

At the first iteration, `val`

is `Infinity`

so any value will override it, whether it’s a positive value or just 0.

There you have it, a more concise function that does the same as the first solution we adopted.

There are many other ways of solving this problem, let me know yours in the comment.

If you liked this type of content, please let me know in the comments and I’ll create more of these.

Previous Article

JS Challenge 4: Who Likes it?Next Article

JS Challenge 6: Convert string to camel caseJS Challenge 7: Multiples of 3 or 5

October 28, 2020

1 min

JS Challenge 6: Convert string to camel case

October 25, 2020

1 min

JS Challenge 4: Who Likes it?

October 12, 2020

2 min

JS Challenge 3: Remove Zeroes

October 06, 2020

2 min

JS Challenge 2: Word Scrambles

October 01, 2020

2 min

JS Challenge 1: Simple Pig Latin

September 29, 2020

1 min