counting the elements of a list of lists PROLOG - prolog

I am trying to count the elements of a list of
lists.
I implemented the code in this way:
len1([],0).
len1([_X|Xs],N) :- len1(Xs,N1), N is N1+1.
clist([[],[]],0).
clist([Xs,Ys],N):- len1(Xs,N1),len1(Ys,N2),N is N1+N2.
i re-use count element (len1 predicates) in a list, and seems work.
Anyone can say me if is nice work, very bad or can do this but it s preferable other (without len1).
I dont think is good implementation, and otherwhise seems not generic.
Ad example this work only with list, that contain two list inside. If i want make generic? i think need to use _Xs, but i try to change my code and not working.
in particular i try to change this:
clist([Xs,Ys],N):- len1(Xs,N1),len1(Ys,N2),N is N1+N2.
in
clist([_Xs],N):- len1(_Xs,N1),N is N1.
and obviously don't work.

Well you can apply the same trick for your clist/2 predicate: instead of solving the problem for lists with two elements, you can consider two cases:
an empty list [], in which case the total number is of course zero; and
a non-empty list [H|T], where H is a list, and T is the list of remaining lists. In that case we first calculate the length of H, we the calculate (through recursion) the sum of the lists in T and then sum these together.
So we can implement this as:
clist([], 0).
clist([H|T], N) :-
length(H, HN),
clist(T, TN),
N is HN + TN.
The above can be improved by using an accumulator: we can define a predicate clist/3 that has a variable that stores the total number of elements in the list this far, in case we reach the end of the list, we unify the answer with that variable, like:
clist(L, N) :-
clist(L, 0, N).
clist([], N, N).
clist([H|T], N1, N) :-
length(H, HN),
N2 is N1 + HN,
clist(T, N2, N).

Yes, you were correct in wanting to generalize your definition. Instead of
clist([[],[]],0).
(well, first, it should be
clist( [] , 0).
Continuing...) and
clist([Xs,Ys], N):- len1(Xs,N1), len1(Ys,N2), N is N1+N2.
which handles two lists in a list, change it to
clist([Xs|YSs], N):- len1(Xs,N1), len1(YSs,N2), N is N1+N2.
to handle any number of lists in a list. But now the second len1 is misapplied. It receives a list of lists, not just a list as before. Faced with having to handle a list of lists (YSs) to be able to handle a list of lists ([Xs|YSs]), we're back where we started. Are we, really?
Not quite. We already have the predicate to handle the list of lists -- it's clist that we're defining! Wait, what? Do we have it defined yet? We haven't finished writing it down, yes, but we will; and when we've finished writing it down we will have it defined. Recursion is a leap of faith:
clist([Xs|YSs], N):- len1(Xs,N1), clist(YSs,N2), N is N1+N2.
Moreover, this second list of lists YSs is shorter than [Xs|YSs]. An that is the key.
And if the lists were arbitrarily deeply nested, the recursion would be
clist([XSs|YSs], N):- clist(XSs,N1), clist(YSs,N2), N is N1+N2.
with the appropriately mended base case(s).
Recursion is a leap of faith: assume we have the solution already, use it to handle smaller sub-cases of the problem at hand, simply combine the results - there you have it! The solution we assumed to have, coming into existence because we used it as if it existed already.
recursion( Whole, Solution ) :-
problem( Whole, Shell, NestedCases),
maplist( recursion, NestedCases, SolvedParts),
problem( Solution, Shell, SolvedParts).
A Russian matryoshka doll of problems all the way down, turned into solutions all the way back up from the deepest level. But the point is, we rely on recursion to handle the inner matryoshka, however many levels it may have nested inside her. We only take apart and reassemble the one -- the top-most.

howMany([],_,0).
howMany([Head|Tail],X,Times):-
\+(Head = X),
howMany(Tail,X,Times1),
Times is Times1.
howMany([Head|Tail],X,Times):-
Head = X,
howMany(Tail,X,Times1),
Times is Times1 +1.

Related

Finding occurrences of predicate within list

I'm attempting to find the amount of inversions within a list. Inversions would be defined as any pair a,b from a list, where ai is the index of a and bi is the index of b that satisfies a > b and ai < bi. Essentially a comes before b but yet is larger than b.
The first thing I did was write a predicate to find out what the index is.
indexOf(Index, Element, List) :-
nth1(Index, List, Element).
Then I wrote a predicate to determine if any set of two numbers is an inversion
isInversion(A, B, List) :-
A \= B, indexOf(AI, A, List), indexOf(BI, B, List), A > B, AI < BI.
At this point I have a lot of questions, especially as I'm very unfamiliar with logic programming languages. My first question is, indexOf won't actually give me the index will it? I'm confused how that would actually work as it seems like it'd essentially have to try every number, which I'm not explicitly telling it to do.
If somehow indexOf will automatically determine the index and store it in AI/BI like I'm expecting, then I believe my isInversion predicate will evaluate correctly, if I'm wrong please let me know.
My main concern is how to actually determine the amount of inversions. In something like python I would do
count = 0
for a in puzzle
for b in puzzle
if a is b continue
if isInversion(a, b, puzzle)
count = count + 1
That would give me my amount of inversions. But how can I do this in prolog? For loops don't seem very stylistic so I don't want to use that.
Something to note, I have searched for other questions. It's a little tough since I obviously don't know exactly what I'm trying to look for. However I just wanted to make it clear that I felt things such as Prolog do predicate for all pairs in List? didn't help me answer the question.
You should remove the constraint A\=B as it will fail with unbound variables.
Then use aggregate_all/3 to count all the inversions (you don't actually need the values A/B of the inversion):
isInversion(A, B, List):-
indexOf(AI, A, List),
indexOf(BI, B, List),
A > B,
AI < BI.
countInversions(List, N):-
aggregate_all(count, isInversion(_, _, List), N).
Sample run:
?- countInversions([4,3,2,1,9], N).
N = 6.
You may see which inversions exists using findall/3 on isInversion:
?- findall(A-B, isInversion(A,B,[4,3,2,1,9]), LInversions).
LInversions = [4-3, 4-2, 4-1, 3-2, 3-1, 2-1].

Finding the longest list in Prolog?

I need to write a predicate longestList/2 such that longestList(L1,L2) is satisfied if L2 is the longest
nested list from the list of lists L1.
?- longestList([[1],[1,2],[1,2,3],[1,2,3,4]],LI).
LI = [[1, 2, 3, 4]] ;
No
?- longestList([[a,b,c],[d,e],[f,g,h]],LI).
LI = [[f, g, h],[a,b,c]];
No
Could someone please help me with intuition to go about solving it?
Here's an outline for a basic, recursive approach. Not quite as crisp as the answer #CapelliC gave, but on the same order of simplicity.
The idea is to traverse the list and keep track of the longest list you've seen so far, and what it's length is. Then you step through the list recursively and update these arguments for the recursion if the conditions indicate so. It's a slight elaboration on the technique used to do a recursive "max list element" predicate. To do this, you set up a call to include more arguments (the current longest list, and its length).
longestList([], []).
longestList([L|Ls], LongestList) :-
length(L, Length),
% Start with the first element (L) being my best choice so far
longestList(Ls, L, Length, LongestList).
Here is the expanded predicate with the new arguments.
longestList([L|Ls], LongestListSoFar, GreatestLengthSoFar, LongestList) :-
% Here, you need to examine L and determine if it should supersede
% the longest list so far and its length. You need to keep in mind that
% if the length of L is the same as the max length so far, then I
% may choose to keep the LongestListSoFar, or choose L. Both are
% valid solutions for this call. This is a good place to use the `;`
% operator, and to be cautious about parenthesizing expressions since
% the comma has higher precedence than the semi-colon.
% Also, you'll need to make a recursive call to longestList(Ls, ??, ??, LongestList).
% The arguments to the recursion will depend upon which way the decision flow goes.
%
% After all that to-do, don't let it scare you: it's about 5 lines of code :)
%
longestList([], LongestListSoFar, ??, ??).
% Fill in the ??. What should they be at list's end ([])?
% Do I even care now what the 3rd argument is?
Hopefully that's enough to give you something to think about to make progress. Or, use #CapelliC's solution and write the member_length/3 predicate. :) Note that, as in his solution, the above solution would generate each maximum list on backtracking if there are more than one. So, you could use findall/3 if you want to get all the solutions in one list.
member/2 will allow you to peek an element (a list for your case) from a list: so, if you have a member_length/3 predicate, you could code
longestList(Lists, Longest) :-
member_length(Lists, Longest, N),
\+ ( member_length(Lists, _Another, M), M > N ).
then to find all longest, you can use findall/3...
Following code, which uses if else, seem to work partially. It has to be called with 0 length and so one cannot get length itself from here.
longest_list([H|T], LongList, LongLen):-
length(H, Len),
(Len > LongLen ->
longest_list(T, [H], Len);
longest_list(T, LongList, LongLen)).
longest_list([],Finallist,_):-writeln(Finallist).
?- longest_list([[1,2,3], [3,4], [4,5,6,7,8], [5,3,4]], Longestlist, 0).
[[4,5,6,7,8]]
true.
However, the variable itself is not coming:
?- writeln(Longestlist).
_G1955
true.
It may give some ideas.

Find best result without findall and a filter

I'm in a bit of pickle in Prolog.
I have a collection of objects. These objects have a certain dimension, hence weight.
I want to split up these objects in 2 sets (which form the entire set together) in such a way that their difference in total weight is minimal.
The first thing I tried was the following (pseudo-code):
-> findall with predicate createSets(List, set(A, B))
-> iterate over results while
---> calculate weight of both
---> calculate difference
---> loop with current difference and compare to current difference
till end of list of sets
This is pretty straightforward. The issue here is that I have a list of +/- 30 objects. Creating all possible sets causes a stack overflow.
Helper predicates:
sublist([],[]).
sublist(X, [_ | RestY]) :-
sublist(X,RestY).
sublist([Item|RestX], [Item|RestY]) :-
sublist(RestX,RestY).
subtract([], _, []) :-
!.
subtract([Head|Tail],ToSubstractList,Result) :-
memberchk(Head,ToSubstractList),
!,
subtract(Tail, ToSubstractList, Result).
subtract([Head|Tail], ToSubstractList, [Head|ResultTail]) :-
!,
subtract(Tail,ToSubstractList,ResultTail).
generateAllPossibleSubsets(ListToSplit,sets(Sublist,SecondPart)) :-
sublist(Sublist,ListToSplit),
subtract(ListToSplit, Sublist, SecondPart).
These can then be used as follows:
:- findall(Set, generateAllPossibleSubsets(ObjectList,Set), ListOfSets ),
findMinimalDifference(ListOfSets,Set).
So because I think this is a wrong way to do it, I figured I'd try it in an iterative way. This is what I have so far:
totalWeightOfSet([],0).
totalWeightOfSet([Head|RestOfSet],Weight) :-
objectWeight(Head,HeadWeight),
totalWeightOfSet(RestOfSet, RestWeight),
Weight is HeadWeight + RestWeight.
findBestBalancedSet(ListOfObjects,Sets) :-
generateAllPossibleSubsets(ListOfObjects,sets(A,B)),
totalWeightOfSet(A,WeightA),
totalWeightOfSet(B,WeightB),
Temp is WeightA - WeightB,
abs(Temp, Difference),
betterSets(ListOfObjects, Difference, Sets).
betterSets(ListOfObjects,OriginalDifference,sets(A,B)) :-
generateAllPossibleSubsets(ListOfObjects,sets(A,B)),
totalWeightOfSet(A,WeightA),
totalWeightOfSet(B,WeightB),
Temp is WeightA - WeightB,
abs(Temp, Difference),
OriginalDifference > Difference,
!,
betterSets(ListOfObjects, Difference, sets(A, B)).
betterSets(_,Difference,sets(A,B)) :-
write_ln(Difference).
The issue here is that it returns a better result, but it hasn't traversed the entire solution tree. I have a feeling this is a default Prolog scheme I'm missing here.
So basically I want it to tell me "these two sets have the minimal difference".
Edit:
What are the pros and cons of using manual list iteration vs recursion through fail
This is a possible solution (the recursion through fail) except that it can not fail, since that won't return the best set.
I would generate the 30 objects list, sort it descending on weight, then pop objects off the sorted list one by one and put each into one or the other of the two sets, so that I get the minimal difference between the two sets on each step. Each time we add an element to a set, just add together their weights, to keep track of the set's weight. Start with two empty sets, each with a total weight of 0.
It won't be the best partition probably, but might come close to it.
A very straightforward implementation:
pair(A,B,A-B).
near_balanced_partition(L,S1,S2):-
maplist(weight,L,W), %// user-supplied predicate weight(+E,?W).
maplist(pair,W,L,WL),
keysort(WL,SL),
reverse(SL,SLR),
partition(SLR,0,[],0,[],S1,S2).
partition([],_,A,_,B,A,B).
partition([N-E|R],N1,L1,N2,L2,S1,S2):-
( abs(N2-N1-N) < abs(N1-N2-N)
-> N3 is N1+N,
partition(R,N3,[E|L1],N2,L2,S1,S2)
; N3 is N2+N,
partition(R,N1,L1,N3,[E|L2],S1,S2)
).
If you insist on finding the precise answer, you will have to generate all the partitions of your list into two sets. Then while generating, you'd keep the current best.
The most important thing left is to find the way to generate them iteratively.
A given object is either included in the first subset, or the second (you don't mention whether they're all different; let's assume they are). We thus have a 30-bit number that represents the partition. This allows us to enumerate them independently, so our state is minimal. For 30 objects there will be 2^30 ~= 10^9 generated partitions.
exact_partition(L,S1,S2):-
maplist(weight,L,W), %// user-supplied predicate weight(+E,?W).
maplist(pair,W,L,WL),
keysort(WL,SL), %// not necessary here except for the aesthetics
length(L,Len), length(Num,Len), maplist(=(0),Num),
.....
You will have to implement the binary arithmetics to add 1 to Num on each step, and generate the two subsets from SL according to the new Num, possibly in one fused operation. For each freshly generated subset, it's easy to calculate its weight (this calculation too can be fused into the same generating operation):
maplist(pair,Ws,_,Subset1),
sumlist(Ws,Weight1),
.....
This binary number, Num, is all that represents our current position in the search space, together with the unchanging list SL. Thus the search will be iterative, i.e. running in constant space.

How to count the number of children of parents in prolog (without using lists) in prolog?

I have the following problem. I have a certain number of facts such as:
parent(jane,dick).
parent(michael,dick).
And I want to have a predicate such as:
numberofchildren(michael,X)
so that if I call it like that it shows X=1.
I've searched the web and everyone puts the children into lists, is there a way not to use lists?
Counting number of solutions requires some extra logical tool (it's inherently non monotonic). Here a possible solution:
:- dynamic count_solutions_store/1.
count_solutions(Goal, N) :-
assert(count_solutions_store(0)),
repeat,
( call(Goal),
retract(count_solutions_store(SoFar)),
Updated is SoFar + 1,
assert(count_solutions_store(Updated)),
fail
; retract(count_solutions_store(T))
),
!, N = T.
I can only see two ways to solve this.
The first, which seems easier, is to get all the solutions in a list and count it. I'm not sure why you dislike this option. Are you worried about efficiency or something? Or just an assignment?
The problem is that without using a meta-logical predicate like setof/3 you're going to have to allow Prolog to bind the values the usual way. The only way to loop if you're letting Prolog do that is with failure, as in something like this:
numberofchildren(Person, N) :- parent(Person, _), N is N+1.
This isn't going to work though; first you're going to get arguments not sufficiently instantiated. Then you're going to fix that and get something like this:
?- numberofchildren(michael, N)
N = 1 ;
N = 1 ;
N = 1 ;
no.
The reason is that you need Prolog to backtrack if it's going to go through the facts one by one, and each time it backtracks, it unbinds whatever it bound since the last choice point. The only way I know of to pass data across this barrier is with the dynamic store:
:- dynamic(numberofchildrensofar/1).
numberofchildren(Person, N) :-
asserta(numberofchildrensofar(0)),
numberofchildren1(Person),
numberofchildrensofar(N), !.
numberofchildren1(Person) :-
parent(Person, _),
retract(numberofchildrensofar(N)),
N1 is N + 1,
asserta(numberofchildrensofar(N1),
!, fail.
numberofchildren1(_).
I haven't tested this, because I think it's fairly disgusting, but it could probably be made to work if it doesn't. :)
Anyway, I strongly recommend you take the list option if possible.

prolog: subsets of length k

in class we went over the subset_of/2 predicate that my teacher gave as follows:
subset_of([],[]).
subset_of([X|Xs],Zs):-subset_of(Xs,Ys),maybe_add(X,Ys,Zs).
maybe_add(_,Ys,Ys).
maybe_add(X,Ys,[X|Ys]).
subsets_of(Xs,Xss):-findall(Ys,subset_of(Xs,Ys),Xss).
He then asked us to change it to only give the subsets of some length K (but not by using length/2, by directly finding a recursive definition). My first attempt was to split up the subset_of call into one that adds the extra element and one that does not (instead of having the maybe_add call) and to keep track of the length of the list that was passed and check at the end, but this did not work as planned at all.
subset_of(K, 0, [],[]).
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subset_of(K, L1, Xs, Zs),
L1 == K.
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subset_of(K, L1, Xs,Ys),
do_add(X, Ys, Zs),
Len == K.
subsets_of(K,Xs,Xss):-
length(Xs, Len),
findall(Ys,subset_of(K, Len, Xs,Ys),Xss).
I am NOT asking for the correct code to solve this, but only a push in the right direction so I can keep trying to figure it out. This is my first time with a declarative languange and I am pretty confused.
If you don't want a direct answer, than I'd say that it can be done much simpler. I've got 3 rules in my solution. However I don't use this additional maybe_add formula or anything that resambles it. If you really need it, it can be used and it takes 5 arguments then - 3 input arguments and 2 output arguments. This reduces the number of rules for subset_of to only 2, just as in the original solution. They are quite similar after all.
Also watch out for repetitions. I think subset_of(0, _, []) as suggested in other answer may be a way that leads to repetitions. However there might be a correct solution that incorporates it, I'm not sure that there isn't.
Think of it as a proof of correctness. Say you wanted to prove recursively that one set is a K-element subset of another. How would you go about it. Look at the implications that you used. How can you turn them into Prolog rules?
Not using maybe_add seems like a good idea. However, you don't need two extra arguments: one will do. Your base clause would be
subset_of(0, _, []).
i.e., the empty set is a zero-element subset of anything. Of the two recursive clauses, one would look for K-1-element subsets, the other for K-sized subsets.

Resources