Skip to content

Commit

Permalink
concept is more efficient
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-s-s committed Oct 25, 2017
1 parent 79d1f9a commit 62c487f
Showing 1 changed file with 206 additions and 3 deletions.
209 changes: 206 additions & 3 deletions dicetables/bestof_scratch.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dicetables import AdditiveEvents, EventsCalculations, DiceTable, Die
from dicetables import AdditiveEvents, EventsCalculations, DiceTable, Die, Modifier
from dicetables.eventsbases.integerevents import IntegerEvents
from time import clock
from itertools import product
from itertools import product, combinations, permutations, combinations_with_replacement


class BestOfCorrectButSlow(IntegerEvents):
Expand All @@ -19,6 +19,7 @@ def _create_dict(self, total, select, die_size):
exclude_index = total - select
for roll_tuple in allrolls:
key = sum(sorted(roll_tuple)[exclude_index:])
# key = sum(roll_tuple) - min(roll_tuple) only works when just removing one die.
master_dict[key] += 1
print('time', clock() - start)
return master_dict
Expand All @@ -27,19 +28,164 @@ def _create_dict(self, total, select, die_size):
def get_dict(self):
return self._dict.copy()

from bisect import bisect, insort
from functools import partial
def get_tup(input_tup, new_val):
index = bisect(input_tup, new_val)
return input_tup[:index] + (new_val, ) + input_tup[index:]

def get_tup_alt(input_tup, new_val):
lst = list(input_tup)
insort(lst, new_val)
return tuple(lst)



def gen_insort(number, size):
start = {(): 1}
for num in range(number):
new_dict = dict.fromkeys(combinations_with_replacement(range(1, size+1), num+1), 0)
for key, val in start.items():
for roll in range(1, size+1):
index = bisect(key, roll)
new_key = key[:index] + (roll,) + key[index:]
new_dict[new_key] = val + new_dict[new_key]
start = new_dict.copy()
return start


def gen_insort_alt(number, size):
keys = combinations_with_replacement(range(1, size+1), number)
return {the_key: get_count(the_key) for the_key in keys}


from math import factorial
def get_count(lst):
"""simple calculation over tuple of sorted values and possibly repeating value
to tell number of unique permutations. so get_count((1, 2, 3)) = 3!. get_count((1, 2, 2, 3, 3)) = 5!/(2!*2!)"""
answer = factorial(len(lst))
current = lst[0]
count = 0
for el in lst:
if el == current:
count += 1
else:
current = el
answer //= factorial(count)
count = 1
return answer // factorial(count)

# no good
from itertools import groupby
def get_count_alt(lst):
answer = factorial(len(lst))
for el, lst in groupby(lst):
answer //= factorial(len(list(lst)))
return answer





class BestOfExp(IntegerEvents):

def __init__(self, total, select, die_size):
self._dict = self._create_dict(total, select, die_size)

super(BestOfExp, self).__init__()

def get_dict(self):
return self._dict.copy()

def _create_dict(self, total, select, die_size):
start = clock()
select_range = range(select, select * die_size + 1)
master_dict = {key: 0 for key in select_range}
combos = gen_insort_alt(total, die_size)
rm_index = total - select
for roll_lst, num in combos.items():
key = sum(roll_lst[rm_index:])
master_dict[key] += num
new_time = clock() - start
print('exp time', new_time)
return master_dict




class BestOfExperiment(IntegerEvents):

def __init__(self, total, select, die_size):
self._dict = self._create_dict(total, select, die_size)

super(BestOfExperiment, self).__init__()

def _create_dict(self, total, select, die_size):
base_dict = dict.fromkeys(range(1, die_size+1), 1)
master = {}
for smallest in base_dict.keys():
new_dict = {key: val for key, val in base_dict.items() if key >= smallest}
base_add = AdditiveEvents.new().combine(AdditiveEvents(new_dict), total).get_dict()

to_add = {key-smallest: val for key, val in base_add.items()}
master = add_dict(master, to_add)

return master

def get_dict(self):
return self._dict.copy()



def add_dict(dict1, dict2):
out = dict1.copy()
for key, val in dict2.items():
out[key] = out.get(key, 0) + val
return out


def get_count2(lst):
"""bad idea"""
count = 0
already = []
for val in permutations(lst, len(lst)):
if val not in already:
already.append(val)
count += 1
return count








if __name__ == '__main__':
x = BestOfCorrectButSlow(4, 3, 6)
# 3D3 = {3: 1, 4: 3, 5: 6, 6: 7, 7: 6, 8: 3, 9: 1}
# best 2 of 3D3 = {2: 1, 3: 3, 4: 7, 5: 9, 6: 7}

# 2D3 = {2: 1, 3: 2, 4: 3, 5: 2, 6: 1}
# 2D2 + 2 = {4: 1, 5: 2, 6: 1}
# 2D1 + 4 = {6: 1}
# D2 + D3 + 1 = {3: 1, 4: 2, 5: 2, 6: 1}
# D2 + D1 + 3 = {5: 1, 6: 1} times two?
# D3 + D1 + 2 = {4: 1, 5: 1, 6: 1}
x = BestOfCorrectButSlow(4, 3, 8)
y = BestOfExp(4, 3, 8)

print(x.get_dict())
print(y.get_dict())
pct = EventsCalculations(x).percentage_points()
for key, val in pct:
print('{:>2}: {:>5.2f}'.format(key, val))

for key in range(3, 10): # keys in 3D3
number_of_ones = 0
for dice in range(1, 4): # 1, 2, or 3 dice containing ones
if dice + 3 * (3 - dice) >= key:
number_of_ones += 1
print('key ', key, 'ones ', number_of_ones)
# start = clock()
# master = {key: [] for key in range(3, 19)}
# other_master = {key: 0 for key in range(3, 19)}
Expand Down Expand Up @@ -77,6 +223,54 @@ def add_dict(dict1, dict2):
# for key in range(2, 13):
# print('{:>2}: {}'.format(key, other_master[key]))
# print(clock() - start)
start = clock()
for val in combinations_with_replacement([1, 2, 3, 4, 5, 6, 7, 8], 5):
get_count2(val)
new_try = clock() - start

start = clock()
x = product([1, 2, 3, 4, 5, 6, 7, 8], repeat=5)
for val in x:
sorted(val)
sum(val)
sorting = clock() - start

start = clock()
x = product([1, 2, 3, 4, 5], repeat=5)
for val in x:
min(val)
sum(val)
minning = clock() - start

print(new_try, sorting, sep='\n', end='\n\n')

import matplotlib.pyplot as plt
from itertools import cycle
colors = cycle('rbg')
for size in range(3, 10):
color = next(colors)
name = 'size: {}'.format(size)
times = []
for num in range(1, 38 - size*3):
start = clock()
to_test = gen_insort(size, num)
other = gen_insort_alt(size, num)
if to_test != other:
print(to_test, other, sep='\n', end='\n\n\n')
to_add = clock() - start
times.append(to_add)


plt.plot(times, '{}-o'.format(color), label=name)
plt.grid(True)
plt.legend()
plt.show()


# for size in range(1, 8):
# for val in combinations_with_replacement(range(1, size+1), size):
# print(val, get_count(val), sep=': ')

"""
11
12 21
Expand Down Expand Up @@ -133,5 +327,14 @@ def add_dict(dict1, dict2):
1111
1: 1, 2: 1, 3: 1,
2: 1, 3: 1, 4: 1
3: 1, 4: 1, 5: 1
4: 1, 5: 1, 6: 1
"""

0 comments on commit 62c487f

Please sign in to comment.