Dies ist ein Wortspiel aus einem Satz Aktivitätskarten für Kinder. Unterhalb der Regeln befindet sich Code, um das beste Triplet mit / usr / share / dict / words zu finden. Ich dachte, es sei ein interessantes Optimierungsproblem und frage mich, ob die Leute Verbesserungen finden können.
Regeln
- Wählen Sie jeweils einen Buchstaben aus den folgenden Sätzen.
- Wählen Sie ein Wort mit den gewählten Buchstaben (und allen anderen).
- Bewerte das Wort.
- Jeder Buchstabe aus dem gewählten Satz erhält die Nummer, die mit dem Satz angezeigt wird (Wiederholungen eingeschlossen).
AEIOU
0 zählen- Alle anderen Buchstaben sind -2
- Wiederholen Sie die obigen Schritte 1 bis 3 (keine weiteren Buchstaben in Schritt 1) noch zweimal.
- Die Endnote ist die Summe der drei Wortnoten.
Setzt
(Set 1 ergibt 1 Punkt, Set 2 ergibt 2 Punkte usw.)
- LTN
- RDS
- GBM
- KWK
- FWV
- YKJ
- QXZ
Code:
from itertools import permutations
import numpy as np
points = {'LTN' : 1,
'RDS' : 2,
'GBM' : 3,
'CHP' : 4,
'FWV' : 5,
'YKJ' : 6,
'QXZ' : 7}
def tonum(word):
word_array = np.zeros(26, dtype=np.int)
for l in word:
word_array[ord(l) - ord('A')] += 1
return word_array.reshape((26, 1))
def to_score_array(letters):
score_array = np.zeros(26, dtype=np.int) - 2
for v in 'AEIOU':
score_array[ord(v) - ord('A')] = 0
for idx, l in enumerate(letters):
score_array[ord(l) - ord('A')] = idx + 1
return np.matrix(score_array.reshape(1, 26))
def find_best_words():
wlist = [l.strip().upper() for l in open('/usr/share/dict/words') if l[0].lower() == l[0]]
wlist = [l for l in wlist if len(l) > 4]
orig = [l for l in wlist]
for rep in 'AEIOU':
wlist = [l.replace(rep, '') for l in wlist]
wlist = np.hstack([tonum(w) for w in wlist])
best = 0
ct = 0
bestwords = ()
for c1 in ['LTN']:
for c2 in permutations('RDS'):
for c3 in permutations('GBM'):
for c4 in permutations('CHP'):
for c5 in permutations('FWV'):
for c6 in permutations('YJK'):
for c7 in permutations('QZX'):
vals = [to_score_array(''.join(s)) for s in zip(c1, c2, c3, c4, c5, c6, c7)]
ct += 1
print ct, 6**6
scores1 = (vals[0] * wlist).A.flatten()
scores2 = (vals[1] * wlist).A.flatten()
scores3 = (vals[2] * wlist).A.flatten()
m1 = max(scores1)
m2 = max(scores2)
m3 = max(scores3)
if m1 + m2 + m3 > best:
print orig[scores1.argmax()], orig[scores2.argmax()], orig[scores3.argmax()], m1 + m2 + m3
best = m1 + m2 + m3
bestwords = (orig[scores1.argmax()], orig[scores2.argmax()], orig[scores3.argmax()])
return bestwords, best
if __name__ == '__main__':
import timeit
print timeit.timeit('print find_best_words()', 'from __main__ import find_best_words', number=1)
Die Matrix-Version ist das, was ich gefunden habe, nachdem ich eine in reinem Python (mit Wörterbüchern und unabhängig voneinander bewerteten Wörtern) und eine andere in Numpy geschrieben habe, aber mit Indexierung statt Matrix-Multiplikation.
Die nächste Optimierung wäre, die Vokale vollständig aus der Wertung zu entfernen (und eine modifizierte ord()
Funktion zu verwenden), aber ich frage mich, ob es noch schnellere Ansätze gibt.
EDIT : hinzugefügt timeit.timeit Code
BEARBEITEN : Ich füge ein Kopfgeld hinzu, das ich für jede Verbesserung gebe, die ich am meisten mag (oder möglicherweise für mehrere Antworten, aber ich muss mehr Ansehen aufbauen, wenn das der Fall ist).