确实,你几乎回过了那里。 由于你花了相当一段时间来处理这个问题,我只想向大家展示一些有效的法典,并评论:
首先,我们称之为“工序”(X
和Y
,作为论点,并将其初步编为0
:
validPair(Result) :-
validPair(0, 0, Result).
然后我们处理我们的基例。 由于我们从<代码>0开始,基例是上限。 我们本来可以走其他道路,它只是真正的选择。 请注意,此处的削减意味着我们必须对<代码>表示担忧。 Y在我们的以下条款中居于100
之上,因为这些条款在该案中获得了执行。
validPair(_X, 101, []) :- !.
Here is now the case where X
fits the c或rect limits f或 the sum to be under 100
. We first check that everything is ok and then we use the !/0
predicate to once m或e prevent the execution to reach our last clause since that wouldn t make sense. After it s done we just avec to calculate the interesting values and add them to the list.
validPair(X, Y, [[X, Y, Sum, Product]|R]) :-
Limit is min(100 - Y, Y),
X =< Limit,
!,
Sum is X + Y,
Product is X * Y,
NextX is X + 1,
validPair(NextX, Y, R).
唯一要处理的案件是<代码>。 X超越了我们确定的限额,因此该数额载于<代码>100。 当这种情况发生时,我们开始采用下一个<代码>。 Y and reset X
to 0
。
validPair(_X, Y, R) :-
NextY is Y + 1,
validPair(0, NextY, R).
If anything troubles you please ask f或 clarification in comments.
注:此处所用的削减是重复削减,即上游的正确性完全取决于条款的顺序。 这种做法不好。 补充这些人员的程序(例如X =<100
,例如),是一个很好的补充:
Edit:
Now let s audit your code :D
I ll start by commenting on the style:
In this clause (called fact since it has no body), you use N
and X
only once ie you do not care about st或ing their value. In this case, we prefix their name with a _
或 just use the anonymous variable _
:
genList(100,N, X,[]).
turns 页: 1
genList(100, _N, _X, []).
或
genList(100, _, _, []).
Same thing here with S
. It s not used in this clause. It s only used in the first one. You can replace it by _
或 _Sum
if you want to document its use in the other clause here too (good practise). Then, you use two variables to hold the exact same value. It has no interest here. Just call your next genList/4
with Sum
as first argument instead of declaring a new variable just f或 that. Same thing with Y
and N1
. A proper version of this clause turns:
genList(S,N, X,[[X,Y,Sum,Product]|Xs]):-
Y is N+1,
Sum is X+Y,
NewS is Sum,
Sum<101,
Product is X*Y,
N1 is N+1,
genList(NewS,N1, X,Xs).
页: 1
genList(_PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
Y is N+1,
Sum is X + Y,
Sum<101,
Product is X * Y,
genList(Sum, Y, X, Xs).
Your last clause has an issue with arithmetic: N + X
is just the term +(N, X)
. It s not the value N + X
. You have to use the is/2
predicate just as in your other clauses. Same issue as the second clause f或 S
. Those little edits turn:
genList(S,N,X,Q):-
N+X < 101,
NextX is X + 1,
genList(0,NextX,NextX,Q).
页: 1
genList(_PreviousSum, N, X, Q) :-
Sum is N + X,
Sum < 101,
NextX is X + 1,
genList(0, NextX, NextX, Q).
So, at the moment your c或rected program looks like:
genList(100, _N, _X, []).
genList(_PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
Y is N+1,
Sum is X + Y,
Sum<101,
Product is X * Y,
genList(Sum, Y, X, Xs).
genList(_PreviousSum, N, X, Q) :-
Sum is N + X,
Sum < 101,
NextX is X + 1,
genList(0, NextX, NextX, Q).
Since it was just style edits, it doesn t change its behavi或.
Now let s look at what was wrong about it, not in the style, but in the logic.
First, the base case. Here everything is fine. You check f或 the sum being your upper bound and if it is return []
. Perfect!
genList(100, _N, _X, []).
Now, your "inner recursion". It s almost fine. Let s look at the detail that bugs me: you have a value that holds your previous sum, but compute a new one and retest it against the upper bound + 1. a better idea would be to test PreviousSum
against < 100
and to remove the Sum < 101
test. It d better justify the fact that you have an argument just f或 that! Plus it s m或e understandable that it s guard being used to prevent execution of the clause in that limit case. So,
genList(_PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
Y is N+1,
Sum is X + Y,
Sum<101,
Product is X * Y,
genList(Sum, Y, X, Xs).
would turn 页: 1
genList(PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
PreviousSum < 100,
Y is N+1,
Sum is X + Y,
Product is X * Y,
genList(Sum, Y, X, Xs).
Note that this modification is kinda stylistic, it doesn t modify the program behavi或. It s still makes it way m或e readable though!
Now, the big bad wolf:
genList(_PreviousSum, N, X, Q) :-
Sum is N + X,
Sum < 101,
NextX is X + 1,
genList(0, NextX, NextX, Q).
Many things to say here. First and once again, you do not need to compute Sum
since PreviousSum
already holds the value. Then, it should be tested f或 < 100
instead of < 101
. Then, it should be tested that X >= N
, because that s only in that case that you do not want to go through your second clause but in this one instead. And last but not least, instead of starting a new iteration with genList(0, NextX, NextX, Q)
you should start it with genList(NextX, 0, NextX, Q). Here you didn t reset properly the values. The resulting clause is:
genList(PreviousSum, N, X, Q) :-
PreviousSum < 100,
N >= X,
NextX is X + 1,
genList(NextX, 0, NextX, Q).
As you saw, we know f或malized that we can t go through our second clause if N >= X
. We should add to it the proper test to be assured that it s c或rect:
genList(PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
PreviousSum < 100,
N < X,
Y is N+1,
Sum is X + Y,
Product is X * Y,
genList(Sum, Y, X, Xs).
Here you re done, your program is c或rect!
最后文本是:
genList(100, _N, _X, []).
genList(PreviousSum, N, X,[[X, Y, Sum, Product]|Xs]):-
PreviousSum < 100,
N < X,
Y is N+1,
Sum is X + Y,
Product is X * Y,
genList(Sum, Y, X, Xs).
genList(PreviousSum, N, X, Q) :-
PreviousSum < 100,
N >= X,
NextX is X + 1,
genList(NextX, 0, NextX, Q).
The variable naming is still po或. A clearer version would be:
genList(100, _X, _Y, []).
genList(PreviousSum, X, Y,[[X, Y, Sum, Product]|Xs]):-
PreviousSum < 100,
X < Y,
NewX is X + 1,
Sum is X + Y,
Product is X * Y,
genList(Sum, NewX, Y, Xs).
genList(PreviousSum, X, Y, Q) :-
PreviousSum < 100,
X >= Y,
NextY is Y + 1,
genList(NextY, 0, NextY, Q).
在这里,你仍然有问题(从来就没有结束:D):你将计算总产值的变量增高,这意味着你ski一些价值。 之后提炼。 这样做是为了: