Skip to content

Instantly share code, notes, and snippets.

@tadeoos tadeoos/
Last active Sep 10, 2017

What would you like to do?
Script for calculating spotify's discover weekly probabilities
from __future__ import print_function, division
import itertools, sys, time
# simple factorial function
def fact(n, acc=1):
return acc if n == 0 else fact(n - 1, n * acc)
# binomial coefficient
def newton(n, k):
return 0 if k > n else fact(n) / (fact(k) * fact(n - k))
# our function!
def discover_weekly_prob(n, x, y):
if x * y < n:
return 0
sigma_sum = sum([((-1)**(i - 1)) * newton(n, i) * (((newton((n - i), y)
* fact(y) * fact(n - y)) / (fact(n)))**x) for i in range(1, n - y + 1)])
return 1 - sigma_sum
def filter_heads(p, head):
# This function flattens a tuple of tuples into list of gotten heads
# filter_heads(((1,4,2,3), (3,1,2,4)), 2) => [1,4,3,1]
return [y for x in p for y in x[:head]]
def brute_prob(n, x, y):
# all possible permutations of our initial set
permuts = [p for p in itertools.permutations(range(n))]
# list of every possible outcome of our experiment. Shrinked to y-long heads.
space = [filter_heads(prdct, y) for prdct in itertools.product(permuts, repeat=x)]
# the number of outcomes in which we got all elements of our initial set
good = sum([1 for outcome in space if len(set(outcome)) == n])
return (good / len(space))
def tests(n=5):
for x in range(1, n+1):
for h in range(1, n):
for t in range(1, 4):
w = brute_prob(x, t, h)
# if w>0:
# print('for n:{} x:{} y:{} prob is {}'.format(x,t,h,w))
assert (abs(w - discover_weekly_prob(x,t,h)) < 0.01)
print('--tests passed--')
def best_ratio(sngtme=5, hours=7, scale=1, prnt=False, tmlimit=False):
TIME_LIMIT = hours*60/sngtme
res = []
data_dict = {'x':[], 'y':[], 'ratio':[]} # dict used for creating a scatter plot
for x in range(1,31):
for y in range(1,31):
prob = discover_weekly_prob(30, x, y)
filtered_prob = 0 if prob <= 0.5 else prob
if tmlimit:
if prob == 0 or (x*y > TIME_LIMIT):
ratio = (30*scale*filtered_prob) / (y * x)
rt_to_add = ratio*2 if ratio!=1 else ratio+0.1 # scaling for scatter plot
if prnt:
for x in res:
print('y: {} x: {} ratio: {:.6}'.format(x[2],x[1], x[0]))
return res, data_dict
if __name__ == "__main__":
# tests()
assert len(sys.argv)==4
n, x, y = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
res = discover_weekly_prob(n,x,y)
ratio = (30*res) / (y * x)
print('With n={}, x={} & y={}\nThe probability of listening to every song is ~{:.0%}\nProbability/time ratio is {:.4}'.format(n,x,y,res,ratio))
except Exception as e:
print("Something went wrong...")
if len(sys.argv)!=4:
print("It looks like you haven't passed three arguments!")
elif y>n:
print('y cannot be bigger then n!')
print('Your error is: ', e)
print('Correct syntax looks like this: "python 30 14 5"')

This comment has been minimized.

Copy link
Owner Author

tadeoos commented Feb 15, 2017

For context see my post.


You need to have Python installed. Both 2.7+ and 3+ versions are supported.

If you are on mac - don't worry you should have Python 2.7 already installed. Otherwise - read this.

Once you have Python installed, download the above file. Then open Terminal and go to the folder where you saved the file.

Example for mac users:

If you downloaded the file to your "Downloads" folder, you should simply type cd ~/Downloads in Terminal and you should be good to go.

Once you're there you just run the script and pass the values for n, x and y by typing for example:

python 30 14 6

this will print the probability for n=30 x=14 and y=6 as well as it's ratio measure.

Have fun! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.