Si vous disposez d'une copie de Python 3, vous pouvez le faire en un clin d'œil.
Tout d'abord, transcrivez les mots de passe dans un tableau comme ceci. (Ne tapez pas les >>>
personnages.)
>>> passwords = ["hideout", "flowing", "blanket", "dealing", "banning", "leaving",
"studies", "fencing", "battles", "chamber", "parties", "carrier",
"blazing", "various", "working", "beating", "mention", "wanting"]
Nous pouvons effectuer un contrôle d'intégrité et nous assurer que tous les mots de passe ont la même longueur :
>>> list(map(len, passwords))
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
Maintenant, nous devons voir combien de lettres sont les mêmes entre deux mots de passe. C'est un jeu d'enfant :
>>> def distance(a,b):
return sum(1 for al, bl in zip(a,b) if al == bl) if a != b else -1
Si les mots de passe sont identiques, nous retournons -1 au lieu de 7, ce qui nous permet d'ignorer ces cas.
Maintenant, nous avons besoin du code pour ne choisir que les mots de passe qui ont autant de caractères correspondants que le jeu nous indique. C'est un autre exemple. Vous lui donnez la liste des mots de passe, ce que vous avez essayé et qui n'a pas fonctionné et combien de caractères étaient corrects.
>>> def refine(candidates, wrong_pw, matches):
result = list(x for x in candidates if distance(x, wrong_pw) == matches)
return result
Disons que vous avez créé le mot de passe "coulant" et que vous avez obtenu un caractère correct. Aïe. Vous utilisez alors ce que nous avons défini comme ceci :
>>> passwords = refine(passwords, "flowing", 1); passwords
['blanket', 'studies', 'parties', 'carrier', 'mention']
Ok, que diriez-vous de "études"... non, 3 lettres correctes.
>>> passwords = refine(passwords, "studies", 3); passwords
['parties']
Oh regarde, ça doit être le mot de passe !
Alors, comment automatiser le choix des mots de passe à partir d'un pool ? Ce que nous pouvons faire, c'est regarder chaque option et voir, dans l'onglet le pire dans ce cas, combien de mots de passe cela nous laisse. Nous pouvons alors choisir celui qui présente le plus petit nombre d'options restantes dans le pire des cas. Ce mot de passe est celui qui a la meilleure garantie de réduire le champ.
Ce code vérifie chaque mot de passe contre chaque autre mot de passe contre chaque autre mot de passe pour trouver le meilleur candidat.
def get_next_guess(passwords):
scores = {}
for candidate in passwords:
results = []
remainder = (x for x in passwords if x != candidate)
for correct_pw in remainder:
no_alternatives = len(refine(remainder, candidate,
distance(candidate, correct_pw)))
results.append(no_alternatives)
scores[candidate] = max(results)
return min(scores, key = lambda x: scores[x])
Sur mon ordinateur, il devine immédiatement "parties", ce qui est une chance, car "battre" aurait été une autre bonne supposition. Regardons plutôt celui de la capture d'écran, où le mot de passe correct était 'WAITING'.
>>> passwords = ["cleanse", "grouped", "gaining", "wasting", "dusters", "letting", "endings", "fertile", "seeking", "certain", "bandits", "stating", "wanting", "parties", "waiting", "station", "maltase", "monster"]
>>> get_next_guess(passwords)
'wanting'
>>> #incorrect, 6/7 correct
>>> passwords = refine(passwords, "wanting", 6); passwords
['wasting', 'waiting']
Avec deux mots de passe restants, get_next_guess
devient essentiellement un jet de dé. Il suffit d'essayer le premier, puis le second, et vous avez terminé en trois essais, sans recommencer.
(Aparté amusant. Vous savez le lien que Colin D a partagé avec la liste des mots de passe à 12 caractères ? L'auteur a choisi APPRECIATION
. C'est en fait la meilleure hypothèse ! Dans ce cas, il ne vous reste pas plus que deux alternatives, quel que soit le mot de passe correct).
5 votes
D'ailleurs, cette question n'est pas spécifique à F:NV. Le même mini-jeu, avec exactement les mêmes solutions, existe dans Fallout 3.
0 votes
@sanmai Comme l'a fait valoir l'utilisateur galacticninja, cette question porte spécifiquement sur l'automatisation, et non sur l'optimisation ou le jeu effectif.