So I have a list that looks like this:
[
["p1", "p2", "100", "Storgatan"],
["p1", "p3", "200", "Lillgatan"],
["p2", "p4", "100", "Nygatan"],
["p3", "p4", "50", "Kungsgatan"],
["p4", "p5", "150", "Kungsgatan"]
]
The elements in each nested list represent (in order):
1st element = Start Point
2nd element = End Point
3rd element = Distance
4th element = Street Name.
I have to now write a predicate which figures out which street is the shortest and which street is the longest, along with their respective (summed up) distances.
For example the final output should look something like this:
Longest street: Kungsgatan, 200
Shortest street: Storgatan, 100
I don't really understand why the start and end points are relevant information here. My current idea is to collect all the unique street names, put them in a separate list along with a counter for each street that starts at zero and then use that list to accumulate all of the distances for each separate street.
Something like:
create_sum_list([
["p1", "p2", "100", "Storgatan"],
["p1", "p3", "200", "Lillgatan"],
["p2", "p4", "100", "Nygatan"],
["p3", "p4", "50", "Kungsgatan"],
["p4", "p5", "150", "Kungsgatan"]
], SL).
SL= [[Storgatan, 0], [Lillgatan, 0],
[Nygatan, 0], [Kungsgatan ,0]]
accumulate(SL, List).
List=[[Storgatan, 100], [Lillgatan, 200],
[Nygatan, 100], [Kungsgatan ,200]]
This is probably a stupid idea and there is probably a way better way to solve this. I have thought of many different ideas where I either reach a dead end or they are way too complex for such a "simple" task.
I can achieve this easily through "normal" imperative programming but I am new to logical programming and Prolog. I have no idea how to achieve this.
Help?
Thanks!
If you already have a list and you want to group by street name and sum the lengths, you must decide how you do the grouping. One way is to use library(pairs):
streets_lengths(S, L) :-
maplist(street_name_and_length, S, NL),
keysort(NL, NL_sorted),
group_pairs_by_key(NL_sorted, G),
maplist(total_lengths, G, GT),
transpose_pairs(GT, By_length), % sorts!
group_pairs_by_key(By_length, L).
street_name_and_length([_, _, N, L], L_atom-N_number) :-
number_string(N_number, N),
atom_string(L_atom, L).
total_lengths(S-Ls, S-T) :-
sum_list(Ls, T).
You can use it like this:
?- streets_lengths([
["p1", "p2", "100", "Storgatan"],
["p1", "p3", "200", "Lillgatan"],
["p2", "p4", "100", "Nygatan"],
["p3", "p4", "50", "Kungsgatan"],
["p4", "p5", "150", "Kungsgatan"]
], SL).
SL = [100-['Storgatan', 'Nygatan'], 200-['Lillgatan', 'Kungsgatan']].
Since there can be many streets with the same length, the results are returned grouped by length. You can get the "shortest" and "longest" by getting the first and last element of the list, like this:
L = [First|_], last(L, Last)
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments