「ロジック パズル」を解くための簡単なスクリプトを書きました。これは、多くの規則が与えられ、「A、B、C という名前の 5 人のミュージシャンがいます。 、D、および E がコンサートで演奏している場合、それぞれが次々に演奏します... A が B の前にあり、D が最後ではない場合...誰がいつ演奏するかの順序は何ですか?」等
可能な解決策を評価するために、各「ルール」を個別の関数として記述しました。この関数は、可能な解決策 (単純に文字列のリストとして表される) が有効かどうかを評価します。たとえば、
#Fifth slot must be B or D
def rule1(solution):
return solution[4] == 'B' or solution[4] == 'D'
#There must be at least two spots between A and B
def rule2(solution):
returns abs(solution.index('A') - solution.index('B')) >= 2
#etc...
最初のルールが失敗した後にルールの評価を停止する機能を備えた、可能な解決策がそのようなすべてのルールに合格するかどうかをテストする Pythonic の方法を見つけることに興味があります。
最初に、可能な限り単純なことを書きました。
def is_valid(solution):
return rule1(solution) and rule2(solution) and rule3(solution) and ...
しかし、これはかなり醜いようでした。リスト内包表記のようなものを使用して、これをもう少しエレガントに読むことができるのではないかと思いました...
def is_valid(solution)
rules = [rule1, rule2, rule3, rule4, ... ]
return all([r(solution) for f in rules])
all()
...しかし、関数が評価される前にリスト内包表記が生成されるため、これにはまったく短絡しないという副作用があることに気付きました-最初のルールが返された場合でも、すべてのルールが評価されますFalse
.
だから私の質問は:の長いリストを書き出す必要なしに、ショートサーキットを使用してTrue
/式のリストを評価できる、よりPythonic/機能的な方法はありますか?False
return f1(s) and f2(s) and f3(s) ...