2017-01-18 24 views
4

私は心をたくさん包み込み、それを理解できませんでした。 はバックトラックに、この形式のリストを生成するスクリプトを作成することが可能です:Prolog - バックトラックで交互にシンボルを生成する:[a]; [a、b]; [a、b、a]; [a、b、a、b]

[a] 
[a,b] 
[a,b,a] 
[a,b,a,b] 
... 

私は一度に2つの要素を生成し、1を作ったが、私の頭には「Aを生成1をしようとしてけがをし始めました次回の "b"と次の "a"というように続きます。ここで

は一度に2つの要素のためのスクリプトです:

ab([a]). 
ab([b,a|T]):-ab([a|T]). 
ab([a,b|T]):-ab([b|T]). 

答えて

7

リストを記述し、常にDCG表記を使用することを検討してください。

エッセンスに、それほど多くの追加の変数と引数を付けずに、説明したい内容のフォーカスを合わせることが非常に便利です。

たとえば、考えてみます。

 
abs --> [a], abs_rest. 

abs_rest --> []. 
abs_rest --> [b], ([] | abs). 

サンプルクエリと答えは:

 
?- phrase(abs, ABs). 
ABs = [a] ; 
ABs = [a, b] ; 
ABs = [a, b, a] ; 
ABs = [a, b, a, b] ; 
ABs = [a, b, a, b, a] ; 
ABs = [a, b, a, b, a, b] . 

は、この便利な形式論の詳細については、を参照してください!

+0

ありがとう! それは面白いです、それ以前にそれにつまずくことはなかったし、私は確かに私の大学のコースでそれを学ぶことはありません、それは貴重な情報です! 私は再帰殺しを訓練してスクリプトを作成しています。私はDCGが私の試験で受け入れられるかどうかわかりませんので、伝統的な方法で解決策を探しています:) –

+1

"伝統的な方法" 「読みにくい」という意味では、次のクエリを使用して、DCGに対応するプレーンなPrologコードを取得するだけです: '? - listing(abs // 0)、listing(abs_rest // 0)あなたのインストラクターにそれを渡して、おそらく同じことを表現するもっと複雑な方法があるときに、なぜ適合する形式を使用するのかという理由で、おそらくあなたが使えないより良い解決策があることを知っていますか? – mat

+0

伝統は、私が必要とするものを記述するのに最適な言葉ではありませんでした。 私は、Head、Tail、およびリストの再帰プロパティを使用してのみ記述しています。そのような方法で: ab([a])。 ab([b、a | T]): - ab([a | T])。 ab([a、b | T]): - ab([b | T])。 –

3

私は1つの問題のこれらのタイプのために可能な場合を使用する必要があります@matに同意します。

ここには別のルールがあります。

abs --> [a]. 
abs --> [a,b]. 
abs --> [a,b], abs. 

?- phrase(abs, Ls). 
Ls = [a] ; 
Ls = [a, b] ; 
Ls = [a, b, a] ; 
Ls = [a, b, a, b] ; 
Ls = [a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a, b, a] 

興味深いことに、これらのルールは、あなたがDCGを使用しない場合は、その後、私はあること@matに同意すると示唆Using Definite Clause Grammars in SWI-Prolog

から演習の一つであり、この変化

abs2 --> []. 
abs2 --> [a]. 
abs2 --> [a,b], abs2. 

?- phrase(abs2, Ls). 
Ls = [] ; 
Ls = [a] ; 
Ls = [a, b] ; 
Ls = [a, b, a] ; 
Ls = [a, b, a, b] ; 
Ls = [a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b, a, b] 

から開始標準のProlog構文でDCGを表示するにはlisting/1を使用します。彼らはそのように使用することができ、通常のPrologルールとして

listing(abs). 

abs([a|A], A). 
abs([a, b|A], A). 
abs([a, b|A], B) :- 
     abs(A, B). 

listing(abs2). 

abs2(A, A). 
abs2([a|A], A). 
abs2([a, b|A], B) :- 
     abs2(A, B). 

abs(X,[]). 
X = [a] ; 
X = [a, b] ; 
X = [a, b, a] ; 
X = [a, b, a, b] ; 
X = [a, b, a, b, a] ; 
X = [a, b, a, b, a, b] ; 
X = [a, b, a, b, a, b, a] 

abs2(X,[]). 
X = [] ; 
X = [a] ; 
X = [a, b] ; 
X = [a, b, a] ; 
X = [a, b, a, b] ; 
X = [a, b, a, b, a] ; 
X = [a, b, a, b, a, b] 
+1

あなたがリンクしているテキストは、古い用語を使用しています。 – mat

+0

@mat私はSWI-Prologにおける「Definite Clause Grammarsの使用」を参照しています。私は他の同様の問題があることを示すためにリンクを追加しました。それは基本的にリンクの理由です。 –

+0

ありがとう、これをさらに説明するために、感謝! –

1

あなたが書いた述語はあまりにも一般的である:

?- ab([b,a]). 
true 

原因は次のルール

ab([b,a|T]) :- 
    ab([a|T]). 
です

あなたは、あなたの実際の問題を解決していない中間結果を浮かべてください。

ab([a]). 
ab([a|Xs]) :- 
    ba(Xs). 

ba([b]). 
ba([b|Xs]) :- 
    ab(Xs). 

また、あなたのようにabs考えることができます:これを修正するには、abシーケンスがaで始まり、残りの胸像がbaシーケンスが再びabの配列で定義されているbaシーケンスは、ことよりも述べることができ最後の要素がbであった場合はいつでも がaを生成し、その逆はステートマシンです。 我々は歴史をトレースする追加の引数を導入した場合、私たちは到着:

abs(a,[a]). 
abs(b,[b]). 
abs(a,[a|Xs]) :- 
    abs(b,Xs). 
abs(b,[b|Xs]) :- 
    abs(a,Xs). 

今、私たちは最後aを先頭に追加1としてabシーケンスを定義します。

ab(Xs) :- 
    abs(a,Xs). 

は楽しみを持って:)

関連する問題