Using Python To Evaluate Lil John’s “Turn Down For What”

Written by ethan.jarrell | Published 2018/12/14
Tech Story Tags: programming | python | data-science | turn-down-for-what | lil-john

TLDRvia the TL;DR App

turn down for what?

I recently listened to the timeless classic “Turn Down for What”, by Lil John and DJ Snake. In this masterpiece, they ask a question, which I set out to solve programmatically using Python. The question is “Turn Down For what?”. In solving this puzzle, I will also be going over how to utilize the following concepts in Python:

  1. While loop

3. Do While loop (emulated in Python)

4. Conditional Statements

5. Variables

6. JSON Data

7. Data Modeling and Simulation

Before we get into the code, let’s take a look at the lyrics to see how we might approach the problem:

Fire up that loudAnother round of shots

Turn down for what?Turn down for what?Turn down for what?Turn down for what?Turn down for what?

The first obvious question here is, what is the meaning of “Turn Down for What?”. According to Quora.com:

"Turn up" means to drink, party, dance and possibly do drugs. The opposite (stop partying and sober up) is to "turn down." When Lil Jon says the phrase in the song, he is telling listeners there is no reason to stop partying.

So, what we want to solve here is the following: Would there be a reason to turn down? And if so, when would that condition be met?

While Loops vs. Do While Loops

If we analyze the first line of the lyrics, it appears that Lil John and DJ Snake are telling us that when the party begins, all party patrons will be required to have another round of shots. Also, the Loud will be fired up. In essence, they are executing some actions, followed by a conditional statement, “turn down for what?”. This is the basic flow of a Do While loop that are common in many C based languages. The general syntax for a Do While loop is as follows:

Basically, a Do While loop differs from other common loops in that it executes code before checking for a condition. This means that the code to be executed will always be executed at least once. Let’s compare that to a typical While loop:

Here, the condition is first, followed by the code to be executed. If the condition is met when the code first runs, then the code will never be executed. Let’s look again at how this might play out in Turn Down For What:

Lil John’s initial statement seems to be a Do While loop since the code to be executed comes before the conditional statement, as transposed here into Pseudo-Code. Suppose the condition, or reason to turn down was that it wasn’t past 9:00pm. If this section of code had been run at 9:01pm, then at least everyone would have had a round of shots, and everyone would have been able to party briefly. However, in the same scenario, if Lil John had written the conditional before the code to be executed:

Then no shots would have been taken and the party would never have been started. In this case, Lil John was smart to write it in such a way, so that no matter what, even if the condition evaluates to True, everyone still gets to party at least once.

Making a Do While Loop in Python

While many C based languages have a native way to write a Do While loop, Python does not. In order to achieve the same result, we’ll need to use a slightly different syntax than the Pseudo Code above to emulate a Do While loop in Python.

Here, we’ve emulated the Do While loop in Python. while True simply allows the loop to continue forever. If we had no condition after this, the loop would run indefinitely. However, we have included a conditional statement inside the loop, and if that condition is met, we break the loop, short circuiting it. In the end, the code will always execute at least once, followed by it’s possible termination in the conditional statement.

Defining Variables

Python is dynamically typed, which means that you don’t have to declare what type each variable is. In Python, variables are a storage placeholder for texts and numbers. It must have a name so that you are able to find it again. The variable is always assigned with the equal sign, followed by the value of the variable.

Booleans

Boolean values are the two constant objects False and True.

They are used to represent truth values (other values can also be consideredfalse or true).

In numeric contexts (for example, when used as the argument to anarithmetic operator), they behave like the integers 0 and 1, respectively.

The built-in function bool() can be used to cast any value to a Boolean,if the value can be interpreted as a truth value

They are written as False and True, respectively.

Numbers

Numeric variables in Python are used to store numbers. Numbers are usually stored as integers, floating-point values, or complex numbers, depending on the requirements of the program.

In Lil John’s lyrics, he doesn’t explicitly define the variables, but it is implied. We can’t be sure what the starting values are for Loud, but only that it would be fired up. We also don’t know how much ‘fired upincrements the value of Loud, or if it is a boolean that is either on or off (True or False).

Incrementing a Numeric Variable

If the variable Loud is a numerical value to be incremented, it might look something like this:

Setting a Boolean Variable

However, if the variable Loud is a boolean, it could be written like this:

Before we make a decision on how to handle the variable Loud, it’s important to understand what exactly Loud is. According to Urban Dictionary:

1. (Adjective) used to describe marijuana of very high quality; very strong weed.

2. (Adjective) used to describe something (or someone) that is of high quality; very good; awesome; sick (slang); cool; dope(slang); amazing.

Based on this, it would appear that Lil John intends to use Loud in the former context. With that in mind, it would probably make more sense to treat it as an incremented numerical value rather than a boolean. If we treated it as a boolean, and set the value to False, that would indicate that there was no Loud being fired up currently. Conversely, if we use the value as a number, we can increment it, indicating that more Loud is constantly being fired up.

We can also probably assume that the same is true for another round of shots. Shots would need to be a numerical value which would store the number of rounds of shots. The format for this would look pretty similar to our previous example:

Now that we have a rough idea of how to represent this scenario via Python, let’s compare the what we have so far:

At this point, it seems to look pretty good. We have successfully converted most of this scenario into a testable block of Python code. However, there are still a couple off issues we still have yet to resolve.

  1. What would a condition be that would end this loop? The phrase “Turn Down For What” seems to indicate that there is not a reason to turn down, and perhaps there never will be. In programming this could cause a problem because as our while loop would simply run indefinitely if no terminating conditions are ever met.
  2. It also seems confusing that in the scenario, “Turn Down for What”, or our conditional statement, is repeated 5 times. Typically, a conditional statement would only need to be executed once. To make things more simple, it is probably easiest to call this line only once instead of repeating a condition multiple times without executing any code.

In deciding the answer to our first problem, there does seem to be at least one condition that would terminate our while loop. At each iteration of the loop, each party guest will be required to have another round of shots. This means that as the party continues, guests will begin to be inebriated. At some point, if this pattern continues, all guests will become too intoxicated to party, and the party will be required to “turn down”, thus ending the while loop. With this in mind, let’s consider the following:

The average weight for a person in the United States is 180.62 lbs. Liquor (distilled spirits) is most often consumed in mixed drinks with 1.5-oz. spirits. Sometimes spirits (vodka, gin, scotch, bourbon, etc.) are mixed with water, club soda, or juice or served “straight” or “on the rocks.” No matter how spirits are consumed, a standard serving (1.5 oz.) of 80 proof (40 percent alcohol by volume) of distilled spirits has the same amount of alcohol as standard servings of beer and wine. So 1.5 oz. x 40 percent alcohol by volume = 0.6 oz. of alcohol/serving.

“BAC” is short for “blood alcohol concentration” — a measurement of how much alcohol is in a person’s blood. Generally, BAC rises as a person drinks.

A blood alcohol concentration of higher than 0.14 usually means that an individual will start to feel less euphoric and probably more unpleasant. By 0.25, most individuals would be severely impaired.

The number of shots that it would take to reach a blood alcohol concentration of 0.14 is probably around 8–10 drinks (1.5 oz each ) for a person of an average weight in the US ( 180.62 lbs ). See figure 1a.

figure 1a

Thus, we can assume that if Shots is incremented during each iteration of our while loop, by the 9th iteration, the party would start to necessarily “turn down”. Perhaps the best way to incorporate this into our code would be to set a variable called Party with a starting value of 10, and as we increment the number of drinks, we decrement the party party variable. Then if the party variable ever reaches 0, then the condition would be met and the party would turn down. However, this presents us with a problem. Consider how this would look if we graphed the party variable. See figure 1b.

figure 1b

Basically, the party would start out really fun, and decrement by a value equal to the number of shots consumed. I don’t think that this is the type of party that Lil John envisioned when he described this scenario. And this presents us with a conundrum. Lil John seems to envision a party that increases in Loud and Shots and Fun indefinitely, but obviously there will be finite limits to the amount of fun that can be had if the number of drinks consumed also increments indefinitely.

Additionally, by thinking about the problem in such a way, we are not considering other variables. For example, we are assuming that this is a closed party. In other words, if there are 20 guests at this event, the while loop begins and increments until the party ends with all 20 guests reaching a blood alcohol concentration of greater than or equal to .25. We are assuming that no new guests would arrive at the party. In reality, new guests would probably arrive later than others, meaning that not the entire group would not reach the same blood alcohol concentration at the same time.

Another factor we might want to consider is that while the party increases and gets louder, it may attract more potential guests to the party.

Let’s look at how that data might be represented visually. See figure 1c.

figure 1c

In this rough example, there are 7 people at Lil John’s party when it starts (or our while loop begins). Conversely, there are 22 people who are not currently at the party, but are within a close proximity of it. At each iteration of the while loop, the value of loud and shots are incremented and as a side effect of this, more people who are not currently in attendance, are more likely to become aware of the party. Those who join the party will be swept into our while loop, where they will be forced to enjoy another round of shots at each iteration. Let’s look at another visualization of how this may play out in our code. See figure 1d.

figure 1d

This helps us see what the relationship is between the level of noise at the party, the number of guests at the party, and the number of inebriated guests at the party. At the beginning of the party, the noise will likely not start at 0, but somewhere maybe around 50. All guests at the party will not be inebriated when the party begins. As guests begin to become inebriated, while at the same time, new guests join the party who are not yet inebriated. But we can see that eventually each of these data points will hit a plateau. Think of the data this way, we can probably make 3 safe assumptions before we move forward:

  1. The level of noise has a maximum (a stereo can only be turned up to 100%). Also, the level of noise is likely to reach it’s maximum value before all the guests arrive at the party, and also before the first guests become completely inebriated (This is mainly because the level of noise is likely to start at a high level anyway, and will reach it’s maximum sooner than later).
  2. The second data point likely to plateau would be the number of guests at the party. This data point could be based on maximum population and/or population density. This doesn’t necessarily mean that all of the population will attend the party. Rather that there is a finite number of the population that will eventually attend.
  3. The last data point to reach it’s maximum value is the number of inebriated guests at the party. Once the maximum number of possible party patrons arrive at the party, and the total guests are all completely inebriated, then the party will likely be over ( and the condition of turn down for what will return True ).

JSON Data

Because there is a variance in the way we would calculate BAC depending on the gender of the party patron, and because the weight of each party patron will vary, it would probably be best to treat the inebriation of each guest individually. A good way to do this is with JSON data. JSON stands for JavaScript Object Notation, and is a common way to store data. A standard JSON object consists of key/value pairs. Let’s take a look at how we might keep track of our guests using JSON data. Each guests JSON object might look like the following:

figure 2a

In our earlier diagram, we saw a potential scenario where there were initially 7 guests at Lil John’s party, and 22 who were not yet in attendance. If we represented this with JSON data like the one shown in figure 2a, each guest would have a data profile. The keys would provide us with meaningful data about each guest. The keys, ‘gender’, ‘genderConstant’, ‘weight’, and ‘shots consumed’ would all help us calculate the current blood alcohol content of each guest. the ‘atParty’ key would let us know if the guest is currently involved in the ‘round of shots’ during each iteration.

At each iteration of the loop if a guest’s ‘atParty’ value is set to True, and the current guest also has a blood alcohol content of lower than say, .2, then that guest’s ‘shots consumed’ value will be incremented by a value of 1, and the same guest’s ‘bac’ key will be recalculated with the new ‘shots consumed’ value.

If at any point a guests blood alcohol content is higher than .2, we can assume that the guest is too inebriated to continue drinking. Once all the guests who would attend the party have arrived at the party and each guest also has a blood alcohol content of .2, then the condition will return True, and the while loop will terminate. In order to do this, we may want to use the following code structure:

figure 2b

In the above example, out basic framework for this exercise is to define our variables first. Above are some possible starting values for each of these variables. Our function which creates a new guest will need to determine if the new guest is a male or female. To determine this, we will choose a random selection of our maleFemale array. Once the new guest has been created, we can append this new guest to our arrayOfGuests. Our other function, calculate BAC, will use the values of each current guest and calculate their current blood alcohol content. Finally, our ‘edit values of existing guest’ will add the total number of shots consumed for each guest, and then call the calculate BAC function to re-calculate the guest’s BAC.

Let’s take a look at each of these functions individually to see how they would work:

Calculating BAC:

def calculateBAC(shotsConsumed, weight, genderConstant):newBAC = shotsConsumed/(weight*genderConstant)*50return newBAC

This function will take three parameters:

  1. shots consumed
  2. weight
  3. gender constant.

The function will calculate a new blood alcohol content, and return that value.

Creating a new person:

def createNewPerson():genderConstant = 0choice = random.choice(maleFemale)sConsumed = 0weight = random.randint(115, 260)if choice == 'male':genderConstant = 0.68elif choice == 'female':genderConstant = 0.55person = {'gender': choice,'genderConstant': genderConstant,'weight': weight,'shotsConsumed': sConsumed,'bac': 0,'atParty': bool(random.getrandbits(1))}return person

Here, creating a new person will not need any arguments. It will generate a new person at random. Our maleFemale variable will probably look like this:

maleFemale = ['male', 'female']

The function starts by choosing one of the values of this array at random. Based on the value chosen, it will determine a genderConstant of either .68 or .55. Then it will choose a weight from a range of 115 to 260. Since the average human weight in the US is about 180, these values represent a wider range of possible weights for each partier. Finally, the function will build a dict, which is basically a JSON object. This JSON object will consist of the same key/value pairs we discussed earlier. Then the function will return only the JSON object that it builds.

Edit an existing person:

def editExisting(x):isAtPartyNow = bool(random.getrandbits(1))if x['atParty'] == True:newShots = x['shotsConsumed']+1x['shotsConsumed'] = newShotsx['bac'] = calculateBAC(newShots, x['weight'], x['genderConstant'])if isAtPartyNow == True:x['atParty'] = Trueif loud > 50 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueif loud > 60 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueif loud > 70 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueif loud > 80 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueif loud > 90 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Truereturn x

This function will take only one argument (the existing person). Then, it will use the keys of the person (in JSON format) to access the values associated with these keys. We also have a conditional statement here, as we will edit the guest differently depending on whether or not they are currently at the party.

If the guest is at the party already (atParty == True), we will increment the current person’s shotsConsumed by 1, and we will recalculate the current person’s blood alcohol content.

If the guest is not currently at the party, we will do a little bit more work. We will start by randomly getting another boolean value, and if it is True, we’ll reset the guest’s atParty value to True. However, if the atParty value of the guest is still false, we’ll run that code again (getting a new boolean value) for each time loud has been incremented. This fits nicely with our diagram 1c, which indicates that guests are more likely to become involved in the party as the level of noise is incremented.

Creating all guests:

for i in xrange(0, 20):person = createNewPerson()people.append(person)

This function will be a simple for loop. In the for loop, we will iterate over a range. This range represents the total number of guests we intend to have. In this example, we would only have a total of 20 people in our test case. Each person would be created by the function we looked at earlier, and then appended to our array of people.

Function to simulate the party:

while True:

if loud < 90:loud = loud + 10for p in people:if p['bac'] < .2 and p['atParty'] = True:editExisting(p)roundsOfShots = roundsOfShots + 1if roundsOfShots >= 10:break

This is the basic outline we looked at earlier, with a few modifications. The changes here are:

  1. The value of Loud only increments if the value is currently less than 90. Also, instead of incrementing by 1, we’re incrementing the value of Loud by 10 at each iteration.
  2. We’ve included a for loop that is nested inside the while loop. Each time the while loop runs, it then loops over all of the people at the party. If the current person in the nested loop is below .2 and the current person is also at the party, then we run the editExisting function we looked at earlier, which will increment the number of shots and re-calculate the blood alcohol content.
  3. Finally, we’ll also increment the roundsOfShots variable.
  4. In this case, we’re short circuiting the while loop when the roundsOfShots variable reaches 10. Obviously this isn’t what we want to happen in the end, but this way we can at least test the code to make sure portions of it works, and then adjust the short circuiting conditional statement later.

Let’s look at how all of the code looks together. I’ve also made some adjustments to our starting variables, and adjusted our conditional statement for short circuiting the while loop:

import randomloud = 50roundsOfShots = 0totalPeople = 300peopleAtParty = 0peopleNotAtParty = 0peopleInebriated = 0timeElapsed = 0people = []maleFemale = ['male', 'female']

def calculateBAC(shotsConsumed, weight, genderConstant):newBAC = shotsConsumed/(weight*genderConstant)return newBAC

def createNewPerson():genderConstant = 0choice = random.choice(maleFemale)sConsumed = 0weight = random.randint(115, 260)if choice == 'male':genderConstant = 0.68elif choice == 'female':genderConstant = 0.55person = {'gender': choice,'genderConstant': genderConstant,'weight': weight,'shotsConsumed': sConsumed,'bac': 0,'atParty': bool(random.getrandbits(1))}return person

def editExisting(x):isAtPartyNow = bool(random.getrandbits(1))if x['atParty'] == True:newShots = x['shotsConsumed']+1x['shotsConsumed'] = newShotsx['bac'] = calculateBAC(newShots, x['weight'], x['genderConstant'])if x['atParty'] == False:if isAtPartyNow == True:x['atParty'] = Trueif loud > 50 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueelif loud > 60 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueelif loud > 70 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueelif loud > 80 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Trueelif loud > 90 and isAtPartyNow == False:isAtPartyNow = bool(random.getrandbits(1))if isAtPartyNow == True:x['atParty'] = Truereturn x

for i in xrange(0, totalPeople):person = createNewPerson()people.append(person)

while True:timeElapsed += 10if loud <= 100:loud = loud + 10for p in people:if p['bac'] < .2 and p['atParty'] == True:editExisting(p)if p['bac'] >= .2 and p['atParty'] == True and peopleInebriated < totalPeople:peopleInebriated += 1if p['atParty'] == False:editExisting(p)roundsOfShots = roundsOfShots + 1print peopleInebriatedif peopleInebriated >= totalPeople:break

for p in people:if p['atParty'] == False:peopleNotAtParty += 1else:peopleAtParty += 1print ptotalConsumed = 1.5 * (peopleInebriated*roundsOfShots)print "Total Consumed: ", totalConsumedprint "Time Elapsed is: ", timeElapsed, " minutes"print "Total People: ", totalPeopleprint "People Inebriated: ", peopleInebriatedprint "People at the party: ", peopleAtPartyprint "People Not at the party: ", peopleNotAtPartyprint ("loud is: ", loud)print ("total rounds of shots: ", roundsOfShots)

Here, the total number of party patron has been set to a more realistic number of 300. The BAC calculation has also been modified to allow people to party harder for longer. In addition, a variable for timeElapased has been added, theorizing that the Loud would be fired up, and rounds of shots would be added approximately every 10 minutes. By these calculations, this party would last around 3 hours and 20 minutes. At this point, all of the party guests who would potentially be in range of the Loud, would also be too inebriated to continue the party. As a result, the condition to turn down would be met, and the party would end. Also interesting to note here is the totalConsumed variable, which keeps track of the total amount of consumed alcohol. Because this is based on the 1.5 oz figure we came to earlier, the total consumed is usually around 9000oz, or about 72 gallons.

In summary, Turn Down For What?

The answer seems to be after 72 gallons of alcohol has been consumed by the party patrons, if the total number of party patrons is around 300.

Hopefully this has been a fun and entertaining exercise. Feel free to share any feedback. Thanks!


Published by HackerNoon on 2018/12/14