* (Q) Find all combinations of 1, 2, ..., n items out of m items.

* (A) by rlevesque@videotron.ca 2001/08/30;
	SPSS Dedicated web site http://pages.infinit.net/rlevesqu/index.htm.

* Note: This is a complex syntax but it is very easy to use. See the example at the end.
*	3 macros are defined by the syntax,
	the first of these macros (combina) writes a syntax file 
	which subsequently writes a text file. The text file is read into the data editor and 
	used to write all combinations.


SET MPRINT=no.

*/////////////////////////////.
DEFINE !combine (n=!TOKENS(1) 
	/items=!CMDEND).

/* Find all combinations of 1,2, ... n items out of m items*/
/* August 30,2001 rlevesque@videotron.ca */

* Count number of variables.
!LET !nb=!NULL
!DO !cnt !IN (!items)
!LET !nb=!CONCAT(!nb,!BLANK(1))
!DOEND
!LET !m=!LENGTH(!nb)

!DO !thisn=1 !TO !n
NEW FILE.
INPUT PROGRAM.
LOOP i=1 TO !thisn.
END CASE.
END LOOP.
END FILE.
END INPUT PROGRAM.
LIST.

!LET !list=!NULL
!DO !cnt=1 !TO !thisn
	!LET !list=!CONCAT(!list," ","j",!cnt)
!DOEND

COMPUTE n=!thisn.

* Calculate variable names for LOOP of the next WRITE command *.
STRING cntname cntbeg(A8).

COMPUTE cntname=CONCAT('j',LTRIM(STRING(i,F8.0))).

* Calculate first parameter for the LOOP of the next WRITE command *.
DO IF i=1.
COMPUTE cntbeg="1".
ELSE.
COMPUTE cntbeg=CONCAT('j',LTRIM(STRING(i-1,F8.0))," + 1").
END IF.

* Calculate second parameter for the LOOP of the next WRITE command *.
COMPUTE k=!m - !thisn + i.
FORMATS i k n(F8.0).

STRING quote(A1) strlist(A255).
COMPUTE quote='"'.
COMPUTE strlist=!QUOTE(!list).

* Write the syntax file which will store all the combinations in the list.txt file*.
WRITE OUTFILE "c:\\temp\\macro.sps" 
	/"LOOP "cntname"="cntbeg" TO "k".".
DO IF i=!thisn.
+	WRITE OUTFILE "c:\\temp\\macro.sps" 
	/"WRITE OUTFILE "quote"c:\\temp\\list.txt"quote "/" strlist "." .
+	LOOP cnt=1 TO !thisn.
+		WRITE OUTFILE "c:\\temp\\macro.sps" /"END LOOP.".
+	END LOOP.
+	WRITE OUTFILE "c:\\temp\\macro.sps" /"EXECUTE.". 
END IF.
EXECUTE.
INCLUDE FILE="c:\\temp\\macro.sps".

/* Convert data from list.txt to the corresponding sav file */.
DATA LIST FILE='c:\\temp\\list.txt' LIST /!list.
SAVE OUTFILE=!QUOTE(!CONCAT('c:\\temp\\list',!thisn,'.sav')).
!DOEND

/* Combine all the sav files */.
GET FILE='c:\\temp\\list1.sav'.
!DO !nb=2 !TO !n.
ADD FILES FILE=* 
	/FILE=!QUOTE(!CONCAT('c:\\temp\\list',!nb,'.sav.')).
!DOEND

/* Eliminate duplicates  */.
SORT CASES BY ALL.
MATCH FILES FILE=* /BY=ALL /FIRST=first.
SELECT IF first.
SAVE OUTFILE='c:\\temp\\all combinations.sav'.

/* Find name of last variables */
!DO !var !IN (!items)
!LET !lastone=!var
!DOEND

VECTOR vnames(!m A8).
!LET !cnt=!BLANK(1)

/* Create variables containing the names of the items variables */
!DO !var !IN (!items)
COMPUTE vnames(!LEN(!cnt))=!QUOTE(!var).
!LET !cnt=!CONCAT(!cnt,!BLANK(1))
!DOEND

/* Construct the string containing the list of combinations */.
STRING items(A255).
VECTOR j=j1 TO !CONCAT('j',!n) /ind=vnames1 TO  !CONCAT('vnames',!m).
COMPUTE nvar=NVALID(j1 TO !CONCAT('j',!n)).
LOOP cnt=1 TO nvar.
COMPUTE items=CONCAT(RTRIM(items)," ",vnames(j(cnt))).
END LOOP.

EXECUTE.

!ENDDEFINE.
*////////////////////////////.


*************************.
* EXAMPLES OF USE.
*************************.

SET MPRINT=yes.
!combine n=5 items=educ jobcat jobtime prevexp minority.

* Example 2.
!combine n=3 items=a b c d e f g.