Delete an unassigned member in list - prolog

i write a code , to get some specific output (2 List) , and it's work , and give me what i need , but there are unassigned element in the two list ,as shown below ,so my question is : how to delete thess unassigned elements .
Courses = [_G1619, linear, _G1607, physics2, physics1, calculas1|_G1590],
Marks = [_G1622, 78, _G1610, 90, 80, 78|_G1593]

In SWI-Prolog there are some list processing utilities like exclude/3, that allow to specify a predicate to be used on each element. var/1 seems appropriate. For instance
2 ?- exclude(var,[1,A,B,2,3|L],R).
L = [],
R = [1, 2, 3] ;
...
(note: place a cut after the call to get rid of nondeterminism).
I was surprised to find it also removed the unbounded tail - I thought it would require a proper list. Then it should fit your request.

Related

Setting order method in Sicstus prolog Samsort

I am trying to sort a list of lists such as Books=[[5,1,science,24,3,2018],[6,1,math,24,3,2019],[4,2,science,24,5,2019],[6,2,science,23,3,2019],[3,1,math,24,3,2020]]. I want to order this list based on the 5th value of each element. I tried to use
samsort(sortDateBooks, Books, Output).
sortDateBooks(Book1,Book2):-nth0(5,Book1, Date1),nth0(5,Book2, Date2), Date1<Date2.
The output variable is never filled with data and the original list is also not changed.
I feel that I am not declaring de order predicate properly but can't find any examples.
Thank you for your help.
Well, I noticed I had forgotten to import the samsort library and because of the way it is used no error would be shown. Many thanks to #Reema Q Khan that provided a very usefull workaround and a easy explanation.
I am not sure if this is what you want to do, if yes, then this may give you some hints:
1. Here collect dates will act as findall. It will search for all the years and put them in a list e.g. [2019,2018,2019,2019,2020].
2. sortBook(Sorted) predicate first finds all the Years using collectdates predicate, then sorts them. Notice that in sort I've used #=<, this will not remove any repeated values. You will get [2018,2019,2019,2019,2020].
3. s predicate simply takes each year, searches for the information and puts it in a List.
s predicate will take each year and check through each book, so this may lead to extras. append is used to decrease extra brackets, set predicate simply removes duplicates if any.
sortBook(Sorted):-
Book=[[6,2,science,23,3,2019],[5,1,science,24,3,2018],[6,1,math,24,3,2019],[4,2,science,24,5,2019]
,[3,1,math,24,3,2020]],
collectdates(Book,Clist),
sort(0, #=<, Clist, SList),
s(SList,Book,Sorted1),append(Sorted1,Sorted2),set(Sorted2,Sorted).
collectdates([],[]).
collectdates([H|T],[Last|List]):-
last(H,Last),
collectdates(T,List).
s([],_,[]).
s([H|T],[B|L],[W|List]):-
sortBook1(H,[B|L],W),
s(T,[B|L],List).
sortBook1(_,[],[]).
sortBook1(H,[B|L],[B|List]):-
member(H,B),
sortBook1(H,L,List).
sortBook1(H,[B|L],List):-
\+member(H,B),
sortBook1(H,L,List).
set([],[]).
set([H|T],[H|T2]):-
subtract(T,[H],T3),
set(T3,T2).
Example:
?-sortBook(Sorted).
Sorted = [[5, 1, science, 24, 3, 2018], [6, 2, science, 23, 3, 2019], [6, 1, math, 24, 3, 2019], [4, 2, science, 24, 5, 2019], [3, 1, math, 24, 3, 2020]]
false

how does variable calculating the value in prolog's functor?

The trace processing of the functor 'flatten2' with input list: "[4, [3, [2, [1,[ ] ] ] ] ]" (Screenshot of the tracing process)
The above is the screenshot of me calling functor flatten2 with input list "[4, [3, [2, [1,[ ] ] ] ] ]", and a variable 'X'.
The below is the function that I was tracing, stolen from this question: Flatten a list in Prolog.
So my essential question is that during the recursion, what happens to the variable X and its value? Why is the 'X' showed as '_295' in the "call 1", how does prolog grammar calculating this value?
flatten2([], []) :- !.
flatten2([L|Ls], FlatL) :-
!,
flatten2(L, NewL),
flatten2(Ls, NewLs),
append(NewL, NewLs, FlatL).
flatten2(L, [L]).
X is just a local name for "globally visible stuff" that is held in the "term store".
X designates (or names or denotes) either:
Concrete content: A term, which a generally tree. The variable is called "bound" or "instantiated". The leaves of the tree are either concrete content (atoms, numbers etc.) or cells with no content (see below). The inner nodes are called compound terms. If X designates a term, then the query nonvar(X) succeeds. When X is printed, it "disappears": The content is printed instead.
A cell with no content (I like to call this a "hole"), which is meant to be take up a term eventually. In that case the variable is called "unbound" or "uninstantiated". If X is such an unbound variable, i.e. if it designates a hole, then the query var(X) succeeds. When X is printed, its name is printed.
Confusingly (and I should add, rather sloppily), a "variable name" is commonly also called a "term". That's a Prolog tripmine, these two concepts should be held apart but they are not.
If you write your Prolog clause, you will use nice variable names.
flatten2(L, [L]).
Remember these variables names have no particular significance and they are local to the clause.
When Prolog runs, it has to pull new variable names that are distinct from any other names "out of the hat". These fresh variable names look like _295. Different implementations have different conventions here.
An example where new variable names have to be created to describe a list that contains a member foo somewhere (on at least one place). List templates of increasing length are generated. At each place of the list except the place holding foo (a concrete term), there is a "cell without content"/"hole". To express this, a random new variable name distinct from any other variable name is generated and printed. The variable name is probably directly derived from the hole address.
?- member(foo,L).
L = [foo|_23302] ;
L = [_23300, foo|_24038] ;
L = [_23300, _24036, foo|_24774] ;
L = [_23300, _24036, _24772, foo|_25510] ;
L = [_23300, _24036, _24772, _25508, foo|_26246] ;
L = [_23300, _24036, _24772, _25508, _26244, foo|_26982]

Nested for loops in Pari/GP

Is there a way to nest for loops inside other for loops in Pari/GP (2.7.6) since the following error always appears:
*** at top-level: read("prog.txt")
*** ^----------------
*** read: sorry, embedded braces (in parser) is not yet implemented.
Code:
(12:14) gp > n = 12
%12 = 12
(12:14) gp > k = 10
%13 = 10
(12:14) gp > g = [1..10]
%14 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
{
forprime(p = 1, 16,
rn = n%p
rk = k%p
{
for(i=1, #g,
if( (rn*(g[i]+rk)+1)%p!=0,
h = concat(h, g[i])
}
g = h
}
Thanks for help. The question where I posted and got the code from got deleted, so I'm kind of stuck at this point.
Braces don't mean the same thing as in C# or many other programming languages. They do not start/end a block.
In PARI multiple statements are joined with a semi-colon and contained within the argument parenthesis of a function. Special functions include while, for, if etc.
For example:
my(s=7);forprime(p=1, 7, s*=3; for(i=1, p, s+=p^2); s+=6); s
contains three statements inside the forprime loop, separated by semicolons and one of those is another loop.
Now braces {} on the other hand, just allow you to write programs that are more than one line long. Normally when an end of line is reached, PARI tries to interpret everything on that line. But it doesn't do that if between { and }, so you never need more than one pair.
In your example you need to remove the inner {} and add some semi-colons between statements.

Why don't I need to check in the member_of_set if Element and Element1 are different?

When using sets, adding an Element to the Set is done like this:
add_to_set(Element, [], [Element]).
add_to_set(Element, [Element | Set], [Element | Set]).
add_to_set(Element, [Element1 | Set], [Element1 | NewSet]) :-
not(Element = Element1),
add_to_set(Element, Set, NewSet).
Now, with this, I thought member_of_set would be like:
member_of_set(Element, [Element|_]).
member_of_set(Element, [Element1|Set]) :-
not(Element = Element1), /* Not necessary */
member_of_set(Element, Set).
This works like a charm, but in this case, not(Element = Element1) is not necessary. I can't seem to figure out why. If you ask for more answers from Prolog, won't it backtrack and succeed on the second clause of member_of_set?
An if it's not necessary in the member_of_set, then why is it necessary in the add_to_set?
Please keep in mind that I'm only studying since one month Prolog, so I'm still in some kind of mind switch...
I know that using cut, there's probably better alternatives, but cut shouldn't be used.
it's not necessary in the member_of_set
because it doesn't hurt if the list is not a set. Only you will end up - in case you pass a list with repeated elements inside - with multiple solution, but still each solution is valid.
OTOH, add_to_set leads to invalid data if you remove the test:
?- add_to_set(1,[],A),add_to_set(1,A,B).
A = B, B = [1] ;
A = [1],
B = [1, 1] ;
false.
for a friendly explanation of cuts, and why are necessary in Prolog, see this page
contains(Element, [Element|_]).
contains(Element, [_|Set]) :-
contains(Element, Set).
You can read this as: "Element is in a Set, if it's the head of that Set, or if it's in the tail of that Set". If you're checking if it's in the tail, there's no need to check if it's equal to the head, except for performance reasons.
Actually, this way, you're not even restricting it to a Set. It's a general contains.

recursion in prolog - error in base case

I'm trying to write predicate range\3 that takes three parameters the first is the start, the second is the end and return the generated list in the third argument.
E.g rang(1,5,L).
L = [1, 2, 3, 4, 5]
I used this code
range(E,E,[E]).
range(S,E,L):-
S1 is S + 1,
range(S1,E,[S|L]).
But it does not work, when i used trace command to know where is the error i recognized that the base case is useless, I also tried the green cut !in the base case but it does not work range(E,E,[E]),!.
So, if any one knows what is the problem please help me
You're building the list in 'wrong' sense. Consider that when you'll call the base case, it will receive the consed list. How could match a single element list ? Try instead
range(S,E,[S|L]):-
S1 is S + 1,
range(S1,E,L).

Resources