|
from sympy import * |
|
import itertools |
|
|
|
# Number of matches to play at home, before playing away |
|
HOME_MATCHES = 3 |
|
# First to this number wins. |
|
MATCHES_TO_WIN = 4 |
|
# The chances of winning away or home games |
|
# HOME_CHANCE = Rational(51/100) |
|
# AWAY_CHANCE = Rational(49/100) |
|
|
|
HOME_CHANCE = 0.51 |
|
AWAY_CHANCE = 0.49 |
|
|
|
def get_reference_list(): |
|
return itertools.product(range(MATCHES_TO_WIN + 1), repeat=2) |
|
|
|
def get_reference_matrix(): |
|
reference_matrix = [] |
|
for i,x in enumerate(get_reference_list()): |
|
reference_matrix.append([]) |
|
for j,y in enumerate(get_reference_list()): |
|
reference_matrix[i].append([]) |
|
reference_matrix[i][j] = (y, x) |
|
return reference_matrix |
|
|
|
def board_size(): |
|
return len(list(get_reference_list())) |
|
|
|
|
|
def get_starting_matrix(): |
|
empty = [S(0)] * board_size() |
|
empty[0] = Rational(1) |
|
return Matrix(empty) |
|
|
|
def get_transition_matrix(): |
|
size = board_size() |
|
|
|
matrix = zeros(size) |
|
reference_matrix = get_reference_matrix() |
|
|
|
for y in range(size): |
|
for x in range(size): |
|
reference = reference_matrix[x][y] |
|
# The current state we're in: e.g., (1,3), representing 1 vs. 3 (away) |
|
current_state = reference[0] |
|
# The state we would transition to, if we would stay in this row! |
|
next_state = reference[1] |
|
|
|
# If we've reached a 'winning' state: |
|
if current_state[0] == MATCHES_TO_WIN or current_state[1] == MATCHES_TO_WIN: |
|
# Next state matches our winning state, so (1) makes a loop |
|
if current_state == next_state: |
|
matrix[x,y] = S(1) |
|
# Zero out the rest of the column |
|
else: |
|
matrix[x,y] = S(0) |
|
continue |
|
|
|
# We can calculate whether this state is a home-game (first HOME_MATCHES game) by calculating total wins |
|
# This logic is flimsy against points being awarded in some other way than matches. |
|
is_home_game = current_state[0] + current_state[1] > HOME_MATCHES |
|
a_victory = next_state[0] == current_state[0] + 1 |
|
b_victory = next_state[1] == current_state[1] + 1 |
|
|
|
a_stayed_same = next_state[0] == current_state[0] |
|
b_stayed_same = next_state[1] == current_state[1] |
|
|
|
# Winning in this state would be a home-A victory |
|
if a_victory and b_stayed_same: |
|
matrix[x,y] = HOME_CHANCE if is_home_game else AWAY_CHANCE |
|
continue |
|
|
|
# Winning in this state would be a team-B victory |
|
if b_victory and a_stayed_same: |
|
matrix[x,y] = AWAY_CHANCE if is_home_game else HOME_CHANCE |
|
continue |
|
|
|
# Technically not required since we started with zeros, but: |
|
# Any other state would be illegal. For example some states would represent |
|
# both teams winning at once, or one team winning lots of points at once. |
|
matrix[x,y] = S(0) |
|
|
|
|
|
return matrix |
|
|
|
|
|
def main(): |
|
matrix = get_starting_matrix() |
|
transform = get_transition_matrix() |
|
pprint(transform, wrap_line=False) |
|
for i in range(MATCHES_TO_WIN * 2): |
|
matrix = transform * matrix |
|
|
|
# print(matrix) |
|
# print(list(get_reference_list())) |
|
|
|
a_chance = 0 |
|
b_chance = 0 |
|
|
|
for m, r in zip(matrix, get_reference_list()): |
|
if(r[0] == 4): |
|
a_chance += m |
|
if(r[1] == 4): |
|
b_chance += m |
|
|
|
print(Float(a_chance)) |
|
print(Float(b_chance)) |
|
|
|
|
|
main() |