Prolog pattern match and return - list

New to Prolog here and already found it hard.
And here's the question: let's say I got a char list such as [h,e,l,l,o] and a unicode number 108(which is the letter "l").
I'm trying to write a function that take the elements of the list one by one and pattern match with the given unicode number. Once matched, return the reste of the list.
Worked on it for a whole day now , almost tried everything I can think of and I still didn't figure out how to make it work. Anyone got some ideas?

function([C|Chars], CutoffCode, Chars) :-
char_code(C, CutoffCode).
function([C|Chars], CutoffCode, Result) :-
not(char_code(C, CutoffCode)),
function(Chars, CutoffCode, Result).
e.g.
?- function([h,e,l,l,o], 108, Result).
Result = [l, o]
?- function([h,e,l,l,o], 109, Result).
false

Related

Prolog: Adding elements to list through read/1

I am trying to add user input to a list with add_read_list/2 until the word "end." is encountered. This is how the output is supposed to look:
add_read_list(Resultlist, [a,b]).
|: c.
|: d.
|: e.
|: f.
|: end.
Resultlist = [f,e,d,c,a,b].
This is how far I have come:
add_read_list(Resultlist,Entrylist) :-
read(end), append([], Entrylist, Resultlist).
add_read_list(Resultlist, Entrylist) :-
read(Input), append([Input], Entrylist, X),
add_read_list(Resultlist, X).
But this way every second input gets skipped:
add_read_list(Resultlist, [a,b]).
|: c.
|: d.
|: e.
|: f.
|: end.
Resultlist = [f,d,a,b].
What am I doing wrong?
drop the first clause, and use the simple 'if/then/else' construct:
add_read_list(Resultlist, Entrylist) :-
read(Input),
( Input = end
-> reverse(Resultlist, Entrylist)
; add_read_list(Resultlist, [Input|Entrylist])
).
instead of appending each item read, 'cons' it, and reverse the full list when done (well, simply unify to get the list in LIFO, as seems required. i.e. instead of reverse(Resultlist, Entrylist), Resultlist = Entrylist)
The actual error is read(end). This will only succeed, if the term read in is end. Otherwise it fails.
But I do have a lot of reservation to tell you this at all, since nobody every does this is Prolog. Here are the actual things that would need improvement.
The first, is to use end_of_file in place of end, because this is automatically generated at the end of a file, plus you can write it yourself, too.
The second is the way how to handle this. You need to read and then process the term read in:
... read(X), ( X == end_of_file -> ... ; /* whatever */ ... ), ....
However, please do reconsider your entire task. There is a single reason why this could be needed: When you are processing a Prolog file. But this you get cheaper and less error prone by saying [file].
So better design your data to fit into Prolog terms.

Prolog program- implementing rules and list matching

I am trying to write a program in Prolog that would recognize 'is a' statements and apply the transitive property in inquired. For example:
Input: Mary is a girl.
Output: ok.
Input: A girl is a human.
Output: ok.
Input: Is Mary a human?
Output: yes.
Here's my code:
begin :-
begin(Input).
begin(Input) :-
write('Begin.. '),
write('\n'),
readln(Input),
tokenize_atom(Atom, List),
rules(List).
begin.
rules(['A', Subj, is, a, What]) :-
asserta(a(Subj, What)),
write('ok'),
write('\n').
rules([Subj, is, a, What]) :-
asserta(is(Subj, What)),
write('ok'),
write('\n').
rules(['Is', Subj, a, What]) :-
(is(Subj, Z) ; a(Z, What)) -> (write('Yes.'), nl)
; (write('Unknown.'), nl).
It doesn't go into any of the cases, it will just say true and terminate when given a statement. What am I doing wrong?
Prolog itself wants to help you. Look at the helpful messages you get:
|: begin :-
|: begin(Input).
Warning: user://1:9:
Singleton variables: [Input]
This is pointing out that this rule is no different from:
begin :- begin(_).
This is highlighting that the role of Input in begin/1 is ambiguous. Is it input or output? If you can use it like this, it must be output, and that's consistent with how it's used in its definition, but look at the other problem you have there:
|: begin(Input) :-
|: write('Begin.. '),
|: write('\n'),
|: readln(Input),
|: tokenize_atom(Atom, List),
|: rules(List).
Warning: user://1:14:
Singleton variables: [Atom]
Where did Atom and List come from? Presumably you wanted one of those to show up from readln/1. What's actually going on here is that you're asking Prolog to input a value, which you then return, having done nothing with it; meanwhile Prolog materializes Atom and List from thin air and uses them with your rules/1 predicate. So clearly something isn't hooked up here that should be.
Then you have an obvious typo:
|: begin.
Warning: user://1:22:
Clauses of begin/0 are not together in the source-file
I suspect you meant a comma after rules(List) instead of a period.
Try fixing those problems and see if you make some progress.

Prolog, working with multiple predicates

I've just starting working with Prolog and I don't understand how to work with multiple predicates.
For example I have to solve the following problem: Substitute in a list a value with all the elements of another list.
This is the code that I managed to write so far:
domains
elem=integer
list=elem*
predicates
%append to a list already created another list. There are 3 list parameters
%because I don't know other method
append (list,list,list)
%This will search the list (the first one) for the searched element and
%it is it will replace it with the list(the second one). The result will be
%kept in the third list.
add(list,list,elem,list)
goal
add([1,2,3,2,1],[4,5],2,L),
write (L).
clauses
add ([],[_],_,[]).
add ([A|L],L1,E,[A|L2]):-
add(L,L1,E,L2).
add ([E|L],L1,E,L2):-
add(L,L1,E,L2).
append([],[],L2).
append([],[X|L1],[X|L2]):-
append([],L1,L2).
Does your append definition is working? I think should be
append([], L, L).
append([X|Xs], Ys, [X|Zs]):-
append(Xs, Ys, Zs).
The append predicate it's one of the most basic tools in Prolog programming, better to keep the usual behaviour, or to change name...
Instead of add, a better name could be replace_elem_with_list.
To implement it you should iterate, inspecting each element, and when you find a match to what's required to replace append the list instead of copying the element.
Something like
% replace_elem_with_list(ToSearch, Replacement, SoughtElem, Result)
replace_elem_with_list([E|Es], Replacement, E, Result) :-
!, replace_elem_with_list(Es, Replacement, E, Rs),
append(Replacement, Rs, Result).
I'll leave you the other 2 cases that you will need to cover (when element doesn't match and recursion base, which are similar to append)
the result:
?- replace_elem_with_list([1,2,3,4,2,3,4],[a,b],2,L).
L = [1, a, b, 3, 4, a, b, 3, 4].

List search in Prolog

I'm trying to make a search in a list in Prolog, but I would like to start right at a certain position. Will I have to do that boring recursive search?
Thank you.
you can Skip N positions using N free_vars, and append/3 to get rid of list' header:
?- [user].
|: find(Needle, Haystack, Skip) :-
|: length(Header, Skip),
|: append(Header, Actual, Haystack),
|: memberchk(Needle, Actual).
|: % user://1 compiled 0,04 sec, 2 clauses
true.
?- find(3-X,[1-alfa,2-beta,3-gamma,4-delta,1-abba,2-bridge],1).
X = gamma.
?- find(3-X,[1-alfa,2-beta,3-gamma,4-delta,1-abba,2-bridge],3).
false.
?- find(3-X,[1-alfa,2-beta,3-gamma,4-delta,1-abba,2-bridge],2).
X = gamma.
If there are many search to to, the list build length(Header, Skip) it's better done once...

Prolog problem help

I am trying to learn prolog and have come across a problem that I can't figure out. The problem is to write a prolog predicate that takes all the numbers of a list that are less than a given number and put them into a list that will be returned. For example:
input:
findNum(5, [5, 3, 5, 6, 4, 5], Y)
output:
Y = [3, 4]
Everything I've tried seems to fail. So any help would be much appreciated. Thanks.
To solve this, you will use a typical Prolog pattern of examining the elements from your input list one-at-a-time. Prolog includes a syntax for selecting the head element from a list, by unifying the list with [A | B] , the first element of the list is unified with A and the remainder of the list (or emptiness if no elements remain) is unified with B.
You should consider first how many clauses you will need. You will need one clause to handle the case of an empty list, which is also the termination condition for your recursion. Each time you examine one item of the list, you recursively examine the remainder of the list. On the final examination, the 'remainder of the list' is empty.
For the clauses which examine the head element of the list, you have two possible conditions: the element satisfies your search criterion (less than 'num'), or it does not. To represent this, implement two clauses, both of which iterate over the list, but only the first of which matches your search criteria. The clause which detects "matching" elements must be written first in your Prolog file so that it will be considered first.
% This clause is for the "empty input" case which is also used to
% discontinue the recursion when finished.
findNum( _, [], []).
% This clause completes only if the first input element is less than
% 'M'. If the clause completes, the first input element ('X') is unified
% with the output list ([X | Y]).
findNum( M, [X | L], [X | Y]) :-
X < M,
findNum(M, L, Y).
% This clause completes if the above clauses do not. Much like an "else"
% case, this clause simply removes the first input element from the list,
% the element must not match in the search clause above and so we will now
% discard it. Thus, it is unified with the "throw away" variable named "_"
findNum( M, [_ | L], Y) :-
findNum(M, L, Y).