あなたが投稿の最後に言及したソルバーを書きましたが、コードがあまり読みにくいことを前もってお詫びします。
この種の問題に対するソルバーのコードは、本質的には深さ優先検索であり、既に機能していることを意味します。
「左から右に解決される括弧を使用しないソリューション」を使用する場合、解決できない入力セットがあることに注意してください。たとえば、ターゲットが 144 の 11,11,11,11,11,11 です。解は ((11/11)+11)*((11/11)+11) です。私のソルバーは、括弧を別の行に分割することで人間が理解しやすくしていますが、左から右に評価するのではなく、効果的に括弧を使用しています。
「括弧を使用する」方法は、操作を入力の 1 つとアキュムレータに適用するのではなく、入力に操作を適用して結果を入力バッグに戻すことです。たとえば、入力バッグが 1,2,3,4,5,6 で、3 と 4 を乗算すると、バッグは 1,2,12,5,6 になります。このように、再帰する場合、そのステップは前のステップの結果を使用できます。これを出力用に準備するのは、操作の履歴を各番号とともにバッグに格納する場合にすぎません。
より「洗練された」ソリューションについてあなたが何を意味しているのかは、私のjavascriptソルバーで使用されているシンプルなヒューリスティックに過ぎないと思います。ソルバーは、検索空間全体の深さ優先検索を実行し、最も少ないステップを使用するソリューションだけでなく、「最適な」ソリューションを選択することによって機能します。
解がターゲットに近い場合、その解は以前の解よりも「優れている」と見なされます (つまり、それを「答え」解として置き換えます) (ソルバー内の任意の状態が候補解であることに注意してください。それは、ほとんどがより離れているということです)。ターゲットからの距離が等しく、ヒューリスティック スコアが低い場合。
ヒューリスティック スコアは、末尾の 0 が削除された「中間値」(つまり、「=」記号の右側の値) の合計です。たとえば、中間値が 1、4、10、150 の場合、ヒューリスティック スコアは 1+4+1+15 です。10 と 150 は、ゼロで終わるため、1 と 15 としてのみカウントされます。これは、人間は 10 で割り切れる数を扱う方が簡単であると判断し、解決策が「より単純」に見えるためです。
「洗練された」と見なすことができるもう1つの部分は、いくつかの行が一緒に結合される方法です. これは単に「5 + 3 = 8」と「8 + 2 = 10」の結果を「5 + 3 + 2 = 10」に結合するだけです。これを行うコードは絶対に恐ろしいものですが、興味がある場合は、すべてhttps://github.com/jes/cntdn/blob/master/js/cntdn.jsのJavascriptにあります。配列形式で格納されているソリューション (各数値がどのように作成されたかに関する情報を含む) では、一連の後処理が行われます。だいたい:
- DFS から生成された「ソリューション リスト」を (初歩的な、ネストされた配列ベースの) 式ツリーに変換します。これは、複数引数の場合に対処するためです (つまり、「5 + 3 + 2」は 2 つの加算演算ではなく、 3 つの引数を持つ 1 つの加算のみ)
- 式ツリーをステップの配列に変換します。これには、引数がより一貫して表示されるようにソートすることも含まれます
- ステップの配列を文字列表現に変換して、ユーザーに表示します。結果が等しくない場合は、結果がターゲット番号からどれだけ離れているかの説明が含まれます
その長さについてお詫び申し上げます。うまくいけば、それのいくつかは役に立ちます。
ジェームズ
編集: カウントダウン ソルバー全般に興味がある場合は、数字の 1 よりもはるかにエレガントな私の文字ソルバーをご覧になることをお勧めします。これはhttps://github.com/jes/cntdn/blob/master/js/cntdn.jsの上位 2 つの関数です。文字列と一致するすべての単語に対して呼び出される関数を使用して、solve_letters() の呼び出しを使用します。このソルバーは、ディクショナリを表すトライ ( https://github.com/jes/cntdn/blob/master/js/mk-js-dictによって生成) をトラバースし、すべてのエンド ノードでコールバックを呼び出すことによって機能します。