Skip to content

Instantly share code, notes, and snippets.

@ealmansi
Last active December 28, 2017 01:07
Show Gist options
  • Save ealmansi/86d9eded23851a00d487 to your computer and use it in GitHub Desktop.
Save ealmansi/86d9eded23851a00d487 to your computer and use it in GitHub Desktop.
TEG: probabilidad de conquistar otro país mediante ataques reiterados
#!/usr/bin/env python3
import math;
##########################################################################################
# Basado en: http://openpool.com.ar/reglamento/T.E.G.-REGLAMENTO.pdf
#
# Probabilidad de conquistar otro pais si atacamos sin frenar hasta que:
# i) conquistamos el otro pais, o
# ii) nos quedamos con una sola ficha y no podemos atacar más
#
# Tabla: Cantidad de ejércitos disponibles (Atacante \ Defensor) vs Probabilidad (%)
#
# A\D | 1 2 3 4 5 6 7 8 9 10
# ____________________________________________________________________
# 1 | 41.7 10.6 1.8 0.3 0.1 0.0 0.0 0.0 0.0 0.0
# 2 | 79.5 43.7 18.1 9.0 3.6 1.8 0.7 0.3 0.1 0.1
# 3 | 95.2 73.6 45.7 35.2 23.7 14.2 10.2 6.8 4.0 2.8
# 4 | 98.9 85.4 56.5 45.9 34.4 23.3 17.7 12.4 8.5 6.2
# 5 | 99.7 93.4 68.6 57.0 45.4 33.5 25.7 19.4 14.2 10.4
# 6 | 99.9 96.4 79.9 69.2 57.3 45.1 36.2 28.2 21.4 16.5
# 7 | 100.0 98.4 85.0 75.7 65.9 54.1 44.9 36.4 28.8 22.9
# 8 | 100.0 99.2 89.4 82.0 73.1 62.4 53.3 44.6 36.5 29.7
# 9 | 100.0 99.6 93.4 87.0 79.2 70.1 61.3 52.6 44.3 37.0
# 10 | 100.0 99.8 95.1 90.1 84.1 76.0 67.9 59.8 51.6 44.1
#
# Aclaración: para el atacante, la cantidad de ejércitos disponibles es la cantidad total
# de ejércitos en el país atacante menos uno; para el defensor, es la cantidad total de
# ejércitos en el país defensor. Por ejemplo, si ataco desde un país con 5 fichas a un
# país con 3 fichas, miro la posición (4, 3) en la tabla: 56.5%.
##########################################################################################
def computarTabla(max_ejs_atacantes, max_ejs_defensores):
pt = computarProbabilidadesTransicion()
tb = [[-1 for j in range(max_ejs_defensores + 1)] for i in range(max_ejs_atacantes + 1)]
for i in range(1, max_ejs_atacantes + 1):
tb[i][0] = 1
for j in range(1, max_ejs_defensores + 1):
tb[0][j] = 0
for i in range(1, max_ejs_atacantes + 1):
for j in range(1, max_ejs_defensores + 1):
ejs_en_ataque = min(i, 3)
ejs_en_defensa = min(j, 3)
ejs_en_juego = min(ejs_en_ataque, ejs_en_defensa)
tb[i][j] = 0
for k in range(ejs_en_juego + 1):
ejs_en_ataque_p = ejs_en_ataque - k
ejs_en_defensa_p = ejs_en_defensa - (ejs_en_juego - k)
p = pt[(ejs_en_ataque, ejs_en_defensa,
ejs_en_ataque_p, ejs_en_defensa_p)]
i_p, j_p = i - k, j - (ejs_en_juego - k)
tb[i][j] += p * tb[i_p][j_p]
return tb
def computarProbabilidadesTransicion():
pt = {}
for ejs_en_ataque in range(1, 3 + 1):
for ejs_en_defensa in range(1, 3 + 1):
ejs_en_juego = min(ejs_en_ataque, ejs_en_defensa)
# inicializo el conteo de veces que sucedio cada posible resultado en 0
for k in range(ejs_en_juego + 1):
ejs_en_ataque_p = ejs_en_ataque - k
ejs_en_defensa_p = ejs_en_defensa - (ejs_en_juego - k)
pt[(ejs_en_ataque, ejs_en_defensa,
ejs_en_ataque_p, ejs_en_defensa_p)] = 0.0
# simulo cualquier par posible de tirada del atacante / del defensor
for tirada_atacante in obtenerPosiblesTiradas(ejs_en_ataque):
for tirada_defensor in obtenerPosiblesTiradas(ejs_en_defensa):
# cuento la cantidad de ejercitos vencidos por el atacante
ejs_vencidos = 0
for i in range(ejs_en_juego):
if tirada_atacante[i] > tirada_defensor[i]:
ejs_vencidos = ejs_vencidos + 1
# incremento el conteo de veces que sucedio este resultado
ejs_en_ataque_p = ejs_en_ataque - (ejs_en_juego - ejs_vencidos)
ejs_en_defensa_p = ejs_en_defensa - ejs_vencidos
pt[(ejs_en_ataque, ejs_en_defensa,
ejs_en_ataque_p, ejs_en_defensa_p)] += 1.0
# transformo los conteos en probabilidades dividiendo por el total de resultados posibles
cant_resultados_posibles = int(math.pow(6, ejs_en_ataque + ejs_en_defensa))
for k in range(ejs_en_juego + 1):
ejs_en_ataque_p = ejs_en_ataque - k
ejs_en_defensa_p = ejs_en_defensa - (ejs_en_juego - k)
pt[(ejs_en_ataque, ejs_en_defensa,
ejs_en_ataque_p, ejs_en_defensa_p)] /= cant_resultados_posibles
return pt
def obtenerPosiblesTiradas(ejs):
for n in range(0, int(math.pow(6, ejs))):
tirada = []
for i in range(1, ejs + 1):
tirada.append(n % 6)
n = n / 6
tirada.sort(reverse=True)
yield tirada
def imprimirTabla(tb, max_ejs_atacantes, max_ejs_defensores):
for i in range(1, max_ejs_atacantes + 1):
for j in range(1, max_ejs_defensores + 1):
print('{0:5.1f}'.format(100 * tb[i][j]), end='')
if (j + 1 < max_ejs_defensores + 1):
print(' ', end='')
print()
def main():
max_ejs_atacantes = 10
max_ejs_defensores = 10
tb = computarTabla(max_ejs_atacantes, max_ejs_defensores)
imprimirTabla(tb, max_ejs_atacantes, max_ejs_defensores)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment