*Hi, i am trying to replace an element from a list with another list and im stuck when turbo prolog gives me syntax error at the case where if C=A-> put in result list(L1) the list that replace the element.
domains
list=integer*
element=i(integer);l(list)
lista=element*
predicates
repl(list,integer,list,lista)
clauses
repl([],A,B,[]):-!.
repl([C|L],A,B,**[l(|L1])**:- C=A,repl(L,A,B,L1),!.
repl([C|L],A,B,[i(C)|L1]):- repl(L,A,B,L1),!.
Thanks for help, problem solved (using dasblinkenlight code)
Try this:
concat([],L,L).
concat([H|T],L,[H|Res]) :- concat(T,L,Res).
repl([],_,_,[]).
repl([Val|T],Val,Repl,Res) :- repl(T,Val,Repl,Temp), concat(Repl,Temp,Res).
repl([H|T],Val,Repl,[H|Res]) :- repl(T,Val,Repl,Res).
I do not know if it is going to work in Turbo Prolog, but it works fine in SWI, and it does not use any built-in predicates.
concat/3 pair of rules concatenates lists in positions 1 and 2 into a resultant list in position 3.
The first repl deals with the empty list coming in; it is identical to yours, except it replaces singleton variables with underscores (a highly recommended practice)
The second rule deals with the situation where the value Val being replaced is at the head of the list; it replaces the values in the tail, and concatenates the replacement list Repl with the result of the replacement Res.
The last rule deals with the situation when the head value does not match the Val. It recurses down one level, and prepends the head of the initial list to the head of the result of the replacement.
As a side note, the cut operator ! is rarely necessary. In case of this problem, you can definitely do without it.
Related
I try to count words in a string in prolog. Like "No, I am definitely not a pie!"
To give me the number 7 and next example "w0w such t3xt... to give number 5.
I had thougt about subtract that are a library function and only get back white-characters. But the problem then is No way will give back 5 and not two words.
I thought about
filter([],L).
filter([X,Y|XS],[Y|XS]):- X = ' ',Y = ' ',L = [Y|XS], filter([Y|XS],L).
filter([X|XS],L):- filter(Xs,L).
That will remove white spaces and get back No way but it dosent work anbody have a tip.
Strings in Prolog are lists of character codes not of atoms, what explains why tests like X=' ' fail. See what is the result of executing
write("ab cd"), nl.
in your Prolog system.
You have errors in your 3 clauses:
What to do you expect the first clause to return in the last argument?
L is, as any other variable in a Prolog program, a variable that is local to the clause it appears in, never a global variable.
The second clause unifies L with a list and you use it as second argument of the recursive call: do you expect the recursive call to change the value of L? This will never be the case: in Prolog there is no assignment of variables, changes are made by building terms and unifying them with new variables.
What happens to X in your third clause???
I'm trying to learn prolog and i bumpt in this error which, i don't know why i get it so i am asking for your help.
code(TPROLOG#86):
trace
domains
item = integer
intList = item*
predicates
member(item,intList)
clauses
member(elm,[elm|_]).
member(elm,[_|T]):- %%% ***ELM is seen as wrong type, why?***
member(item,[T]).
goal
member(5,[1,2,3,4,5])
Any advice or hint is welcomed. Thank you.
You are confusing variables and atoms. Atoms start with a lower case letter, whereas variables start with an upper case letter.
Also, your member/2 definition seems wrong. It should read:
clauses
member(Elm,[Elm|_]).
member(Elm,[_|T]):-
member(Elm,T).
First clause matches the element with the head of the second list. Second clause skips the head of the second list and recursively calls member/2 to find another match in the tail of the list.
I have a predicate "lookupOptions" which returns one by one some lists (Menus).
I'm trying to get it to satisfy the case of multiple inputs. I can return a single set of options as follows, by reading the head of the "list_places" list.
find_options(Restaurant,Town,Menu) :- lookupOptions(Restaurant,H,Menu), list_places(Town,[H|T])
But, I'm not able to get it to iterate.
I have tried a lot of things, these were my best efforts so far.
a) standard enough iteration, but it wont resolve ...
doStuff(X,[],_).
doStuff(Restaurant,[H|T],_):- lookupOptions(Resturant,H,_), doStuff(Restaurant,T,_).
find_options(Restaurant,Town,Menu) :- doStuff(Restaurant,[H|T],Menu), list_places(Town,[H|T]).
b) expanding the goal predicate ...
find_options(_,Town,[H|T],_)
find_options(Restaurant,Town,Menu) :- find_options(Restaurant,Town,[],Menu).
find_options(Restaurant,Town,X,Menu) :- list_places(Town,X).
find_options(Restaurant,Town,[H|T],Menu) :- lookupOptions(Restaurant,[H],Menu), find_options(Restaurant,Town,T,Menu).
Would either of these work ? if the pattern was written correctly. Or if there was an appropriate cut put in place?
Any help most appreciated ...
It's no clear on what you want iterate. Prolog uses backtracking to examine all alternatives, then you should start backtracking if you are after some alternative, or use the all solutions family.
Now I think you want simply declare there could be more find_options(Restaurant,Town,Menu). Then try replacing the head match [H|T] with this:
find_options(Restaurant,Town,Menu) :-
lookupOptions(Restaurant,H,Menu),
list_places(Town, Places),
member(H, Places).
BTW T is a singleton in your original rule. This could be a hint for the need of generalize it.
suppose I have a list ListSum, and I want to append a new list to ListSum recursively, like
appList(ListSum):-
%%generate a list: ListTemp,
append(ListTemp,ListSum,ListSum),
appList(ListSum).
but append(ListTemp,ListSum,ListSum) didn't work in the way i wanted.
Can anyone help me out?
Cheers
You have to understand the concept of unification (or actually "matching" as implemented in Prolog). You can't bind two or more values to the same variable. Variables in Prolog once matched persisted its value until the final goal achieved, or fails somewhere. After that, if there're more possibilities then the variable is re-instantiated with another value and so on.
For example, if I query appList([]), then the append would be tested to match as:
append(ListTemp,[],[])
If ListTemp isn't empty list, this clause would fail because the semantic of append is "append the first argument with second, both are lists, resulting in the third". The recursive call to appList(ListSum) would be called as appList([]) since ListSum is matched with [] previously, resulting in infinite recursion (fortunately, if ListTemp isn't [], this won't be reached).
You must have two arguments in the clause, where one is the original list, and the other is the resulting list. The first two argument of append is then ListSum and ListTemp (depends on the append order you want), while the third is the resulting list. Done, no recursion required.
here's a non-recursive solution, not sure why you even need recursion:
appself(L,X) :- append(L,L,X).
I know on how to display a list by using loop.
For example,
choice(a):-write('This is the top 15 countries list:'),nl,
loop(X).
loop(X):-country(X),write(X),nl,fail.
Unfortunately, I don't know on how to display list by using list. Anyone can guide me?
it's not very clear what it is that you're trying to achieve.
I'm not sure from your description whether you have quite got to grips with the declarative style of Prolog. When you wrote your rule for loop you were providing a set of conditions under which Prolog would match the rule. This is different from a set of procedural instructions.
If you want to collect all the countries into a list you can use the setof rule like follows
top_countries(Cs):-
setof(C, country(C), Cs).
This will return a list [] of the countries matched by the rule.
If you wanted to output each element of this list on a new line you could do something like the following recursive function.
write_list([]).
write_list([H|T]):-
write(H),nl,
write_list(T).
The first rule matches the base case; this is when there are no elements left in the list. At this point we should match and stop. The second rule matches (unifies) the head of the list and writes it to screen with a newline after it. The final line unifies the tail (remainder) of the list against the write_list function again.
You could then string them together with something like the following
choice(a):-
write('This is the top 15 countries list:'),nl,
top_countries(X),
write_list(X).
Things to note
Try not to have singleton variables such as the X in your choice rule. Variables are there to unify (match) against something.
Look into good declarative programming style. When you use functions like write it can be misleading and tempting to treat Prolog in a procedural manner but this will just cause you problems.
Hope this helps
write/1 doesn't only write strings, it writes any Prolog term. So, though Oli has given a prettier write_list, the following would do the job:
choice(Countries):-write('This is the top 15 countries list:'),nl,write(Countries).