Skip to content

Instantly share code, notes, and snippets.

@BlaiseRideout
Last active August 29, 2015 14:27
Show Gist options
  • Select an option

  • Save BlaiseRideout/c6eb3f7e266942166286 to your computer and use it in GitHub Desktop.

Select an option

Save BlaiseRideout/c6eb3f7e266942166286 to your computer and use it in GitHub Desktop.
A genetically optimized mahjong table seating randomizer
#!/usr/bin/env python
import sqlite3 as sql
import random
POPULATION = 256
def main():
todays_players = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98] # 98
random.shuffle(todays_players)
todays_players = todays_players[0:32] # 32 random players
#todays_players = [40,6,23,26,15,98,1,10,55,16,56,97,96,12,13,41,52,88,66,94,89,86,87,77,79,72,76] # 27 players
#todays_players = [40,6,23,26,15,98,1,10] # 8 players (best case score 24)
#todays_players = [97, 96, 12, 13, 41, 52, 88, 66, 94] # 12 players (best case score 14)
conn = sql.connect('MahjongScores.db')
playergames = playerGames(todays_players, conn.cursor())
conn.close()
tables = bestArrangement(todays_players, playergames)
print "Final score: " + str(tablesScore(tables, playergames))
print "Final arrangement: " + str(tables)
def bestArrangement(tables, playergames, population = POPULATION):
numplayers = len(tables)
tabless = []
for i in range(POPULATION):
random.shuffle(tables)
tabless += [(tablesScore(tables, playergames), tables)]
tabless.sort(key=itemgetter(0))
minScore = tabless[0][0]
improved = 0
while improved < numplayers and minScore > 0:
for j in range(POPULATION):
newTables = mutateTables(tabless[j][1])
tabless += [(tablesScore(newTables, playergames), newTables)]
tabless.sort(key=itemgetter(0))
tabless = tabless[0:POPULATION]
improved += 1
if minScore != tabless[0][0]:
minScore = tabless[0][0]
improved = 0
return tabless[0][1]
def mutateTables(tables):
tables = tables[:]
a = random.randint(0, len(tables) - 1)
b = random.randint(0, len(tables) - 1)
tables[a], tables[b] = tables[b], tables[a]
return tables
def tablesScore(players, playergames):
numplayers = len(players)
if numplayers >= 8:
tables_5p = numplayers % 4
total_tables = int(numplayers / 4)
tables_4p = total_tables - tables_5p
else:
if numplayers >= 5:
tables_5p = 1
else:
tables_5p = 0
total_tables = 1
tables_4p = total_tables - tables_5p
score = 0
for i in range(0, tables_5p * 5, 5):
table = players[i:i+5]
score += tableScore(table, playergames)
for i in range(tables_5p * 5, numplayers, 4):
table = players[i:i+4]
score += tableScore(table, playergames)
return score
def tableScore(players, playergames):
numplayers = len(players)
score = 0
for i in range(numplayers):
for j in range(i + 1, numplayers):
if (players[i], players[j]) in playergames:
score += playergames[(players[i], players[j])]
elif (players[j], players[i]) in playergames:
score += playergames[(players[j], players[i])]
return score
def playerGames(players, c):
numplayers = len(players)
playergames = dict()
for i in range(numplayers):
for j in range(i + 1, numplayers):
games = c.execute("SELECT COUNT(*) FROM Scores WHERE PlayerId = ? AND GameId IN (SELECT GameId FROM Scores WHERE PlayerId = ?)", (players[i], players[j])).fetchone()[0]
if games != 0:
playergames[(players[i], players[j])] = games
return playergames
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment