Skip to content

Instantly share code, notes, and snippets.

@HebeHH
Last active June 29, 2024 15:20
Show Gist options
  • Save HebeHH/0056784787d26fcc3fd95f97e9e7e55a to your computer and use it in GitHub Desktop.
Save HebeHH/0056784787d26fcc3fd95f97e9e7e55a to your computer and use it in GitHub Desktop.
Solver for The Password Game, specifically the section "The elements in your password must have atomic numbers that add up to 200"
# This is a solver for The Password Game: https://neal.fun/password-game/,
# Specifically the section "The elements in your password must have atomic numbers that add up to 200"
# It's written as a Flask app because I was sharing it with my friends that were also playing.
# However you can just use the function `get_required_elements_for_password_game(password)`
# to do it locally
# Got ChatGPT to write the element list for me
elements = [
{"name": "Hydrogen", "symbol": "H", "atomic_number": 1},
{"name": "Helium", "symbol": "He", "atomic_number": 2},
{"name": "Lithium", "symbol": "Li", "atomic_number": 3},
{"name": "Beryllium", "symbol": "Be", "atomic_number": 4},
{"name": "Boron", "symbol": "B", "atomic_number": 5},
{"name": "Carbon", "symbol": "C", "atomic_number": 6},
{"name": "Nitrogen", "symbol": "N", "atomic_number": 7},
{"name": "Oxygen", "symbol": "O", "atomic_number": 8},
{"name": "Fluorine", "symbol": "F", "atomic_number": 9},
{"name": "Neon", "symbol": "Ne", "atomic_number": 10},
{"name": "Sodium", "symbol": "Na", "atomic_number": 11},
{"name": "Magnesium", "symbol": "Mg", "atomic_number": 12},
{"name": "Aluminum", "symbol": "Al", "atomic_number": 13},
{"name": "Silicon", "symbol": "Si", "atomic_number": 14},
{"name": "Phosphorus", "symbol": "P", "atomic_number": 15},
{"name": "Sulfur", "symbol": "S", "atomic_number": 16},
{"name": "Chlorine", "symbol": "Cl", "atomic_number": 17},
{"name": "Argon", "symbol": "Ar", "atomic_number": 18},
{"name": "Potassium", "symbol": "K", "atomic_number": 19},
{"name": "Calcium", "symbol": "Ca", "atomic_number": 20},
{"name": "Scandium", "symbol": "Sc", "atomic_number": 21},
{"name": "Titanium", "symbol": "Ti", "atomic_number": 22},
{"name": "Vanadium", "symbol": "V", "atomic_number": 23},
{"name": "Chromium", "symbol": "Cr", "atomic_number": 24},
{"name": "Manganese", "symbol": "Mn", "atomic_number": 25},
{"name": "Iron", "symbol": "Fe", "atomic_number": 26},
{"name": "Cobalt", "symbol": "Co", "atomic_number": 27},
{"name": "Nickel", "symbol": "Ni", "atomic_number": 28},
{"name": "Copper", "symbol": "Cu", "atomic_number": 29},
{"name": "Zinc", "symbol": "Zn", "atomic_number": 30},
{"name": "Gallium", "symbol": "Ga", "atomic_number": 31},
{"name": "Germanium", "symbol": "Ge", "atomic_number": 32},
{"name": "Arsenic", "symbol": "As", "atomic_number": 33},
{"name": "Selenium", "symbol": "Se", "atomic_number": 34},
{"name": "Bromine", "symbol": "Br", "atomic_number": 35},
{"name": "Krypton", "symbol": "Kr", "atomic_number": 36},
{"name": "Rubidium", "symbol": "Rb", "atomic_number": 37},
{"name": "Strontium", "symbol": "Sr", "atomic_number": 38},
{"name": "Yttrium", "symbol": "Y", "atomic_number": 39},
{"name": "Zirconium", "symbol": "Zr", "atomic_number": 40},
{"name": "Niobium", "symbol": "Nb", "atomic_number": 41},
{"name": "Molybdenum", "symbol": "Mo", "atomic_number": 42},
{"name": "Technetium", "symbol": "Tc", "atomic_number": 43},
{"name": "Ruthenium", "symbol": "Ru", "atomic_number": 44},
{"name": "Rhodium", "symbol": "Rh", "atomic_number": 45},
{"name": "Palladium", "symbol": "Pd", "atomic_number": 46},
{"name": "Silver", "symbol": "Ag", "atomic_number": 47},
{"name": "Cadmium", "symbol": "Cd", "atomic_number": 48},
{"name": "Indium", "symbol": "In", "atomic_number": 49},
{"name": "Tin", "symbol": "Sn", "atomic_number": 50},
{"name": "Antimony", "symbol": "Sb", "atomic_number": 51},
{"name": "Tellurium", "symbol": "Te", "atomic_number": 52},
{"name": "Iodine", "symbol": "I", "atomic_number": 53},
{"name": "Xenon", "symbol": "Xe", "atomic_number": 54},
{"name": "Cesium", "symbol": "Cs", "atomic_number": 55},
{"name": "Barium", "symbol": "Ba", "atomic_number": 56},
{"name": "Lanthanum", "symbol": "La", "atomic_number": 57},
{"name": "Cerium", "symbol": "Ce", "atomic_number": 58},
{"name": "Praseodymium", "symbol": "Pr", "atomic_number": 59},
{"name": "Neodymium", "symbol": "Nd", "atomic_number": 60},
{"name": "Promethium", "symbol": "Pm", "atomic_number": 61},
{"name": "Samarium", "symbol": "Sm", "atomic_number": 62},
{"name": "Europium", "symbol": "Eu", "atomic_number": 63},
{"name": "Gadolinium", "symbol": "Gd", "atomic_number": 64},
{"name": "Terbium", "symbol": "Tb", "atomic_number": 65},
{"name": "Dysprosium", "symbol": "Dy", "atomic_number": 66},
{"name": "Holmium", "symbol": "Ho", "atomic_number": 67},
{"name": "Erbium", "symbol": "Er", "atomic_number": 68},
{"name": "Thulium", "symbol": "Tm", "atomic_number": 69},
{"name": "Ytterbium", "symbol": "Yb", "atomic_number": 70},
{"name": "Lutetium", "symbol": "Lu", "atomic_number": 71},
{"name": "Hafnium", "symbol": "Hf", "atomic_number": 72},
{"name": "Tantalum", "symbol": "Ta", "atomic_number": 73},
{"name": "Tungsten", "symbol": "W", "atomic_number": 74},
{"name": "Rhenium", "symbol": "Re", "atomic_number": 75},
{"name": "Osmium", "symbol": "Os", "atomic_number": 76},
{"name": "Iridium", "symbol": "Ir", "atomic_number": 77},
{"name": "Platinum", "symbol": "Pt", "atomic_number": 78},
{"name": "Gold", "symbol": "Au", "atomic_number": 79},
{"name": "Mercury", "symbol": "Hg", "atomic_number": 80},
{"name": "Thallium", "symbol": "Tl", "atomic_number": 81},
{"name": "Lead", "symbol": "Pb", "atomic_number": 82},
{"name": "Bismuth", "symbol": "Bi", "atomic_number": 83},
{"name": "Polonium", "symbol": "Po", "atomic_number": 84},
{"name": "Astatine", "symbol": "At", "atomic_number": 85},
{"name": "Radon", "symbol": "Rn", "atomic_number": 86},
{"name": "Francium", "symbol": "Fr", "atomic_number": 87},
{"name": "Radium", "symbol": "Ra", "atomic_number": 88},
{"name": "Actinium", "symbol": "Ac", "atomic_number": 89},
{"name": "Thorium", "symbol": "Th", "atomic_number": 90},
{"name": "Protactinium", "symbol": "Pa", "atomic_number": 91},
{"name": "Uranium", "symbol": "U", "atomic_number": 92},
{"name": "Neptunium", "symbol": "Np", "atomic_number": 93},
{"name": "Plutonium", "symbol": "Pu", "atomic_number": 94},
{"name": "Americium", "symbol": "Am", "atomic_number": 95},
{"name": "Curium", "symbol": "Cm", "atomic_number": 96},
{"name": "Berkelium", "symbol": "Bk", "atomic_number": 97},
{"name": "Californium", "symbol": "Cf", "atomic_number": 98},
{"name": "Einsteinium", "symbol": "Es", "atomic_number": 99},
{"name": "Fermium", "symbol": "Fm", "atomic_number": 100},
{"name": "Mendelevium", "symbol": "Md", "atomic_number": 101},
{"name": "Nobelium", "symbol": "No", "atomic_number": 102},
{"name": "Lawrencium", "symbol": "Lr", "atomic_number": 103},
{"name": "Rutherfordium", "symbol": "Rf", "atomic_number": 104},
{"name": "Dubnium", "symbol": "Db", "atomic_number": 105},
{"name": "Seaborgium", "symbol": "Sg", "atomic_number": 106},
{"name": "Bohrium", "symbol": "Bh", "atomic_number": 107},
{"name": "Hassium", "symbol": "Hs", "atomic_number": 108},
{"name": "Meitnerium", "symbol": "Mt", "atomic_number": 109},
{"name": "Darmstadtium", "symbol": "Ds", "atomic_number": 110},
{"name": "Roentgenium", "symbol": "Rg", "atomic_number": 111},
{"name": "Copernicium", "symbol": "Cn", "atomic_number": 112},
{"name": "Nihonium", "symbol": "Nh", "atomic_number": 113},
{"name": "Flerovium", "symbol": "Fl", "atomic_number": 114},
{"name": "Moscovium", "symbol": "Mc", "atomic_number": 115},
{"name": "Livermorium", "symbol": "Lv", "atomic_number": 116},
{"name": "Tennessine", "symbol": "Ts", "atomic_number": 117},
{"name": "Oganesson", "symbol": "Og", "atomic_number": 118},
]
element_symbols = [x['symbol'] for x in elements]
elements_by_symbol = {x['symbol']: x['atomic_number']-1 for x in elements}
roman_numerals = ['I','V','X','L','C','D','M']
for e in elements:
e['symbol_contains_roman_numerals'] = e['symbol'][0] in roman_numerals
def get_element_by_symbol(s):
return elements[elements_by_symbol[s]]
def atomic_sum(list_of_symbols):
return sum([get_element_by_symbol(s)['atomic_number'] for s in list_of_symbols])
def stringify_elementlist(symbols):
return ', '.join([s + "(atomic number: " + str(get_element_by_symbol(s)['atomic_number']) +")" for s in symbols])
def elements_to_target(required_symbols, target):
symbols = required_symbols
current_count = atomic_sum(symbols)
while current_count < target:
diff = target - current_count
new_element_idx = diff - 1
while elements[new_element_idx]['symbol_contains_roman_numerals']:
new_element_idx -= 1
current_count += elements[new_element_idx]['atomic_number']
symbols.append(elements[new_element_idx]['symbol'])
assert(atomic_sum(symbols))
return symbols
def find_elements(text):
# Sort symbols by length, longest first
element_symbols.sort(key=len, reverse=True)
result = []
used = [False] * len(text)
for i in range(len(text)):
# Skip if this char is already part of another symbol
if used[i]:
continue
for symbol in element_symbols:
if text.startswith(symbol, i):
# Check if any characters have been used in the range
if all(not used[j] for j in range(i, i+len(symbol))):
result.append(symbol)
# Mark these characters as used
for j in range(i, i+len(symbol)):
used[j] = True
break # No need to check shorter symbols
return result
# Actually get the required elements
def get_required_elements_for_password_game(password):
required_symbols = find_elements(password)
if atomic_sum(required_symbols) == 200:
return {
"INSTRUCTIONS" : "No need to do anything",
"RATIONALE": "The atomic numbers in your password already add up to 200!",
}
if atomic_sum(required_symbols) > 200:
return {
"INSTRUCTIONS" : "Delete everything.",
"RATIONALE": "The atomic numbers already in your password are: "+ stringify_elementlist(required_symbols)+ ". These add up to " + str(atomic_sum(required_symbols)) + ", which is over 200! We can't do anything until you bring that down :(",
}
symbol_list = elements_to_target(required_symbols.copy(), 200) # there's probably a better way to do this than list.copy() but eh I'm in a rush
print(required_symbols)
print(symbol_list)
new_symbols = symbol_list.copy()
for x in required_symbols:
new_symbols.remove(x)
# This could be nicer but oh well I wrote it quick just to help a friend understand
instructions = "Add to your password the text: " + ''.join(new_symbols)
rationale = "Currently, your password includes the elements: " + stringify_elementlist(required_symbols)+ ". "
rationale += "These sum to " + str(atomic_sum(required_symbols)) + ". "
rationale += "In order to equal a sum of 200, you need to add "+ str(200 - atomic_sum(required_symbols)) + ". "
rationale += "In order to do this, you are adding the elements: " +stringify_elementlist(new_symbols) + ", "
rationale += "which sum to " + str(atomic_sum(new_symbols)) + "."
return {
"INSTRUCTIONS" : instructions,
"RATIONALE": rationale,
"full_list":symbol_list,
"existing_elements": required_symbols,
"elements_to_add" : new_symbols
}
# ChatGPT wrote the Flask code for me because who can be bothered
from flask import Flask, request, jsonify
from urllib.parse import unquote
app = Flask(__name__)
@app.route('/process', methods=['POST'])
def process():
data = request.json # Expecting a JSON payload
if 'password' not in data:
return jsonify({"error": "Missing 'password' in payload"}), 400
processed = get_required_elements_for_password_game(data['password'])
return jsonify({"result": processed})
@app.route('/process', methods=['GET'])
def process_get():
text_param = request.args.get('password', None)
if text_param is None:
return jsonify({"error": "Missing 'password' parameter"}), 400
# Decode the URL-encoded text
text = unquote(text_param)
processed = get_required_elements_for_password_game(text)
return jsonify({"result": processed})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5002, debug=True)
@xeon-zolt
Copy link

I hosted it here by creating it into static website
https://password-game-element-solver.xeonzolt.com/

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