prolog sort and print best 3 - sorting

what I have now is,
:-dynamic listofPeople/2.
listofPeople(Mark,Name).
e.g.
19, 'Jos'
92, 'Abdul'
33, 'Izz'
16, 'Xin'
I want it like this -
92, 'Abdul'
33, 'Izz'
19, 'Jos'
which basiclly contains the mark for each student.
I want to print the best 3 marks.
To do that, I blv I have to do sorting. If I do sorting, I will lose the order of the name of the student.
As you can understand by default, what I want is to sort only the marks and change the names position according to the marks as well, so when i print
i get the above output
Code snippets appreciated.

I've answered you in a thread below:
go(N1-G1,N2-G2,N3-G3) :- findall(Grade-Name, listofPeople(Grade,Name), List),
keysort(List, [G1-N1,G2-N2,G3-N3|SortedList]).
On your input go(X,Y,Z) results in X = 'Abdul'-92, Y = 'Izz'-33, Z ='Jos'-19.

Couldn't you sort the list by mark, take the top 3, and then sort THAT by name, before you print?

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

Prolog: How can I show just names that accompany certain numbers. I have a list in the prolog and I need to show just a few certain names

I need to show just 2, 8 and 10, and to show it all in listName. I need to show the ID and Name.
This is what I tried:
listName(NA):-
name(ID, NA),
specific(ID, 2, 8, 10),
format('xxx', [ID, NA]).
Like this?
Using memberchk/2 to implement specific/4, quite naturally:
listName(NA):-
name(ID, NA),
(memberchk(ID,[2,8,10])
-> format("ID = ~q, NA = ~q\n", [ID, NA])
; (format("Nope\n"),fail)).

Delete an unassigned member in list

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.

Sequences in Ruby

Is there a simple function in ruby to create sequences? For example, I want a sequence from 1 to 100 incrementing by 3. So
Function(1,100,increment = 3) = [1,4,7,10, ...,97,100]
Thanks!
Range#step generates another enumerator with given step.
say (1..100).step(3).to_a would be [1,4,7, ... , 97, 100]
alternatively
Numeric#step(limit,step) does similar things,
say 1.step(100,3).to_a

How do I skip certain columns when parsing a text file with Ruby?

I have to parse a tab-delimited text file with Ruby to extract some data from it. For some unknown reason some columns aren't used and are just essentially spacers; I'd like to ignore these columns since I don't need their output (however I can't just ignore all empty columns since some legitimate columns have empty values). I know the indices of these columns already (e.g. columns 6, 14, 24 and 38).
While I could just add a conditional while I'm parsing the file and say parse this unless it's one of those columns, this doesn't seem very "Rubyish" - is there a better and more elegant way to handle this? RegExps, perhaps? I thought of doing something like [6, 14, 24, 38].each { |x| columns.delete_at(x) } to remove the unused columns, but this will force me to redetermine the indices of the columns which I actually need. What I'd really like to do is just loop through the whole thing, checking the index of the current column and ignore it if it's one of the "bad" ones. However it seems very ugly to have code like unless x == 6 || x == 14 || x == 24 || x == 38
No need for a massive conditional like that.
bad_cols = [6, 14, 24, 38]
columns.each_with_index do |val,idx|
next if bad_cols.include? idx
#process the data
end

Resources