def crack(ciphertext, *fitness_functions, ntrials=30, nswaps=3000):
    if ntrials <= 0 or nswaps <= 0:
        raise ValueError("ntrials and nswaps must be positive integers")
    def next_node_inner_climb(node):
        a, b = random.sample(range(len(node)), 2)
        node[a], node[b] = node[b], node[a]
        plaintext = decrypt(node, ciphertext)
        node_score = score(plaintext, *fitness_functions)
        return node, node_score, Decryption(plaintext, ''.join(node), node_score)
    def next_node_outer_climb(node):
        random.shuffle(node)
        key, best_score, outputs = hill_climb(nswaps, node[:], next_node_inner_climb)
        return key, best_score, outputs[-1]
    _, _, decryptions = hill_climb(ntrials, list(string.ascii_uppercase), next_node_outer_climb)
    return sorted(decryptions, reverse=True)