CALL GRAYCODE Routine

Generates all subsets of n items in a minimal change order.

Category: Combinatorial

Syntax

CALL GRAYCODE(k, numeric-variable-1, ..., numeric-variable-n);
CALL GRAYCODE(k, character-variable <, n <, in-out> > );

Required Arguments

k

specifies a numeric variable. Initialize k to either of the following values before executing the CALL GRAYCODE routine:

  • a negative number to cause CALL GRAYCODE to initialize the subset to be empty
  • the number of items in the initial set indicated by numeric-variable-1 through numeric-variable-n, or character-variable, which must be an integer value between 0 and N inclusive
The value of k is updated when CALL GRAYCODE is executed. The value that is returned is the number of items in the subset.

numeric-variable

specifies numeric variables that have values of 0 or 1 which are updated when CALL GRAYCODE is executed. A value of 1 for numeric-variable-j indicates that the jth item is in the subset. A value of 0 for numeric-variable-j indicates that the jth item is not in the subset.

If you assign a negative value to k before you execute CALL GRAYCODE, then you do not need to initialize numeric-variable-1 through numeric-variable-n before executing CALL GRAYCODE unless you want to suppress the note about uninitialized variables.
If you assign a value between 0 and n inclusive to k before you execute CALL GRAYCODE, then you must initialize numeric-variable-1 through numeric-variable-n to k values of 1 and n-k values of 0.

character-variable

specifies a character variable that has a length of at least n characters. The first n characters indicate which items are in the subset. By default, an "I" in the jth position indicates that thejth item is in the subset, and an "O" in the jth position indicates that the jth item is out of the subset. You can change the two characters by specifying the in-out argument.

If you assign a negative value to k before you execute CALL GRAYCODE, then you do not need to initialize character-variable before executing CALL GRAYCODE unless you want to suppress the note about an uninitialized variable.
If you assign a value between 0 and n inclusive to k before you execute CALL GRAYCODE, then you must initialize character-variable to k characters that indicate an item is in the subset, and k-k characters that indicate an item is out of the subset.

Optional Arguments

n

specifies a numeric constant, variable, or expression. By default, n is the length of character-variable.

in-out

specifies a character constant, variable, or expression. The default value is "IO." The first character is used to indicate that an item is in the subset. The second character is used to indicate that an item is out of the subset.

Details

Using CALL GRAYCODE in a DATA Step

When you execute the CALL GRAYCODE routine with a negative value of k, the subset is initialized to be empty.
When you execute the CALL GRAYCODE routine with an integer value of k between 0 and n inclusive, one item is either added to the subset or removed from the subset, and the value of k is updated to equal the number of items in the subset.
To generate all subsets of n items, you can initialize k to a negative value and execute CALL GRAYCODE in a loop that iterates 2**n times. If you want to start with a non-empty subset, then initialize k to be the number of items in the subset, initialize the other arguments to specify the desired initial subset, and execute CALL GRAYCODE in a loop that iterates 2**n-1 times. The sequence of subsets that are generated by CALL GRAYCODE is cyclical, so you can begin with any subset that you want.

Using the CALL GRAYCODE Routine with Macros

You can call the GRAYCODE routine when you use the %SYSCALL macro. Differences exist when you use CALL GRAYCODE in a DATA step and when you use the routine with macros. The following list describes usage with macros:
  • All arguments must be initialized to nonblank values.
  • If you use the character-variable argument, then it must be initialized to a nonblank, nonnumeric character string that contains at least n characters.
  • If you use the in-out argument, then it must be initialized to a string that contains two characters that are not blanks, digits, decimal points, or plus and minus signs.
If %SYSCALL identifies an argument as being the wrong type, or if %SYSCALL is unable to identify the type of argument, then &SYSERR and &SYSINFO are not set.
Otherwise, if an error occurs during the execution of the CALL GRAYCODE routine, then both of the following values are set:
  • &SYSERR is assigned a value that is greater than 4.
  • &SYSINFO is assigned a value that is less than –100.
If there are no errors, then &SYSERR is set to zero, and &SYSINFO is set to one of the following values:
  • 0 if the value of k on input is negative
  • the index of the item that was added or removed from the subset if the value of k on input is a valid nonnegative integer.

Examples

Example 1: Using a Character Variable and Positive Initial k with CALL GRAYCODE

The following example uses the CALL GRAYCODE routine to generate subsets in a minimal change order.
data _null_;
   x='++++';
   n=length(x);
   k=countc(x, '+');
   put '    1' +3 k= +2 x=;
   nsubs=2**n;
   do i=2 to nsubs;
      call graycode(k, x, n, '+-');
      put i 5. +3 k= +2 x=;
   end;
run;
SAS writes the following output to the log:
    1   k=4   x=++++
    2   k=3   x=-+++
    3   k=2   x=-+-+
    4   k=3   x=++-+
    5   k=2   x=+--+
    6   k=1   x=---+
    7   k=0   x=----
    8   k=1   x=+---
    9   k=2   x=++--
   10   k=1   x=-+--
   11   k=2   x=-++-
   12   k=3   x=+++-
   13   k=2   x=+-+-
   14   k=1   x=--+-
   15   k=2   x=--++
   16   k=3   x=+-++

Example 2: Using %SYSCALL with Numeric Variables and Negative k

The following example uses the %SYSCALL macro with numeric variables to generate subsets in a minimal change order.
%macro test;
   %let n=3;
   %let x1=.;
   %let x2=.;
   %let x3=.;
   %let k=-1;
   %let nsubs=%eval(2**&n + 1);
   %put nsubs=&nsubs k=&k x: &x1 &x2 &x3;
   %do j=1 %to &nsubs;
      %syscall graycode(k, x1, x2, x3);
      %put &j: k=&k x: &x1 &x2 &x3 sysinfo=&sysinfo;
   %end;
%mend;
%test;
SAS writes the following output to the log:
nsubs=9 k=-1 x: . . .
1: k=0 x: 0 0 0 sysinfo=0
2: k=1 x: 1 0 0 sysinfo=1
3: k=2 x: 1 1 0 sysinfo=2
4: k=1 x: 0 1 0 sysinfo=1
5: k=2 x: 0 1 1 sysinfo=3
6: k=3 x: 1 1 1 sysinfo=1
7: k=2 x: 1 0 1 sysinfo=2
8: k=1 x: 0 0 1 sysinfo=1
9: k=0 x: 0 0 0 sysinfo=3

Example 3: Using %SYSCALL with a Character Variable and Negative k

The following example uses the %SYSCALL macro with a character variable to generate subsets in a minimal change order.
%macro test(n);
   %*** Initialize the character variable to a 
        sufficiently long nonblank, nonnumeric value. ;
   %let x=%sysfunc(repeat(_, &n-1));
   %let k=-1;
   %let nsubs=%eval(2**&n + 1);
   %put nsubs=&nsubs k=&k x="&x";
   %do j=1 %to &nsubs;
      %syscall graycode(k, x, n);
      %put &j: k=&k x="&x" sysinfo=&sysinfo;
   %end;
%mend;
%test(3);
SAS writes the following output to the log:
nsubs=9 k=-1 x="___"
1: k=0 x="OOO" sysinfo=0
2: k=1 x="IOO" sysinfo=1
3: k=2 x="IIO" sysinfo=2
4: k=1 x="OIO" sysinfo=1
5: k=2 x="OII" sysinfo=3
6: k=3 x="III" sysinfo=1
7: k=2 x="IOI" sysinfo=2
8: k=1 x="OOI" sysinfo=1
9: k=0 x="OOO" sysinfo=3

See Also

Functions: