Skip to content

Instantly share code, notes, and snippets.

@HarvsG
Last active April 21, 2020 18:53
Show Gist options
  • Save HarvsG/f6b1a4bf509866cb21135c091f5ce1ac to your computer and use it in GitHub Desktop.
Save HarvsG/f6b1a4bf509866cb21135c091f5ce1ac to your computer and use it in GitHub Desktop.
My solution to Matt Parker's SCRABBLE PUZZLE (MPMP PUZZLE 3) https://www.youtube.com/watch?v=JaXo_i3ktwM&t
import sys
if sys.version_info[0] < 3:
raise Exception("Python 3 or a more recent version is required.")
# this will serve as a dictionary of what each tile face is worth
scores = {"A": 1 , "B": 3 , "C": 3 , "D": 2 ,
"E": 1 , "F": 4 , "G": 2 , "H": 4 ,
"I": 1 , "J": 8 , "K": 5 , "L": 1 ,
"M": 3 , "N": 1 , "O": 1 , "P": 3 ,
"Q": 10, "R": 1 , "S": 1 , "T": 1 ,
"U": 1 , "V": 4 , "W": 4 , "X": 8 ,
"Y": 4 , "Z": 10, " ":0}
# this is the amount of each tile that is in the game, there are 100 tiles totoal
pieces = {"A":9, "B":2, "C":2, "D":4, "E":12,
"F":2, "G":3, "H":2, "I":9, "J":1,
"K":1, "L":4, "M":2, "N":6, "O":8,
"P":2, "Q":1, "R":6, "S":4, "T":6,
"U":4, "V":2, "W":2, "X":1, "Y":2,
"Z":1, " ":2}
def make_uniques(dic):
unique_scores = set(dic.values())
score_tiles = {}
for key, val in dic.items():
if val not in score_tiles:
score_tiles[val] = pieces[key]
else:
score_tiles[val] += pieces[key]
sorted_tiles = {}
for key in reversed(sorted(score_tiles.keys())):
sorted_tiles[key] = score_tiles[key]
return sorted_tiles
def max_from_uniques(uniques, rem_choices):
max = 0
i = 0
for key, value in uniques.items():
if i < rem_choices:
p = min(value,rem_choices-i)
max = max + (key*p)
i += p
else:
break
return max
def calc(lim, pieces, uniques, remainder, choices=[], solutions=set()):
'''A recursive function to find ways of making 46 from lim tiles
lim = the number of tiles we are choosing
pieces = dictionary of the {tile_string:number_of_tiles}
unqiues = dictionary of {tile_score:number_of_tiles_with_that_score} aka make_uniques(pieces)
remainder = the target number
choices = list the current choices made so far
solutions = the current set of discovered solutions'''
if len(choices) == lim:
# we have made all our n==lim choices so we either have a solution or we dont
if remainder is 0:
# in this case we have found a solution so return it
# sort to prevent duplicates
choices.sort()
# ------optional code to print new solutions-------
if tuple(choices) not in solutions:
print('New soultion found: ' + str(tuple(choices)))
# ---end optional code to print new solutions-------
# add the solutions to the set of solutions, duplicates will be ignored
solutions.add(tuple(choices))
return solutions
else:
# in this case we have used all tiles and not found a solution so return False
return False
elif len(choices) < lim:
# we still have remaining choices to make
rem_choices = lim - len(choices)
# this if statement checks if it is even possible to make the remainder with the remaining tiles, massively more efficient
if max_from_uniques(uniques, rem_choices) < remainder:
return False
for piece, num in pieces.items():
# only try if any tiles of that name remain
if num > 0:
# as each recurrsion may generate > 1 aditional recursion, a branching version must be made, so we make copies
d_choices = choices.copy()
d_lim = lim
d_pieces = pieces.copy()
d_uniques = uniques.copy()
d_remainder = remainder
d_solutions = solutions.copy()
# alter the copies to make the choice
d_pieces[piece] -= 1
d_uniques[scores[piece]] -= 1
d_remainder -= scores[piece]
d_choices.append(piece)
# recurr
res = calc(d_lim, d_pieces, d_uniques, d_remainder, choices=d_choices, solutions=d_solutions)
# if the solution is valid, add it to the solutions. As we are using sets it doesn't matter if there are duplicates
if res is not False:
solutions = solutions | res
else:
continue
else:
continue
return solutions
else:
print('here be dragons')
solutions = calc(7,pieces,make_uniques(scores), 46)
print(sorted(solutions))
print(len(solutions))
@HarvsG
Copy link
Author

HarvsG commented Apr 21, 2020

result is:

[('A', 'F', 'J', 'K', 'Q', 'X', 'Z'), ('A', 'H', 'J', 'K', 'Q', 'X', 'Z'), ('A', 'J', 'K', 'Q', 'V', 'X', 'Z'), ('A', 'J', 'K', 'Q', 'W', 'X', 'Z'), ('A', 'J', 'K', 'Q', 'X', 'Y', 'Z'), ('B', 'B', 'F', 'J', 'Q', 'X', 'Z'), ('B', 'B', 'H', 'J', 'Q', 'X', 'Z'), ('B', 'B', 'J', 'Q', 'V', 'X', 'Z'), ('B', 'B', 'J', 'Q', 'W', 'X', 'Z'), ('B', 'B', 'J', 'Q', 'X', 'Y', 'Z'), ('B', 'C', 'F', 'J', 'Q', 'X', 'Z'), ('B', 'C', 'H', 'J', 'Q', 'X', 'Z'), ('B', 'C', 'J', 'Q', 'V', 'X', 'Z'), ('B', 'C', 'J', 'Q', 'W', 'X', 'Z'), ('B', 'C', 'J', 'Q', 'X', 'Y', 'Z'), ('B', 'D', 'J', 'K', 'Q', 'X', 'Z'), ('B', 'F', 'J', 'M', 'Q', 'X', 'Z'), ('B', 'F', 'J', 'P', 'Q', 'X', 'Z'), ('B', 'G', 'J', 'K', 'Q', 'X', 'Z'), ('B', 'H', 'J', 'M', 'Q', 'X', 'Z'), ('B', 'H', 'J', 'P', 'Q', 'X', 'Z'), ('B', 'J', 'M', 'Q', 'V', 'X', 'Z'), ('B', 'J', 'M', 'Q', 'W', 'X', 'Z'), ('B', 'J', 'M', 'Q', 'X', 'Y', 'Z'), ('B', 'J', 'P', 'Q', 'V', 'X', 'Z'), ('B', 'J', 'P', 'Q', 'W', 'X', 'Z'), ('B', 'J', 'P', 'Q', 'X', 'Y', 'Z'), ('C', 'C', 'F', 'J', 'Q', 'X', 'Z'), ('C', 'C', 'H', 'J', 'Q', 'X', 'Z'), ('C', 'C', 'J', 'Q', 'V', 'X', 'Z'), ('C', 'C', 'J', 'Q', 'W', 'X', 'Z'), ('C', 'C', 'J', 'Q', 'X', 'Y', 'Z'), ('C', 'D', 'J', 'K', 'Q', 'X', 'Z'), ('C', 'F', 'J', 'M', 'Q', 'X', 'Z'), ('C', 'F', 'J', 'P', 'Q', 'X', 'Z'), ('C', 'G', 'J', 'K', 'Q', 'X', 'Z'), ('C', 'H', 'J', 'M', 'Q', 'X', 'Z'), ('C', 'H', 'J', 'P', 'Q', 'X', 'Z'), ('C', 'J', 'M', 'Q', 'V', 'X', 'Z'), ('C', 'J', 'M', 'Q', 'W', 'X', 'Z'), ('C', 'J', 'M', 'Q', 'X', 'Y', 'Z'), ('C', 'J', 'P', 'Q', 'V', 'X', 'Z'), ('C', 'J', 'P', 'Q', 'W', 'X', 'Z'), ('C', 'J', 'P', 'Q', 'X', 'Y', 'Z'), ('D', 'F', 'F', 'J', 'Q', 'X', 'Z'), ('D', 'F', 'H', 'J', 'Q', 'X', 'Z'), ('D', 'F', 'J', 'Q', 'V', 'X', 'Z'), ('D', 'F', 'J', 'Q', 'W', 'X', 'Z'), ('D', 'F', 'J', 'Q', 'X', 'Y', 'Z'), ('D', 'H', 'H', 'J', 'Q', 'X', 'Z'), ('D', 'H', 'J', 'Q', 'V', 'X', 'Z'), ('D', 'H', 'J', 'Q', 'W', 'X', 'Z'), ('D', 'H', 'J', 'Q', 'X', 'Y', 'Z'), ('D', 'J', 'K', 'M', 'Q', 'X', 'Z'), ('D', 'J', 'K', 'P', 'Q', 'X', 'Z'), ('D', 'J', 'Q', 'V', 'V', 'X', 'Z'), ('D', 'J', 'Q', 'V', 'W', 'X', 'Z'), ('D', 'J', 'Q', 'V', 'X', 'Y', 'Z'), ('D', 'J', 'Q', 'W', 'W', 'X', 'Z'), ('D', 'J', 'Q', 'W', 'X', 'Y', 'Z'), ('D', 'J', 'Q', 'X', 'Y', 'Y', 'Z'), ('E', 'F', 'J', 'K', 'Q', 'X', 'Z'), ('E', 'H', 'J', 'K', 'Q', 'X', 'Z'), ('E', 'J', 'K', 'Q', 'V', 'X', 'Z'), ('E', 'J', 'K', 'Q', 'W', 'X', 'Z'), ('E', 'J', 'K', 'Q', 'X', 'Y', 'Z'), ('F', 'F', 'G', 'J', 'Q', 'X', 'Z'), ('F', 'G', 'H', 'J', 'Q', 'X', 'Z'), ('F', 'G', 'J', 'Q', 'V', 'X', 'Z'), ('F', 'G', 'J', 'Q', 'W', 'X', 'Z'), ('F', 'G', 'J', 'Q', 'X', 'Y', 'Z'), ('F', 'I', 'J', 'K', 'Q', 'X', 'Z'), ('F', 'J', 'K', 'L', 'Q', 'X', 'Z'), ('F', 'J', 'K', 'N', 'Q', 'X', 'Z'), ('F', 'J', 'K', 'O', 'Q', 'X', 'Z'), ('F', 'J', 'K', 'Q', 'R', 'X', 'Z'), ('F', 'J', 'K', 'Q', 'S', 'X', 'Z'), ('F', 'J', 'K', 'Q', 'T', 'X', 'Z'), ('F', 'J', 'K', 'Q', 'U', 'X', 'Z'), ('F', 'J', 'M', 'M', 'Q', 'X', 'Z'), ('F', 'J', 'M', 'P', 'Q', 'X', 'Z'), ('F', 'J', 'P', 'P', 'Q', 'X', 'Z'), ('G', 'H', 'H', 'J', 'Q', 'X', 'Z'), ('G', 'H', 'J', 'Q', 'V', 'X', 'Z'), ('G', 'H', 'J', 'Q', 'W', 'X', 'Z'), ('G', 'H', 'J', 'Q', 'X', 'Y', 'Z'), ('G', 'J', 'K', 'M', 'Q', 'X', 'Z'), ('G', 'J', 'K', 'P', 'Q', 'X', 'Z'), ('G', 'J', 'Q', 'V', 'V', 'X', 'Z'), ('G', 'J', 'Q', 'V', 'W', 'X', 'Z'), ('G', 'J', 'Q', 'V', 'X', 'Y', 'Z'), ('G', 'J', 'Q', 'W', 'W', 'X', 'Z'), ('G', 'J', 'Q', 'W', 'X', 'Y', 'Z'), ('G', 'J', 'Q', 'X', 'Y', 'Y', 'Z'), ('H', 'I', 'J', 'K', 'Q', 'X', 'Z'), ('H', 'J', 'K', 'L', 'Q', 'X', 'Z'), ('H', 'J', 'K', 'N', 'Q', 'X', 'Z'), ('H', 'J', 'K', 'O', 'Q', 'X', 'Z'), ('H', 'J', 'K', 'Q', 'R', 'X', 'Z'), ('H', 'J', 'K', 'Q', 'S', 'X', 'Z'), ('H', 'J', 'K', 'Q', 'T', 'X', 'Z'), ('H', 'J', 'K', 'Q', 'U', 'X', 'Z'), ('H', 'J', 'M', 'M', 'Q', 'X', 'Z'), ('H', 'J', 'M', 'P', 'Q', 'X', 'Z'), ('H', 'J', 'P', 'P', 'Q', 'X', 'Z'), ('I', 'J', 'K', 'Q', 'V', 'X', 'Z'), ('I', 'J', 'K', 'Q', 'W', 'X', 'Z'), ('I', 'J', 'K', 'Q', 'X', 'Y', 'Z'), ('J', 'K', 'L', 'Q', 'V', 'X', 'Z'), ('J', 'K', 'L', 'Q', 'W', 'X', 'Z'), ('J', 'K', 'L', 'Q', 'X', 'Y', 'Z'), ('J', 'K', 'N', 'Q', 'V', 'X', 'Z'), ('J', 'K', 'N', 'Q', 'W', 'X', 'Z'), ('J', 'K', 'N', 'Q', 'X', 'Y', 'Z'), ('J', 'K', 'O', 'Q', 'V', 'X', 'Z'), ('J', 'K', 'O', 'Q', 'W', 'X', 'Z'), ('J', 'K', 'O', 'Q', 'X', 'Y', 'Z'), ('J', 'K', 'Q', 'R', 'V', 'X', 'Z'), ('J', 'K', 'Q', 'R', 'W', 'X', 'Z'), ('J', 'K', 'Q', 'R', 'X', 'Y', 'Z'), ('J', 'K', 'Q', 'S', 'V', 'X', 'Z'), ('J', 'K', 'Q', 'S', 'W', 'X', 'Z'), ('J', 'K', 'Q', 'S', 'X', 'Y', 'Z'), ('J', 'K', 'Q', 'T', 'V', 'X', 'Z'), ('J', 'K', 'Q', 'T', 'W', 'X', 'Z'), ('J', 'K', 'Q', 'T', 'X', 'Y', 'Z'), ('J', 'K', 'Q', 'U', 'V', 'X', 'Z'), ('J', 'K', 'Q', 'U', 'W', 'X', 'Z'), ('J', 'K', 'Q', 'U', 'X', 'Y', 'Z'), ('J', 'M', 'M', 'Q', 'V', 'X', 'Z'), ('J', 'M', 'M', 'Q', 'W', 'X', 'Z'), ('J', 'M', 'M', 'Q', 'X', 'Y', 'Z'), ('J', 'M', 'P', 'Q', 'V', 'X', 'Z'), ('J', 'M', 'P', 'Q', 'W', 'X', 'Z'), ('J', 'M', 'P', 'Q', 'X', 'Y', 'Z'), ('J', 'P', 'P', 'Q', 'V', 'X', 'Z'), ('J', 'P', 'P', 'Q', 'W', 'X', 'Z'), ('J', 'P', 'P', 'Q', 'X', 'Y', 'Z')]
138

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment