Reading list from a file - list

I don't have much experience in Prolog.
add(first, second) :-
see('telefon_375319.txt'),
read(L),
seen,
M = [[first, second] | L],
tell('telefon_375319.txt'),
write(M),
nl,
told.
The purpose of the above code is to:
Read the list (which is a list of list) from a file (into L).
Add the list [first, second] at the beginning of the list (it might be at the end or even in the middle).
Save it to a file.
The result I get in the file is following:
[[x, y], end_of_file].
The result should be:
[[x, y], and here should be the rest of the list].
I don't know why ,but Prolog read a text end_of_file into L instead of the list which is stored in the file.
What's wrong?

end_of_file is not text. It’s atom and it’s read when the file ends. But in my SWI Prolog I see that an empty line must me placed at the end of the file in order to read it correctly. Searching for relevant info on that.

I modified the original slightly to use variables, not atoms. I also added writing a period (.) after the list that's written since read expects to see it:
add(First, Second) :-
see('telefon_375319.txt'),
read(L),
seen,
M = [[First, Second] | L],
tell('telefon_375319.txt'),
write(M), write('.'),
nl,
told.
Contents of telefon_375319.txt:
[[a,b],[c,d]].
Then run:
| ?- add(x, y).
yes
New contents of telefon_375319.txt:
[[x,y],[a,b],[c,d]].
Run:
| ?- add(z, w).
New contents of telefon_375319.txt:
[[z,w],[x,y],[a,b],[c,d]].
Other than the two changes that I made which I mentioned above, I don't see anything wrong with the predicate based upon the described desired behavior. I ran this on GNU Prolog and SWI Prolog on Linux, and SWI Prolog on Windows 7 and it worked as expected in all cases. The text file ends in a single \n in the case of Linux, and \r\n in the case of Windows.

Related

problem with deleting list item in prolog

my code in prolog
:- dynamic kitchenfurniture/1.
kitchenfurniture([furniture(fridge,1), furniture(table,2), furniture(chair,1)]).
writel([H|T]) :- write(H), nl, writel(T).
whatkitchenfurniture :- kitchenfurniture(X), writel(X).
addkitchenfurniture(X) :- kitchenfurniture(Y), append(Y, [X], Z), retract(kitchenfurniture(Y)), assert(kitchenfurniture(Z)).
deletekitchenfurniture(X) :- kitchenfurniture(Y), delete(X, Y, Z), retract(kitchenfurniture(Y)), assert(kitchenfurniture(Z)).
when I enter the code in the console
it does not remove the item from the list
problem wth line code deletekitchenfurniture(furniture(fridge,1)).
It is difficult to understand what exactly you type into the console; why don't you show it?
It is probable that this is wrong:
?- deleteaddkitchenfurniture('furniture(fridge,1)').
The correct way to do it might be:
?- deleteaddkitchenfurniture(furniture(fridge,1)).
No single quotes there. If you put it in single quotes, it becomes an atom with some parentheses embedded in it. If you don't quote, it is a compound term, as in the original list you have in here:
kitchenfurniture([furniture(fridge,1), furniture(table,2), furniture(chair,1)]).

Inserting value into the begining of each sublist

I'm currently writing a predicate that will run through a list of lists and insert a value I have calculated onto the beginning of the list
Step one is easy, just perform the calculation for each list and unify variable N with it.
checkthrough([]).
checkthrough([H|T]):-
count_validentries(H,N),
checkthrough(T).
What I'm trying to achieve now is to put that variable N onto the beginning of each of my sublists, so each list begins with the count of valid entries.
I have attempted to do this using an accumulator. Attempting to start with an empty list, and to every time add the new value N and the head of the list to it:
checkthrough([],Sofar,Lastone).
checkthrough([H|T],Sofar,Lastone):-
count_validentries(H,N),
Newsofar is [N,H|Sofar],
checkthrough(T,Newsofar,Lastone).
I'm quite sure I'm making a really stupid mistake somewhere along the lines. This is not valid Prolog syntax, failing with Arithmetic:' [2 internal variables]' is not a function.
Does anyone have any tips please?
Using meta-predicate maplist/3 and Prolog lambda simply write:
?- use_module(library(lambda)).
?- maplist(\Es^[N|Es]^count_validentries(Es,N), Ess, Xss).
Also, I'd guess that you're really looking for (-)/2 pairs which is how key-value pairs are commonly represented—by library predicates and the built-in predicate keysort/2. Consider:
?- Ess = [[a,b,c],[d,e],[],[f]],
maplist(\Es^(N-Es)^length(Es,N), Ess, Xss),
keysort(Xss, Yss).
Ess = [ [a,b,c], [d,e], [], [f]],
Xss = [3-[a,b,c], 2-[d,e], 0-[], 1-[f]],
Yss = [0-[], 1-[f], 2-[d,e], 3-[a,b,c]].
Maybe
checkthrough([],Sofar,Sofar).
checkthrough([H|T],Sofar,Lastone):-
count_validentries(H,N),
checkthrough(T,[[N|H]|Sofar],Lastone).
but you'll end up with the list reversed. Keeping it simpler will help
checkthrough([],[]).
checkthrough([H|T],[[N|H]|Rest]):-
count_validentries(H,N),
checkthrough(T,Rest).
or better, if you're running a recent version of SWI-Prolog:
checkthrough(L,L1) :-
maplist([E,E1]>>(count_validentries(E,N),E1=[N|E]), L,L1).

Sublists in Prolog(without recognizing the empty list)

I want to create a predicate in Prolog which will check if a list A is a sublist of a list B. Moreover I do not want my program to consider an empty list as a subset of another one.
E.g. included_list([1,4],[1,2,3,4,5]).
true.
included_list([2,3],[1,2,3,4,5]).
true.
included_list([1,6],[1,2,3,4,5]).
false.
included_list([],[1,2,3,4,5]).
false.
and so on...
So, I have written the following code so far:
member(X,[X|Tail]).
member(X,[Head|Tail]):- member(X,Tail).
included_list([X],_).
included_list([Head|Tail],List):- member(Head,List), included_list(Tail,List).
But the above code seems to be wrong, because in one specific case it throws true, instead of throwing wrong. I wish I'd made it clear having presented the following screenshot:
As you might have noticed the fifth(5th) sentence gives true, instead of wrong. That is, when I write a sentence of the form:
included_list([x,y],[w,x,v,z]).
whereas only x is included in the second list(and not y) the program gives me true(and this is wrong).
In general, if the first argument of the first list is included in the second list then, no matter if the rest of the former are included in the latter, the program gives me true.
In any other case the program gives me the right result(true or false).
What do I do wrong?
I will be waiting for your answers!
Thank you in advance!
Your problem is the first clause of included_list/2. This:
included_list([X], _).
What does it mean? It means, "If the first argument is a list with one element, succeed, ignoring the second argument."
A short aside: if you would not ignore compiler warnings, you would have caught this mistake already. You should get a loud and clear "Singleton variable" warning, hinting that the code you have written does not do what you think it does.
What you actually mean is more along the lines of:
subset_list([X|Xs], Ys) :-
subset_list_1(Xs, X, Ys).
subset_list_1([], X, Ys) :-
member(X, Ys).
subset_list_1([X|Xs], X0, Ys) :-
member(X0, Ys),
subset_list_1(Xs, X, Ys).
But I don't know why you don't simply use the available subset/2, and simply add a requirement that the subset is not an empty list:
subset_list(Subset, List) :-
Subset = [_|_], % a list with at least one element
subset(Subset, List).
Despite what the documentation claims, the second argument to subset/2 does not have to be a true "set", but it does expect that both lists are ground (do not contain any free variables). You can see the source code here.
In this answer we let meta-predicate maplist/2 handle recursion and define:
all_included(Sub, Es) :-
same_length(Es, Xs),
Sub = [_|_], % minimum length: 1
append(_, Sub, Xs), % maximum length: as long as `Es`
maplist(list_member(Es), Sub).
Let's run the queries the OP gave!
First up, use-cases we expect to succeed:
?- member(Xs, [[1,4],[2,3],[2,3,5],[3,4]]), all_included(Xs, [1,2,3,4,5]).
Xs = [1,4]
; Xs = [2,3]
; Xs = [2,3,5]
; Xs = [3,4]
; false.
Next up, some use-cases we expect to fail:
?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.
?- all_included([3,5], [1,2,5]).
false.

How can I check if an element in the list is an empty list: []?

How can I check if an element in the list is an empty list: [] ?
I've got the following:
display_degrees([A,B,C,D]):- write(B).
display_degrees([A,B,C,D]):- B==[], nl,write('has no degree'), nl, !.
When I enter in something like:
display_degrees([1,[],3,4]).
I just get: [] instead of 'has no degree'. Is my syntax wrong? Can I not add a clause to this predicate like this?
You're getting this behavior because proof search stops when a goal has succeeded. When you type
display_degrees([1,[],3,4]).
the first rule unifies, and it writes B. Since it was a success, it stops. You can ask Prolog to keep searching, and then it will find the second clause. In swipl, I get
?- [foo].
?- display_degrees([1,[],3,4]).
[]
true r % I type 'r' there
has no degree
true.
If you're just learning Prolog, I suggest you avoid the cut operator ! for some time. Also, doing IO is not the most intuitive thing. I would try some exercises with defining things like natural numbers and recursive functions. E.g., plus:
plus(z, X, X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
The problem with what you have is that the more general rule will fire first. You could switch the order:
display_degrees([A,[],C,D]) :- nl, write('has no degree'), nl, !.
display_degrees([A,B,C,D]) :- write(B).
I could just as well have written for the first predicate:
display_degrees([A,B,C,D]) :- B == [], nl, write('has no degree'), nl, !.
But the "shortcut" I show initially is more idiomatic for a Prolog predicate like this.
I kept the cut since you know you deterministically want one choice. The first rule will match if and only if the second list element is [].
| ?- display_degrees([1,[],3,4]).
has no degree
yes
| ?- display_degrees([1,2,3,4]).
2
yes
| ?-

Prolog: Downcase all atoms in a list

I'm trying to write a Prolog program that needs to take a user's natural language input and match it against a set of atoms. I'm using SWI Prolog's readln/1 to get input and put it in a list of atoms, but I don't have any guarantee of the case of the user input, so I want to just downcase all of the input I get before I try matching. What I have right now is:
downcase_list(AnyCase, LowerCase) :- dcl(AnyCase, X), flatten(X,LowerCase).
dcl([], List) :- List.
dcl([Head|Rest], []) :- downcase_atom(Head,X), dcl(Rest,X).
dcl([Head|Rest], List) :- downcase_atom(Head,X), dcl(Rest, [List|X]).
Appending using [List|X] seems to be my problem, but I don't know how to fix it, since I've already tried using append/3 and just got an infinite loop:
downcase_list([], List) :- List.
downcase_list([Head|Rest], []) :- downcase_atom(Head,X), downcase_list(Rest, X).
downcase_list([Head|Rest], NewList) :- downcase_atom(Head,X), append(NewList,X,Z), writeln(Z), downcase_list(Rest,Z).
I am very new to Prolog (I would classify myself as a Lisp programmer at this point), so it's very possible I'm missing something elementary. Help?
If you already have a list of atoms, to downcase them you have to apply a mapping with maplist/3 and downcase_atom/2:
downcase_list(AnyCaseList, DownCaseList):-
maplist(downcase_atom, AnyCaseList, DownCaseList).