Need help with a homework

I want the code to:

deleteCntg([a,a,b,b,b,c,c,c],[a,b,c]).
true.
deleteCntg([a,a,b,b,b,c,c,c],[a,b,b,c].
false.
deleteCntg([a,b,c,a,b,c],[a,b,c]).
false.
deleteCntg([a,b,c,a,b,c],[a,b,c,a,b,c]).
true.
deleteCntg([[a],[b],[b],[a],[a],[b]], [[a],[b],[a],[b]]).
true.
deleteCntg([[a],b,[a,b,[c]],[a,b,[c]],[a,b,[a]],c],X).
X = [[a],b,[a,b,[c]],[a,b,[a]],c] .

What is the best way to do this?

Also I have another problem

?- subset_add([10,7,3,4,2,1],7,L).
L = [7] ;
L = [3, 4] ;
L = [4, 2, 1] ;
false.
?- subset_add([1,2,3],0,L).
L = [] ;
false.

What is the best way to do this?

As for subset_add/3, how about to use select/3 for successive selection of elements
until the sum is obtained ?

As for deleteCntg/2, I could not guess its specification; what does it ?

It seems to do what the uniq command does on *nix: filter adjacent repeats. @rodry7 you could use clumped/2 and drop the counts:

uniq(L, U) :-
    clumped(L, C),
    pairs_keys(C, U).

This works (using a better name than deleteCntg):

remove_same_successors([], []).
remove_same_successors([H|T], [H|LstRemoved]) :-
    remove_same_successors_([H|T], H, LstRemoved).

remove_same_successors_([], _, []).
remove_same_successors_([H|T], H, L) :-
    !,
    remove_same_successors_(T, H, L).
remove_same_successors_([H|T], _Prev, [H|L]) :-
    remove_same_successors_(T, H, L).

Great, now you did OP’s homework.

3 Likes

Hey brebs thank you so much this is so helpful, I appreciate it

Hi, Im trying to understand the select/3 functionality but how can I applied it to my second problem?

Just select from the list until you reach the sum or overshoot it. Although maybe it is better to use “subsequence” instead of subset. Depends on whoever gave you your homework and what they expect.

Are you going to attribute our help in your homework submission?

Oh ok, thanks.

And yes of course, I always like to mention if I ever got help and this is very helpful forum.

Why not just try using select/3 ?

?- select(X, [1,2,3,4], Rest).
X = 1,
Rest = [2,3,4] ;
X = 2,
Rest = [1,3,4] ;
X = 3,
Rest = [1,2,4] ;
X = 4,
Rest = [1,2,3].

As you can see, it selects one item from the list and also gives you the list without that item. You can also select two items:

?- forall((select(X, [1,2,3], Rest1), select(Y, Rest1, Rest2)), writeln(X-Y-Rest2)).
1-2-[3]
1-3-[2]
2-1-[3]
2-3-[1]
3-1-[2]
3-2-[1]

(Yes, this does look rather like permuting the list, doesn’t it?)

I think subset_add is a good homework for you to skill up you in Prolog programming, at least because it looks like to tell you some need of “accumulator” to “store” intermediate values which is always used in procedural language like C. Sorry, if this comment makes you confuse. This comment is from my experience at the beginning of my prolog programming. Anyway, I hope you solve it finally.

Are you wanting working code, or hints? Is easier if you show your nearly-working code.

Are you aware of Expandable text sections for hiding the working code so that the OP can read the hints and then only see the code if they choose.

1 Like

I can picture the scene:

But Sir, I only looked at the hint and didn’t peek at the provided code, honest. It’s pure coincidence that my own high-quality answer is completely identical including the variable names!

It’s not actually using select/3:

Code is hiding here, waiting to be clicked...
subset_sum(0, _, []).
subset_sum(Sum, SourceLst, [Elem|SumLst]) :-
    select_after(Elem, SourceLst, After),
    Sum0 is Sum - Elem,
    compare(Comp, Sum0, 0),
    subset_sum_(Comp, Sum0, After, SumLst).

subset_sum_(=, 0, _, []).
subset_sum_(>, Sum1, SourceLst, SumLst) :-
    subset_sum(Sum1, SourceLst, SumLst).

select_after(Elem, [H|T], After) :-
    select_after_(T, H, Elem, After).
    
select_after_(T, H, H, T).
select_after_([H|T], _, E, R) :-
    select_after_(T, H, E, R).

Results:

?- subset_sum(7, [10,7,3,4,2,1], L).
L = [7] ;
L = [3, 4] ;
L = [4, 2, 1] ;
false.

?- subset_sum(0, [10,7,3,4,2,1], L).
L = [] ;
false.

Note the tweaked argument order.