问题
I have the following predicate execute(actualState, instruction, nextState):-
such that when executing with the instructions: move, swap
, i have the following solutions:
?- executed(regs(1,4,*,+,2), swap(1,2), NS).
solution:
NS = regs(4,1,*,+,2)?;
no
?- executed(regs(1,4,3,6,+), move(4), NS).
solution:
NS = regs(1,4,3,6,6)?;
no
How can I implement it?
what I want it to do is that it has an initial state, an instruction and a final state "executed (actualState, instruction, nextState)" and what I want to do is pass it a list of registers as initial state, for example "regs (1,2,3,4)
" and an instruction, for example, move and swap. swap (swap the position X
, X + 1
) and move (copy what is in X
and deposit it in X + 1
) and what I want it to return, as final state, are the examples described in the statement of my question.
回答1:
I would take the following approach. The key elements of this solution are:
Use of
nth1/3
for considering an element of a list at a specified position=../2
for mapping between a term with arguments and a listA "substitution" predicate that substitutes a value at specified position in a list with another
subst([_|T], Y, 1, [Y|T]).
subst([X|T], Y, N, [X|T1]) :-
N #> 1,
N1 #= N - 1,
subst(T, Y, N1, T1).
executed(AS, swap(X,Y), NS) :-
AS =.. [regs|P],
nth1(X, P, Xe),
nth1(Y, P, Ye),
subst(P, Ye, X, P1),
subst(P1, Xe, Y, P2),
NS =.. [regs|P2].
executed(AS, move(X), NS) :-
AS =.. [regs|P],
nth1(X, P, Xe),
X1 #= X + 1,
subst(P, Xe, X1, P1),
NS =.. [regs|P1].
If you are using SWI prolog, you'll need to include the clpfd library, :- use_module(library(clpfd)).
. Also some Prologs, such as Ciao Prolog, does not have nth1/3
. Ciao does provide, however, nth/3
which has the same behavior, so it may be substituted.
Note that I'm using CLP(FD) here for more generality. If your system doesn't support CLP(FD) you can use is
in place of #=
, although it's less desirable.
Note that this solution works as long as the arguments indexing the registers are "in range". So it will fail on executed(regs(1,2,+), move(3), NS).
. As an exercise, if this is required, you should try to enhance this solution to meet that need. It will help you to learn Prolog versus being given every detail of the solution.
回答2:
Here is a solution of swap. The key is term to list =..
.
The rest is to dissect the list and put it back together.
Move is a piece of cake based on this answer and I left it "as an exercise"
:- use_module(library(lists)).
executed(H,swap(X,Y),Result):-
H =.. [regs|TH],
LL1 is X-1,
LL2 is Y-X-1,
length(TH,LL),
LL3 is LL-Y,
length(L1,LL1),
length(L2,LL2),
length(L3,LL3),
append(L1,LI1,TH),[EX|LIX]=LI1,append(L2,LI2,LIX),[EY|L3]=LI2,
flatten([regs,L1,EY,L2,EX,L3],LR),
Result =.. LR.
来源:https://stackoverflow.com/questions/61639909/how-to-implement-data-structure-in-prolog