プロローグワークアウト

旅行者、こんにちは。







これを読んだら、私が以前書いた「面白い」資料の継続をお勧めします。 少し考えて、3つの記事に分かれた場合、主なメッセージは、宣言的なアプローチに関心を示すことだけでした。 何らかの理由で、それがなければeSCuelが公開され必須にならなかったように、それは素晴らしいことではありません。なぜなら、それなしでは考えられないからです。 確かに、タスクを定式化することをお勧めします。これが何に変換されるか心配する必要はありません。







仕事に取り掛かる前に、あなたを楽しませるための試みについて書いたので、プロローグの使用例を引き続き示しますが、以前の記事では、Pythonに興味があり、さらには数千人の人々に興味を引き起こし、新しいバッテリーのニュースに興味があることを示していますテスラに、stotyschビューであり、この行動の背後に見てそれほど少なくないポータルrazrabotnichestskom、上のプログラムを書くためのコメントを読んだ上で認められた、そしておそらくそれらのFIVE、この提案ESCHの第二読会の後 それはより多くを読むべきだという考えを混乱させる...







興味の仮説が満たされていないことが判明したので、私はプロローグの使用方法を示します。これは現代的で開発中の自由に配布されたツールであり、それを取り入れて定式化することができます。







タイムトラベルは存在しないと言いますが、1週間前に行きます。テープの3つの部分について興味深いプロローグがありました。ランダムに遭遇した新しい問題を解決するトピックに触れたので、 この興味深いサイトを取り上げ、最も難しいタスク(文字列を数字に変えない))、 Prologでそれをやろうとします。







関心を高めるのをやめて、始めましょう...







タスク446arithmetic -slices-ii-subsequence



数字のシーケンスは、少なくとも3つの要素で構成され、連続する2つの要素の差が同じ場合、算術と呼ばれます。

たとえば、これらは算術シーケンスです。

1、3、5、7、9

7、7、7、7

3、-1、-5、-9

次のシーケンスは算術ではありません。

1、1、2、5、7

全体として、2つの隣人の違いは保持されるべきであり、これをチェックするだけでいいのでしょうか?

続きを読む:







N個の数字で構成されるゼロインデックス配列Aが与えられます。 その配列のサブシーケンススライスは、0≤P0 <P1 <... <Pk <Nのような整数のシーケンス(P0、P1、...、Pk)です。

配列Aのサブシーケンススライス(P0、P1、...、Pk)は、シーケンスA [P0]、A [P1]、...、A [Pk-1]、A [Pk]が算術である場合、算術と呼ばれます。 。 特に、これはk≥2を意味します。

この関数は、配列Aの算術サブシーケンススライスの数を返す必要があります。

文句を言うと、隣接するアイテムの違いが変わらないように、会うことができるスライスの数、見つけることができるサブリストのオプションの数を見つける必要があります。







これは、サブリストが入力リストのすべての順列の1つの大きなセットにあるかのようです。







例:

入力:[2、4、6、8、10]

出力:7

説明:

すべての算術サブシーケンススライスは次のとおりです。

[2,4,6]

[4,6,8]

[6,8,10]

[2,4,6,8]

[4,6,8,10]

[2,4,6,8,10]

[2,6,10]

私はプロローグでサブリストを表現する方法を知っています、これ:







sublists(InputList, SubList):- append(Prefix,Root,InputList), append(SubList,Suffix,Root).
      
      





目的のタイプのリストを確認する方法-トリプルをチェックインする必要があります。







 is_seq(A,B,C]):-AB =:=BC. is_seq(A,B,C|Tail]):-AB =:=BC, is_seq(B,C|Tail]).
      
      





リストのすべての要素の順列を破棄すると、これは単に近くにある要素のサブリストではなく、要素を省略して形成されたサブリストであることがわかります。







次に、次のように配置します。







 seq(_,[]). seq([H|T],[H|T1]):-seq(T,T1). seq([_|T],T1):-seq(T,T1).
      
      





このようなルールは、リストからすべての可能なサブリストを返しますが、1つの要素から開始することも、次の要素からスキップすることによって、最後に任意の数量を破棄することもできます。







合計すると、過大評価された数の解が得られます。空のリストが何度も返されることはすぐに明らかであり、要素が最後からドロップされると繰り返しを避けることができません。







この問題に対して提案されたテストをレビューした後、入力に重複した値が存在する可能性があり、そのようなリスト[0,1,2,2,2]には4つのソリューションがあるはずです。 各2-kaは個別に取得できます。これは、合計で3つのオプション[0,1,2]と1つの[2,2,2]が適切な個別のスライスと見なされる必要があります。







シーケンスジェネレーターは重複する値を生成するため、これは不運ですが、計算を一意にする方法は? それらをマークし、リストを互いに異なるものにする必要があります。 リストの生成、状態の確認、ソリューションの数のカウントに基づいてソリューション全体を構築します。 そして、決定の繰り返しをどうするか...







要素の簡単な番号付けを行い、リストをコンポーネントの値/インデックス、構造化された用語のリストに変えます。これは彼らがそれを呼ぶものです。 上記の例では、これは[0 / 1,1 / 2,2 / 3,2 / 4,2 / 5]になります。 この入力によって生成されるシーケンスはすべて異なります。







したがって、リストをマークされたリストに変えることができます。







 label([],[],_). label([A|T],[A/N|T1],N):-N1 is N+1, label(T,T1,N1).
      
      





さて、そして最も重要な点は、is_seq算術をチェックすることで、マークされたリストを考慮に入れて一連の試行を行った後、このルールはかなり複雑な式に変わりました。 ここで、数値のトリプルが条件に対応していることを確認し、この特定のソリューションのキーを計算します。一意のソリューションを除外するには、キーが必要でした。これは、リスト内のすべてのキーを収集してからカウントするのに役立ちます。







入力がマークされたリストである場合、出力はキー値になり、各要素の値とインデックスの合計が数字である整数として計算されます。







 %is_seq ,  ,  is_seq([A/An,B/Bn,C/Cn],2,N):- AB=:=BC, N is 10000*(A+An)+100*(B+Bn)+(C+Cn). is_seq([A/An,B/Bn,C/Cn|T],K,N):- AB=:=BC, is_seq([B/Bn,C/Cn|T],K1,N1), K is K1+1, N is N1+(A+An)*(100**K).
      
      





すべてのソリューションを数えるために、組み込み機能を使用して目標を達成し、すべての固有のソリューションをsetof()リストに収集します。 すべてのシーケンスのリストを単純にコンパイルすることは完全に無効であることが判明しました。ここから、より単純な値としてのキーのアイデアが生まれました。







 get_number(List,N) :- label(List,ListL,1), setof(Len,K^Sub^(seq(ListL,Sub),is_seq(Sub,K,Len)),Result), length(Result,N),!. get_number(_,0).
      
      





もちろん、このようなソリューションではパフォーマンスは特に表現されませんでした。







以下に、テストのリストを含むプログラムの完全なテキストを示します。これは、タスクを使用してサイトから筋金入りに抽出されたものです(これはテストの一部にすぎません)。







 label([],[],_). label([A|T],[A/N|T1],N):-N1 is N+1, label(T,T1,N1). seq(_,[]). seq([H|T],[H|T1]):-seq(T,T1). seq([_|T],T1):-seq(T,T1). is_seq([A/An,B/Bn,C/Cn],2,N):- AB=:=BC, N is 10000*(A+An)+100*(B+Bn)+(C+Cn). is_seq([A/An,B/Bn,C/Cn|T],K,N):- AB=:=BC, is_seq([B/Bn,C/Cn|T],K1,N1), K is K1+1, N is N1+(A+An)*(100**K). get_number(List,N) :- label(List,ListL,1),setof(Len,K^Sub^(seq(ListL,Sub),is_seq(Sub,K,Len)),Result), length(Result,N),!. get_number(_,0). %unit-tests framework assert_are_equal(Goal, false):-get_time(St),not(Goal),!,get_time(Fin),Per is round(Fin-St),writeln(Goal->ok:Per/sec). assert_are_equal(Goal, true):- get_time(St),Goal, !,get_time(Fin),Per is round(Fin-St),writeln(Goal->ok:Per/sec). assert_are_equal(Goal, Exp):-writeln(Goal->failed:expected-Exp). %all test :-assert_are_equal(get_number([2,4,6,8,10],7),true). :-assert_are_equal(get_number([],0),true). :-assert_are_equal(get_number([1],0),true). :-assert_are_equal(get_number([1,2],0),true). :-assert_are_equal(get_number([1,2,3],1),true). :-assert_are_equal(get_number([1,2,3,4],3),true). :-assert_are_equal(get_number([1,2,3,4,5],7),true). :-assert_are_equal(get_number([1,2,3,4,5,6],12),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7],20),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8],29),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8,9],41),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8,9,10],55),true). :-assert_are_equal(get_number([2,2,3,4],2),true). :-assert_are_equal(get_number([0,1,2,2,2],4),true). :-assert_are_equal(get_number([0,2000000000,-294967296],0),true). :-assert_are_equal(get_number([1,1,1],1),true). :-assert_are_equal(get_number([1,1,1,1],5),true). :-assert_are_equal(get_number([1,1,1,1,1],16),true). :-assert_are_equal(get_number([1,1,1,1,1,1],42),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1],99),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1],219),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1],466),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1],968),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1],1981),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1],4017),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1],8100),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1],16278),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],32647),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],65399),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],130918),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],261972),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],524097),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],1048365),true).
      
      





残念な結果として、次のような効率が得られます。







 get_number([2, 4, 6, 8, 10], 7)->ok:0/sec get_number([], 0)->ok:0/sec get_number([1], 0)->ok:0/sec get_number([1, 2], 0)->ok:0/sec get_number([1, 2, 3], 1)->ok:0/sec get_number([1, 2, 3, 4], 3)->ok:0/sec get_number([1, 2, 3, 4, 5], 7)->ok:0/sec get_number([1, 2, 3, 4, 5, 6], 12)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7], 20)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8], 29)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8, 9], 41)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 55)->ok:0/sec get_number([2, 2, 3, 4], 2)->ok:0/sec get_number([0, 1, 2, 2, 2], 4)->ok:0/sec get_number([0, 2000000000, -294967296], 0)->ok:0/sec get_number([1, 1, 1], 1)->ok:0/sec get_number([1, 1, 1, 1], 5)->ok:0/sec get_number([1, 1, 1, 1, 1], 16)->ok:0/sec get_number([1, 1, 1, 1, 1, 1], 42)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1], 99)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1], 219)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1], 466)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 968)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 1981)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 4017)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 8100)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 16278)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 32647)->ok:1/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 65399)->ok:1/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 130918)->ok:3/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 261972)->ok:6/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 524097)->ok:12/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 1048365)->ok:27/sec
      
      





決定キーだけでさえリストを収集することは非常に面倒ですが、それは宣言的な決定であり、それなしではすべてのユニークなソリューションを数えることはできません。







結論。



これがProlog言語でのタスクの定式化であり、問​​題のステートメントをプログラムに単純に転送するだけでは効率が不十分です。 それとも、この問題ではアルゴリズムによる解決策しか利用できないのでしょうか? プロセスはどのくらい複雑ですか?







再び質問を残します...







それでも、私たちの職業では、答えを探すことは興味深いですよね?








All Articles