1। परिचय
इस समस्या से व्यवस्थित तरीके से संपर्क करने का एक तरीका है: यदि आपके पास एक एल्गोरिथम है जो जल्लाद की भूमिका निभाता है, तो आप प्रत्येक शब्द की कठिनाई को गलत अनुमानों की संख्या मान सकते हैं जो कि उस शब्द का अनुमान लगाने पर आपके प्रोग्राम को ले जाएगा।
2. जल्लाद की रणनीति पर
एक विचार है जो कुछ अन्य उत्तरों और टिप्पणियों में निहित है, कि सॉल्वर के लिए इष्टतम रणनीति अंग्रेजी में अक्षरों की आवृत्ति पर या कुछ कॉर्पस में शब्दों की आवृत्ति पर उनके निर्णयों को आधार बनाना होगा। यह एक मोहक विचार है, लेकिन यह बिल्कुल सही नहीं है। सॉल्वर सबसे अच्छा करता है अगर वह सेटर द्वारा चुने गए शब्दों के वितरण को सही ढंग से मॉडल करता है , और एक मानव सेटर अच्छी तरह से अपनी दुर्लभता या अक्सर उपयोग किए जाने वाले पत्रों से बचने के आधार पर शब्दों का चयन कर सकता है। उदाहरण के लिए, हालांकि Eअंग्रेजी में सर्वाधिक उपयोग होने वाले पत्र है, अगर सेटर हमेशा शब्द से चुनता है JUGFUL, RHYTHM, SYZYGY, और ZYTHUM, फिर एक आदर्श solver का अनुमान लगाकर शुरू नहीं करता हैE !
सेटर को मॉडलिंग करने का सबसे अच्छा तरीका संदर्भ पर निर्भर करता है, लेकिन मुझे लगता है कि कुछ प्रकार के बायेसियन आगमनात्मक निष्कर्ष एक संदर्भ में अच्छी तरह से काम करेंगे जहां सॉल्वर एक ही सेटर के खिलाफ या इसी तरह के बसने वालों के समूह के खिलाफ कई गेम खेलता है।
3. एक जल्लाद एल्गोरिदम
यहाँ मैं एक ऐसे सॉल्वर की रूपरेखा तैयार करूँगा जो बहुत अच्छा है (लेकिन एकदम सही से बहुत दूर)। यह सेटर को एक निश्चित शब्दकोष से समान रूप से शब्द चुनने के रूप में प्रस्तुत करता है। यह एक लालची एल्गोरिथ्म है : प्रत्येक चरण में यह उस पत्र का अनुमान लगाता है जो यादों की संख्या को कम करता है, अर्थात ऐसे शब्द जिनमें अनुमान शामिल नहीं है। उदाहरण के लिए, यदि कोई अनुमान अभी तक नहीं लगाया गया है, और संभव शब्द हैं DEED, DEADऔर DAREफिर:
- यदि आप अनुमान लगाते हैं
DयाE , कोई चूक नहीं है;
- यदि आप अनुमान लगाते हैं
A, तो एक मिस ( DEED) है;
- यदि आप अनुमान लगाते हैं
R, तो दो मिस ( DEEDऔर DEAD) हैं;
- यदि आप किसी अन्य पत्र का अनुमान लगाते हैं, तो तीन मिस हैं।
तो या तो Dया Eइस स्थिति में एक अच्छा अनुमान है।
( टिप्पणी में कर्नल पैनिक के लिए धन्यवाद कि सही अनुमान लगाने वाले जल्लाद में स्वतंत्र हैं - मैं अपने प्रयास में इसे पूरी तरह से भूल गया!)
4. कार्यान्वयन
यहाँ पायथन में इस एल्गोरिथ्म का कार्यान्वयन है:
from collections import defaultdict
from string import ascii_lowercase
def partition(guess, words):
"""Apply the single letter 'guess' to the sequence 'words' and return
a dictionary mapping the pattern of occurrences of 'guess' in a
word to the list of words with that pattern.
>>> words = 'deed even eyes mews peep star'.split()
>>> sorted(list(partition('e', words).items()))
[(0, ['star']), (2, ['mews']), (5, ['even', 'eyes']), (6, ['deed', 'peep'])]
"""
result = defaultdict(list)
for word in words:
key = sum(1 << i for i, letter in enumerate(word) if letter == guess)
result[key].append(word)
return result
def guess_cost(guess, words):
"""Return the cost of a guess, namely the number of words that don't
contain the guess.
>>> words = 'deed even eyes mews peep star'.split()
>>> guess_cost('e', words)
1
>>> guess_cost('s', words)
3
"""
return sum(guess not in word for word in words)
def word_guesses(words, wrong = 0, letters = ''):
"""Given the collection 'words' that match all letters guessed so far,
generate tuples (wrong, nguesses, word, guesses) where
'word' is the word that was guessed;
'guesses' is the sequence of letters guessed;
'wrong' is the number of these guesses that were wrong;
'nguesses' is len(guesses).
>>> words = 'deed even eyes heel mere peep star'.split()
>>> from pprint import pprint
>>> pprint(sorted(word_guesses(words)))
[(0, 1, 'mere', 'e'),
(0, 2, 'deed', 'ed'),
(0, 2, 'even', 'en'),
(1, 1, 'star', 'e'),
(1, 2, 'eyes', 'en'),
(1, 3, 'heel', 'edh'),
(2, 3, 'peep', 'edh')]
"""
if len(words) == 1:
yield wrong, len(letters), words[0], letters
return
best_guess = min((g for g in ascii_lowercase if g not in letters),
key = lambda g:guess_cost(g, words))
best_partition = partition(best_guess, words)
letters += best_guess
for pattern, words in best_partition.items():
for guess in word_guesses(words, wrong + (pattern == 0), letters):
yield guess
5. उदाहरण के परिणाम
इस रणनीति का उपयोग करके एक संग्रह में प्रत्येक शब्द का अनुमान लगाने की कठिनाई का मूल्यांकन करना संभव है। यहाँ मैं अपने सिस्टम डिक्शनरी में छः अक्षरों वाले शब्दों पर विचार करता हूँ:
>>> words = [w.strip() for w in open('/usr/share/dict/words') if w.lower() == w]
>>> six_letter_words = set(w for w in words if len(w) == 6)
>>> len(six_letter_words)
15066
>>> results = sorted(word_guesses(six_letter_words))
इस शब्दकोश में अनुमान लगाने के लिए सबसे आसान शब्द (साथ में अनुमान लगाने के लिए आवश्यक अनुमानों के अनुक्रम के साथ) निम्नानुसार हैं:
>>> from pprint import pprint
>>> pprint(results[:10])
[(0, 1, 'eelery', 'e'),
(0, 2, 'coneen', 'en'),
(0, 2, 'earlet', 'er'),
(0, 2, 'earner', 'er'),
(0, 2, 'edgrew', 'er'),
(0, 2, 'eerily', 'el'),
(0, 2, 'egence', 'eg'),
(0, 2, 'eleven', 'el'),
(0, 2, 'enaena', 'en'),
(0, 2, 'ennead', 'en')]
और सबसे कठिन शब्द ये हैं:
>>> pprint(results[-10:])
[(12, 16, 'buzzer', 'eraoiutlnsmdbcfg'),
(12, 16, 'cuffer', 'eraoiutlnsmdbpgc'),
(12, 16, 'jugger', 'eraoiutlnsmdbpgh'),
(12, 16, 'pugger', 'eraoiutlnsmdbpcf'),
(12, 16, 'suddle', 'eaioulbrdcfghmnp'),
(12, 16, 'yucker', 'eraoiutlnsmdbpgc'),
(12, 16, 'zipper', 'eraoinltsdgcbpjk'),
(12, 17, 'tuzzle', 'eaioulbrdcgszmnpt'),
(13, 16, 'wuzzer', 'eraoiutlnsmdbpgc'),
(13, 17, 'wuzzle', 'eaioulbrdcgszmnpt')]
इसका कारण यह है कि आप कठिन हैं क्योंकि आपने अनुमान लगाया है -UZZLE, आपके पास अभी भी सात संभावनाएं शेष हैं:
>>> ' '.join(sorted(w for w in six_letter_words if w.endswith('uzzle')))
'buzzle guzzle muzzle nuzzle puzzle tuzzle wuzzle'
6. वर्डलिस्ट की पसंद
बेशक, अपने बच्चों के लिए शब्दसूची तैयार करते समय आप अपने कंप्यूटर के सिस्टम शब्दकोश से शुरू नहीं करेंगे, आप उन शब्दों की एक सूची के साथ शुरू करेंगे, जो आपको लगता है कि वे जानने की संभावना है। उदाहरण के लिए, आप विभिन्न अंग्रेजी कॉर्पोरा में सबसे अधिक इस्तेमाल किए जाने वाले शब्दों की विकिपीडिया की सूची पर एक नज़र डाल सकते हैं ।
उदाहरण के लिए, 2006 के प्रोजेक्ट गुटेनबर्ग में 10,000 सबसे आम शब्दों में 1,700 छह-अक्षर शब्दों में से , सबसे कठिन शब्द हैं:
[(6, 10, 'losing', 'eaoignvwch'),
(6, 10, 'monkey', 'erdstaoync'),
(6, 10, 'pulled', 'erdaioupfh'),
(6, 10, 'slaves', 'erdsacthkl'),
(6, 10, 'supper', 'eriaoubsfm'),
(6, 11, 'hunter', 'eriaoubshng'),
(6, 11, 'nought', 'eaoiustghbf'),
(6, 11, 'wounds', 'eaoiusdnhpr'),
(6, 11, 'wright', 'eaoithglrbf'),
(7, 10, 'soames', 'erdsacthkl')]
(सॉम्स फोर्से जॉन गॉल्सवर्थी द्वारा फोर्सेट सागा में एक चरित्र है ; शब्द-सूची को निचले-मामले में बदल दिया गया है, इसलिए मेरे लिए उचित नाम जल्दी से निकालना संभव नहीं था।)
f(w) = (# unique letters) * (7 - # vowels) * (sum of the positions of unique letters in a list, ordered by frequency)। वहां से, आप फ़ंक्शन की सीमा को तीन खंडों में विभाजित कर सकते हैं और अपनी कठिनाइयों को बुला सकते हैं।