Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!gatech!howland.reston.ans.net!news.sprintlink.net!EU.net!uknet!festival!ainews!aisb!markg
From: markg@aisb.ed.ac.uk (Mark Gallagher)
Subject: Re: Subset code
Message-ID: <Cyy3LC.5vG@aisb.ed.ac.uk>
Keywords: Subsets
Sender: news@aisb.ed.ac.uk (Network News Administrator)
Reply-To: markg@aisb.ed.ac.uk (Mark Gallagher)
Organization: Dept of AI, University of Edinburgh, Scotland
References:  <geoff.784196084@coral.cs.jcu.edu.au>
Date: Tue, 8 Nov 1994 10:53:35 GMT
Lines: 58

In article <geoff.784196084@coral.cs.jcu.edu.au>, geoff@coral.cs.jcu.edu.au
(Geoff Sutcliffe) writes:
# Hi,
# 
# I have an application in which I need to create, on backtracking, all 
# subsets of a given set in decreasing order of size. Example
# ?- subset([q,w,e]).
# must, by backtracking, return [q,w,e] [q,w] [q,e] [w,e] [q] [w] [e] [] 
# _in that order_.
# 
# My solution seems inelegant :
# %----------------------------------------------------------------------
# subset(Set):-
#     length(Set,SetLength),
#     integer_in_range(0,SetLength,NumberToRemove),
#     remove_N(Set,NumberToRemove,Subset),
#     write(Subset),nl,
#     fail.
# %----------------------------------------------------------------------
# %----Provide a range of integers through backtracking
# integer_in_range(Low,High,Low):-
#     Low =< High.
# 
# integer_in_range(Low,High,Integer):-
#     Low < High,
#     NewLow is Low + 1,
#     integer_in_range(NewLow,High,Integer).
# %----------------------------------------------------------------------
# remove_N(List,0,List).
# 
# remove_N([H|T],N,[H|RestOfList]):-
#     N > 0,
#     remove_N(T,N,RestOfList).
# 
# remove_N([_|T],N,List):-
#     N > 0,
#     N1 is N - 1,
#     remove_N(T,N1,List).
# %----------------------------------------------------------------------
# 
# Does anyone have a neater solution to suggest?
# 
# Cheers,
# 
# Geoff

Try this:

   subsets(Set, SubSets) :-
      bagof(SubSet, subset(Set, SubSet), SubSets).

   subset([], []).
   subset([Hd|Tl1], [Hd|Tl2]) :-
      subset(Tl1, Tl2).
   subset([Hd|Tl1], Tl2) :-
      subset(Tl1, Tl2).

Isn't 'bagof/3' useful?
