2017-06-05 5 views
3

findallやnumlistなどの述語を使用せずに、Nから1までの数字のリストを生成しようとしています。私は間違って何をしていますか?プロローグで数字のリストをfront Nにする

pred(N,[H|T]):- H is N, N1 is N-1, pred(N1,T). 
    pred(1,[]). 

私はエラーを取得しておく:グローバルスタックのうち

+0

'H is N'は必要ありません(' is/2'は算術式評価用です - ドキュメントを参照)。あなたは 'pred(N、[N | T]):N1はN-1、pred(N1、T) 'と置くことができます。この節の値は何でもかまいませんか?無限再帰を避けるためには条件が必要です。 – lurker

+0

また、あなたの基本ケースが間違っています。 1から1までの数字のリストは本当に空のリスト '[]'ですか? – lurker

+0

私は節の順序を入れ替え、HをNにした。また、pred(1、[])に0を入れた。ありがとうございました ! – Akimm231

答えて

1

はあなたの句の順序を切り替えます。最初に2番目の節を置きます。そうでない場合は、寄与する(つまり停止する)機会がなく、最初の節は負の無限大までカウントダウンし続けます。

もちろん、最初の句に最初の目標として単純なテストを追加することによって、2つの句を相互に排他的にすることは、さらに優れています。

+0

ありがとうございます!出来た 。 – Akimm231

2

最も完全なソリューションは次のようになります。

pred(1, [1]). 
pred(N, [N|T]) :- 
    N > 1, 
    N1 is N-1, 
    pred(N1, T). 

あなたはまだスタックオーバーフローを得ることができますN > 1条件なし:

| ?- pred(3, L). 

L = [3,2,1] ? ; 

Fatal Error: global stack overflow (size: 32768 Kb, reached: 32765 Kb, environment variable used: GLOBALSZ) 

しかしN > 1条件付き:

| ?- pred(3, L). 

L = [3,2,1] ? ; 

(1 ms) no 
| ?- 

また、正しい条件では、述語の順序もはや重要ではない。これは、あなたの句が適切になってから、想定される条件の下でのみ動作するためです。それがなければ、あなたのpred(N, [N|T]) :- ...句は、がN =< 1のときに実行しようとするときにのみ動作するように意図されています。句の順序を入れ替えるだけで、この問題が隠されます。しかし、効率を上げるためには、秩序が重要になります。

関連する問題