learn prolog now 5

来源:互联网 发布:python 在图片上画框 编辑:程序博客网 时间:2024/06/05 03:31

内建运算和处理list问题。

如果只是=符号,prolog只是将variable同term绑定。使用is来运算。

varibale最好放在左端。

计算list长度的第一个版本

len([],0).
len([_|T],N) :- len(T,X), N is X+1.

accumulator来保存中间结果。

Exercise 5.2 1. Define a 2-place predicate increment that holds only when its
second argument is an integer one larger than its first argument. For example,
increment(4,5) should hold, but increment(4,6) should not.

increment(X,Y) :- Y is X+1.
2. Define a 3-place predicate sum that holds only when its third argument is the
sum of the first two arguments. For example, sum(4,5,9) should hold, but
sum(4,6,12)should not.

Exercise 5.3 Write a predicate addone2/ whose first argument is a list of integers,
and whose second argument is the list of integers obtained by adding 1 to each integer
in the first list. For example, the query
addone([1,2,7,2],X).
should give
X = [2,3,8,3].

addone([],[]).
addone([X|Ta],[Y|Tb]) :- Y is X+1, addone(Ta,Tb).

list的append操作

append([],L,L).
append([H|T],L2,[H|L3]) :- append(T,L2,L3).

prefix操作

prefix(P,L) :- append(P,_,L).

suffix操作

list的reverse操作

naiverev([],[]).
naiverev([H|T],R) :- naiverev(T,RevT),append(RevT,[H],R).

更有效的版本

accRev([H|T],A,R) :- accRev(T,[H|A],R).
accRev([],A,A).

rev(L,R) :- accRev(L,[],R).


以下从http://hi.baidu.com/chen_767/item/64a5ff599d968fcdd3e10cfd复制

Exercise 6.1

    Let's call a list doubled if it is made of two consecutive blocks of elements that are exactly the same. For example, [a,b,c,a,b,c] is doubled (it's made up of [a,b,c]followed by [a,b,c]) and so is [foo,gubble,foo,gubble]. On the other hand, [foo,gubble,foo] is not doubled. Write a predicate doubled(List) which succeeds when List is a doubled list.
    
isDoubled(List,Sub,StartIdx,EndIdx):-
    StartIdx =< EndIdx,
    List = [H|T],
    Sub  = [H1|T1],
    H = H1,
    TmpStart is StartIdx + 1,
    isDoubled(T,T1,TmpStart,EndIdx),!.
isDoubled(_,[],_,_):-!.

getSublist(List,1.0,List):-!.
getSublist(List,StartIdx,Ret):-
    StartIdx > 1,
    List=[_|T],
    Tmp is StartIdx - 1,
    getSublist(T,Tmp,Ret),!.

doubled([]):-!.
doubled(List):-
    length(List,L),
    Idx is L / 2 + 1,
    getSublist(List,Idx,Ret),
    isDoubled(List,Ret,1,Idx-1),!.

另一个解法

double(X) :- append(X,X,_).
Exercise 6.2

    A palindrome is a word or phrase that spells the same forwards and backwards. For example, `rotator', `eve', and `nurses run' are all palindromes. Write a predicate palindrome(List), which checks whether List is a palindrome. For example, to the queries

        ?- palindrome([r,o,t,a,t,o,r]).

    and

        ?- palindrome([n,u,r,s,e,s,r,u,n]).

    Prolog should respond `yes', but to the query

        ?- palindrome([n,o,t,h,i,s]).

    Prolog should respond `no'.

isSame([],[]):-!.
isSame([H|T1],[H|T2]):-
    isSame(T1,T2),!.


palindrome(List):-
    reverse(List,RevList),
    isSame(List,RevList),!.
    

另一个解法:

palindrome(List) :- rev(X,X).

Exercise 6.3

        Write a predicate second(X,List) which checks whether X is the second element of List.
        
        
theXth(X,[_|T],Idx, I):-
    I < Idx,
    Tmp is I + 1,
    theXth(X,T,Idx, Tmp),!.
theXth(X,[H|_],Idx,I):-
    Idx is I,
    X = H,!.
theXth(X,List,Idx):-
    theXth(X,List,Idx,1),!.

second(X,List):-
    theXth(X,List,2),!.
另一个解法:

second2(H,[H|Ta]).
second(X,[H|Ta]) :- second2(X,Ta).
        

        Write a predicate swap12(List1,List2) which checks whether List1 is identical to List2, except that the first two elements are exchanged.
        
isSame([H|T1],[H|T2]):-
    isSame(T1,T2),!.
isSame([],[]):-!.

swapFirstTwoElements(List,Ret):-
    List = [H1|T1],
    T1 = [H2|T2],
    Tmp = [H1|T2],
    Ret = [H2|Tmp],!.

swap12(L1,L2):-
    swapFirstTwoElements(L1,Ret),
    isSame(Ret,L2),!.
    另一个解法:

isSame([],[]).        
isSame([H|T1],[H|T2]):-
    isSame(T1,T2).

head(H,[H|Ta]).
swap12([H|Ta],[X|Tb]) :-
       head(X,Ta),
       head(H,Tb),test(Y,Z).
test([H|Ta],[X|Tb]) :- isSame(Ta,Tb).

   


        Write a predicate final(X,List) which checks whether X is the last element of List.


final(X,List):-
    length(List,Len), Len > 1,
    List=[_|T],
    final(X,T),!.
    
final(X,List):-
    length(List,Len), Len is 1,
    List=[H|_],
    X = H,!.
    
另一个解法:


final(X,[X]).
final(X,[H|Ta]) :- final(X,Ta).

        Write a predicate toptail(InList,Outlist) which says `no' if inlist is a list containing fewer than 2 elements, and which deletes the first and the last elements of Inlist and returns the result as Outlist, when Inlist is a list containing at least 2 elements. For example:

                toptail([a],T).
                no
               
                toptail([a,b],T).
                T=[]
              
                toptail([a,b,c],T).
                T=[b]

        Hint: here's where append comes in useful.
        
removeTail(List,Ret):-
    append(X,Y,List),
    length(Y,Len),
    Len is 1,
    Ret = X.

removeTop(List,Ret):-
    List=[_|Ret],!.

toptail(List, T):-
    length(List,Len),
    Len > 2,
    removeTop(List,R1),
    removeTail(R1,T),!.
    
toptail(List, T):-
    length(List,Len),
    Len is 2,
    T = [],!.
    
另一个解法:

toptail([_|Xs],OutList) :- append(OutList,[_],Xs).
    
        Write a predicate swapfl(List1,List2) which checks whether List1 is identical to List2, except that the first and last elements are exchanged. Hint: here's where append comes in useful again.

isTheSame([],[]):-!.
isTheSame([H|T1],[H|T2]):-
    isTheSame(T1,T2),!.

splitArrEle(List,TopArray,TailElement):-
    append(X,Y,List),
    length(Y,Len),
    Len is 1,
    Y = [TailElement|_],
    TopArray = X,!.

swapfl(List1,List2):-
    List1 = [H|T],
    splitArrEle(T,Arr,TailE),
    Tmp = [TailE|Arr],
    append(Tmp,[H],NewList),
    isTheSame(NewList,List2),!.
    
另一个解法:

swapfl([X|Xs],List2) :-
    append(T,[H],Xs),
    append([H|T],[X],List2).

   
Exercise 6.4

    And here is an exercise for those of you who, like me, like logic puzzles.

    There is a street with three neighboring houses that all have a different color. They are red, blue, and green. People of different nationalities live in the different houses and they all have a different pet. Here are some more facts about them:

        The Englishman lives in the red house.

        The jaguar is the pet of the Spanish family.

        The Japanese lives to the right of the snail keeper.

        The snail keeper lives to the left of the blue house.

    Who keeps the zebra?

    Define a predicate zebra/1 that tells you the nationality of the owner of the zebra.

    Hint: Think of a representation for the houses and the street. Code the four constraints in Prolog. member and sublist might be useful predicates.



neigh(Left, Right, List) :-
        List = [Left | [Right | _]];
        List = [_ | [Left | Right]].

zebraowner(Houses, ZebraOwner):-
        member([englishman, _, red], Houses),
        member([spanish, jaguar, _], Houses),
        neigh([_, snail, _], [japanese, _, _], Houses),
        neigh([_, snail, _], [_, _, blue], Houses),
        member([ZebraOwner, zebra, _], Houses),
        member([_, _, green], Houses).


zebra(X) :- zebraowner([_, _, _], X),!.


| ?- zebra(X).

X = japanese

yes
| ?-


--------------------跟踪-------------

| ?- zebra(X).
      1    1  Call: zebra(_16) ?
      2    2  Call: zebraowner([_46,_48,_50],_16) ?
      3    3  Call: member([englishman,_78,red],[_46,_48,_50]) ?
      3    3  Exit: member([englishman,_78,red],[[englishman,_78,red],_48,_50]) ?
      4    3  Call: member([spanish,jaguar,_111],[[englishman,_78,red],_48,_50]) ?
      4    3  Exit: member([spanish,jaguar,_111],[[englishman,_78,red],[spanish,jaguar,_111],_50]) ?
      5    3  Call: neigh([_138,snail,_142],[japanese,_146,_148],[[englishman,_78,red],[spanish,jaguar,_111],_50]) ?
      5    3  Fail: neigh([_138,snail,_142],[japanese,_146,_148],[[englishman,_78,red],[spanish,jaguar,_111],_50]) ?
      4    3  Redo: member([spanish,jaguar,_111],[[englishman,_78,red],[spanish,jaguar,_111],_50]) ?
      4    3  Exit: member([spanish,jaguar,_111],[[englishman,_78,red],_48,[spanish,jaguar,_111]]) ?
      5    3  Call: neigh([_138,snail,_142],[japanese,_146,_148],[[englishman,_78,red],_48,[spanish,jaguar,_111]]) ?
      5    3  Exit: neigh([englishman,snail,red],[japanese,_146,_148],[[englishman,snail,red],[japanese,_146,_148],[spanish,jaguar,_111]]) ?
      6    3  Call: neigh([_176,snail,_180],[_182,_184,blue],[[englishman,snail,red],[japanese,_146,_148],[spanish,jaguar,_111]]) ?
      6    3  Exit: neigh([englishman,snail,red],[japanese,_146,blue],[[englishman,snail,red],[japanese,_146,blue],[spanish,jaguar,_111]]) ?
      7    3  Call: member([_16,zebra,_218],[[englishman,snail,red],[japanese,_146,blue],[spanish,jaguar,_111]]) ?
      7    3  Exit: member([japanese,zebra,blue],[[englishman,snail,red],[japanese,zebra,blue],[spanish,jaguar,_111]]) ?
      8    3  Call: member([_245,_247,green],[[englishman,snail,red],[japanese,zebra,blue],[spanish,jaguar,_111]]) ?
      8    3  Exit: member([spanish,jaguar,green],[[englishman,snail,red],[japanese,zebra,blue],[spanish,jaguar,green]]) ?
      2    2  Exit: zebraowner([[englishman,snail,red],[japanese,zebra,blue],[spanish,jaguar,green]],japanese) ?
      1    1  Exit: zebra(japanese) ?

X = japanese

yes

另一个解法:


原创粉丝点击