import random
import pandas as pd
import seaborn as sns
from collections import Counter
input = [2, 3]     
simulations = []
def inputData(y):       #makes the input list which we'll compare to simulated results
    global input
    remain = y
    for i in range(len(input)):
        remain = remain - (len(input)+1-i) * input[i]
    input.append(remain)
def simulate(y, z):     #refreshes y times from a pool of size z / returns one input data format
    global simulations
    global list
    list = []
    for i in range(y):
        p = random.randint(1, z)
        list.append(p)
    freq = Counter(list)
    df = pd.DataFrame.from_dict(freq, orient='index')
    c = Counter(df[0])
    c = pd.DataFrame.from_dict(c, orient='index').sort_index(axis=0, ascending = False)
    c = c[0].to_list()
    simulations.append(c)
def prevalence(x, y, z): #runs x simulations of y refreshes from a pool of z objects
    global prev
    simulations.clear()
    for i in range(x):
        simulate(y,z)
    prev = (simulations.count(input)/x)
    return(prev)
def runthru(): #runs through all possible values in increments of the range incrents and graphs results
    X = []
    y = []
    global simulations
    for i in range(500, 1500, 50):
        simulations.clear()
        x = prevalence(1000000, 100, i)
        print(i, prev)
        X.append(i)
        y.append(prev)
    d = {'X': X, 'y': y}   
    df = pd.DataFrame(data = d)
    sns.barplot(data=df, x="X", y="y")
def runagain(p, k): #recursive search function
    global int
    running = True
    while running == True:
        x1 = prevalence(k, 100, int)
        x2 = prevalence(k, 100, int-p)
        x3 = prevalence(k, 100, int+p)
        print('x1', x1, 'x2', x2, 'x3', x3)
        if x2 < x1 < x3:
            int = int+p
        if x2 > x1 > x3:
            int = int-p
        if x3 > x2 > x1:
            int = int+p
        if x2 < x1 and x3 < x1:
            print(int, 'is optimal at a precision of', p, '!')
            running = False
            if p/2 > 1:
                p = round(p/2)
                runagain(p, k)
            else: 
                (print(int, 'is globally optimal!'))
        print(int)
def runsmart(p, k): #main search function, 
    global int
    inputData(100)
    running = True
    int = random.randint(1, 2000)
    print(int)
    while running == True:
        x1 = prevalence(k, 100, int)
        x2 = prevalence(k, 100, int-p)
        x3 = prevalence(k, 100, int+p)
        print('x1', x1, 'x2', x2, 'x3', x3)
        if x2 < x1 < x3 or x3 > x2 > x1:
            int = int+p
        if x2 > x1 > x3:
            int = int-p
        if x1 == x2 == x3 == 0.0:
            int = random.randint(1, 2000)
        if x2 < x1 and x3 < x1:
            print(int, 'is optimal at a precision of', p, '!')
            running = False
            if p/2 > 1:
                p = round(p/2)
                runagain(p, k)
        print(int)
    
runsmart(300, 100000)