{{ message }}

Instantly share code, notes, and snippets.

Last active Sep 10, 2017
Script for calculating spotify's discover weekly probabilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 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): continue ratio = (30*scale*filtered_prob) / (y * x) res.append((ratio,x,y)) data_dict['x'].append(x) data_dict['y'].append(y) rt_to_add = ratio*2 if ratio!=1 else ratio+0.1 # scaling for scatter plot data_dict['ratio'].append(rt_to_add) res.sort(reverse=True) if prnt: for x in res: print('y: {} x: {} ratio: {:.6}'.format(x,x, x)) return res, data_dict if __name__ == "__main__": # tests() try: assert len(sys.argv)==4 n, x, y = int(sys.argv), int(sys.argv), int(sys.argv) 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!') else: print('Your error is: ', e) print('Correct syntax looks like this: "python spot.py 30 14 5"')

### tadeoos commented Feb 15, 2017 • edited

For context see my post.

## USAGE

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 spot.py 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! :)