Skip to content

Latest commit

 

History

History
125 lines (109 loc) · 3.18 KB

Price_Combinations.md

File metadata and controls

125 lines (109 loc) · 3.18 KB
import pandas as pd
import numpy as np
import collections
num_boards = 10
price_csv_file_path = 'price_source_data.csv'
max_price = int(num_boards * 2000)
df = pd.read_csv(price_csv_file_path)
df = df[[col for col in df.columns if 'Price' in col or 'Board' in col]].copy()
df = df[~df.isnull().any(axis=1)]
df.columns = [item for sublist in [
    ['board_{}'.format(i), 'price_{}'.format(i)] for i in range(1, num_boards + 1)
    ] for item in sublist]
for col in [c for c in df if 'price' in c]:
    df[col] = df[col].str.slice(1).str.replace(",", ".").astype(float)
    df[col] = np.where(df[col] < num_boards*2, df[col]*1000, df[col]).astype(int)
df
class Player:
    def __init__(self, name, price, board):
        self.name = name
        self.price = price
        self.board = board
# Set up "graph"
d = {}
for board in range(1, num_boards + 1):
    d[board] = collections.defaultdict(list)
    board_col = 'board_{}'.format(board)
    price_col = 'price_{}'.format(board)
    for ix, row in df[[board_col, price_col]].iterrows():
        # Rules to simplify problem
        if board == 1 or board == 10:
            if row[price_col] < 2600:
                continue
        elif board == 2 or board == 9:
            if row[price_col] < 2200:
                continue
        elif board == 3 or board == 8:
            if row[price_col] < 2100:
                continue
        else:
            if row[price_col] > 2000:
                continue
        d[board][row[price_col]].append(Player(row[board_col], row[price_col], board))
# Solve the problem
solutions = []
memo = collections.defaultdict(list)

def dfs(current_solution, board, price):
    # End condition
    if len(current_solution) == num_boards:
        if price == max_price:
            solutions.append(current_solution)
            csum = 0
            for b in range(num_boards - 1):
                csum += current_solution[b]
                memo[(b + 1, csum)].append(current_solution[b + 1:])
            return True
        return False
    
    # Use memo when possible
    if (board, price) in memo:
        for suffix in memo[(board, price)]:
            solutions.append(current_solution + suffix)
        return bool(memo[(board, price)])
    
    # Normal search
    result = False
    for new_price in d[board + 1]:
        sum_price = price + new_price
        if sum_price <= max_price:
            result = dfs(current_solution+[new_price], board + 1, price + new_price) or result
    
    # If search was unsuccessful, remember that
    if not result:
        memo[(board, price)] = []

    return result

dfs([], 0, 0)
# Get number of unique solutions
csum = 0
for i, solution in enumerate(solutions):
    unique = 1
    for j, price in enumerate(solution):
        unique *= len(d[j+1][price])
    csum += unique
csum
# Get random $20,000 team
random_team = np.random.randint(len(solutions))
print([(d[i + 1][price][0].name, d[i + 1][price][0].price/1000) 
       for i, price in enumerate(solutions[random_team])])
# Get total number of possible teams
total = 1
for b in d:
    total *= len(d[b])
total