Build a Weighted Lottery Function in JavaScript
Welcome to this javascript coding exercise where we're going to build out a weighted lottery function. This is going to be one of the more nontrivial exercises that I put together for all of the different javascript programs that I have.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Now, the main reason is that in order to build this out successfully you need to work with a number of different skill sets on the javascript side, and so I wanted to give you that warning.

I will give you some hints before I let you go to go build this out, to tell you a few of the things that you may or may not be aware of just so that you don't stumble blindly through it, and if you do not successfully do this one before watching the solution that's perfectly fine.

This one took me a little while to build out the right solution just by myself, so you are in good company if you feel that this is challenging.

Before we go into some of those hints, let's take a high-level view of what we need to happen.

So imagine that you are hired for some type of gaming system, and it's a system that needs to work with random values, like a slot machine, where you need it to have a sense of randomness, but you don't want it to be completely random because at the end of the day if a slot machine at a casino was truly random all of the casinos would be out of business.

I hate to tell you that but that is the way those types of games work. There's a reason why they say the house always wins, it's because the house has all the weights in their favor. What we're going to do is we're going to act like we were asked to build out this type of system.

Whenever I have a system, especially a challenging one, I try to nail it down to the inputs and the outputs, so let's start there. Let's say that we've been given a set of weights, and so the weights are going to be stored inside of an object.

const weights = {
    winning: 1,
    losing: 1000
}

weightedLottery(weights)

The expected behavior for this kind of game would be is that if you played this a thousand times you should have winning come up once, and you should have losing pop up a thousand times. So that's the way the weight should work.

Now, you're not limited though to just two items. Let's change this to use colors instead.

const weights = {
    green: 1,
    yellow: 2,
    red: 3
}

weightedLottery(weights)

The object needs to be flexible enough that you could put in two weights or you could put in a thousand weights and the expected behavior should still work. The value we're looking to have returned here should be whatever the name of the key is and the larger the value it has, the more times it should appear.

const weights = {
    // KEY ----> green: 1, <---- VALUE
}

That's what we're going to build. Now I'll give you some hints. Here are a few things that, if you haven't ever worked with before that might be good to look up the documentation for.

// Object.keys
// bitwise operators

Now, I can't really tell you exactly how they're going to be used because if I did then it would kind of give away too much of the solution. But these are the only two functions and processes that are not really covered in intermediate JavaScript programs

I definitely recommend that you look those up. Now, my biggest hint would be to do what I did when I was building out my own solution and take it step-by-step. So think of the easiest solution possible and just build that out layer by layer.

Good luck with this, because this one is definitely on the challenging side, so I wish you the best and then pause the video right now and try out your solution. Then we'll come back and you'll see what I put together.


Great job if you went through that, whether you built out the solution or if you tried to do it, that was definitely something that was more challenging. Let's go and let's see how I personally built this one out.

I first created a weightedLottery function and it's going to take in an object as the argument and I made it into an arrow function.

const weightedLottery = weights => {

}

const weights = {
    green: 1,
    yellow: 2,
    red: 3
}

weightedLottery(weights)

Next, I knew that I needed a way of keeping track of the weights, and I want to show you my thought process as I was building this because if you were asked to do something like this in a coding interview situation, this may seem a little bit intimidating or scary.

Now, what I did was I started by just writing some comments to get it all written down.

const weightedLottery = weights => {
    // keep track of your  weights
    //
}

const weights = {
    green: 1,
    yellow: 2,
    red: 3
}

weightedLottery(weights)

I thought you know what I could do is if I just added up each of those values and created some type of data collection.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
}

Well, if I had an array like this, then this would be dynamic since it could take any number of those key-value pairs. When I was thinking through the solution for this, I thought of the game Scrabble.

In Scrabble you have this randomization process because you take all of the letters all and you put them in a bag, then you shake up the bag and then you pull the letters out. Well, I thought, what if I could do that.

What if I could grab each one of those key-value pairs and then however many times the key appeared for green, or yellow or red, I want green to show up one time, Then have yellow show up twice and then have red show up three times. That led me to write my very first line of code.

And keep in mind that before I tried to write anything, I walked through what the end result was supposed to be, which helped me to know that if I could create this container and store all of the words in it then I could have keep track of them with their respective weights.

This would be a way that I could have part of my solution. So I started off by creating a container array. And I used a let variable for it.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
    let containerArray = [];

    Object.keys(weights).forEach(key =>(

    ))
}

Next, I knew I needed to have a second loop because what I wanted to do is to create and keep track of each one of the items and add them to our container array. So what I could do is write a second loop inside this function.

Here is one of the rare times I'm going to use a traditional for loop.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
    let containerArray = [];

    Object.keys(weights).forEach(key =>(
        for (let i = 0; i < weights[key]; i++) {
            containerArray.push(key);
        }
    ))

    return containerArray;
}

Now we have the first implementation of what we need. So notice what's going on here as we're iterating through. The objects and keys are in our object, and our function iterates three times, but if there were 20 weights it would iterate 20 times, and then each time you go inside.

So the first time it's going to go in it's going say okay, this time the key is green and what this for loop does, is it says that I want you for however many times there are in the value, so in this case when I use weights and then use the bracket syntax.

So for the first time that this goes through it's almost like I'm just saying variable i is less than one and it's going to iterate and it's going to give us that behavior. But we want it to be dynamic so sane. However many times the value is there.

I want you to iterate each one of those items and as you do I want you to add that keys' name into the container array and so that gives us exactly what we want. So we're almost there.

Even though this is a very challenging kind of project it doesn't take a ton of code to actually build it out, it just takes walking through the right steps. So now we're at the stage where we need to create the process of randomly going in and picking out a random sample from this array.

Now, we're creating the process where our hand goes in and it picks a random sample out. Well, there are a number of ways to do that. And if you went through this you may have done something like created another loop and that's perfectly fine if you did that.

But what I want to show you is an even faster, more performance way of doing it, which is to use the bracket syntax.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
    let containerArray = [];

    Object.keys(weights).forEach(key =>(
        for (let i = 0; i < weights[key]; i++) {
            containerArray.push(key);
        }
    ))

    return containerArray[Math.random() * containerArray.length];
}

Now, this is almost where we need it to be but we're missing something. This is where I also mentioned how looking up the bitwise operators would help.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
    let containerArray = [];

    Object.keys(weights).forEach(key =>(
        for (let i = 0; i < weights[key]; i++) {
            containerArray.push(key);
        }
    ))

    return containerArray[(Math.random() * containerArray.length) | 0];
}

This is what is called bitwise OR and what this is going to do is if it finds the wrong value here then bitwise OR is going to say okay if not then return 0. Now, there can be an entire chapter of a book dedicated to bitwise operators but we won't go into a ton of detail here, just know that this is required in order to build out this proper random sampling.

Now the cool thing about this is if you run this a thousand times then you're going to get a weighted set of results and let's test that out of a little bit more right here so I'm going to actually get rid of these weights here. And now let's go back to our first example.

const weightedLottery = weights => {
    // keep track of your  weights
    // ['green', 'yellow', 'yellow', 'red', 'red', 'red']
    let containerArray = [];

    Object.keys(weights).forEach(key =>{
        for (let i = 0; i < weights[key]; i++) {
            containerArray.push(key);
        }
    })

    return containerArray[(Math.random() * containerArray.length) | 0];
}

const weights = {
    winning: 1,
    losing: 1000
}

weightedLottery(weights)

If you run this a thousand times you should get losing just about every time and winning should only pop up once.

So in review, great job if you went through this. This was definitely more on the challenging and advanced side of JavaScript programming but hopefully, you got quite a bit out of it. You learned how to iterate over an object which is something that you'll need to do quite often.

We also learned a little bit about bitwise operators how and how you can use them to work with a conditional OR all on one line, and you did all of it in under 20 minutes.

So great job if you went through that. I definitely recommend if you need it to go through it again play with some of these values up until it starts to really solidify in your mind. I can promise you if you can do these types of coding exercises you're going to be able to handle pretty much anything they throw at you in a coding exercise or whenever you're tasked with a challenging project or algorithm.

Resources