Solver for The Password Game, specifically the section "The elements in your password must have atomic numbers that add up to 200"

7 min read Original article ↗
# 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)