File : combinations.sp


$ spar combinations
 0 1 2
 0 1 3
 0 1 4
 0 2 3
 0 2 4
 0 3 4
 1 2 3
 1 2 4
 1 3 4
 2 3 4


#!/usr/local/bin/spar

pragma annotate( summary, "combinations" )
       @( description, "Given non-negative integers m and n, generate all size m" )
       @( description, "combinations of the integers from 0 to n-1 in sorted" )
       @( description, "order (each combination is sorted and the entire table" )
       @( description, "is sorted" )
       @( see_also, "http://rosettacode.org/wiki/Combinations" )
       @( author, "Ken O. Burtch" );

pragma restriction( no_external_commands );

procedure combinations is
  number_of_items : constant natural := 3;
  max_item_value  : constant natural := 5;

  -- get_first_combination
  -- return the first combination (e.g. 0,1,2 for 3 items)

  function get_first_combination return string is
    c : string;
  begin
    for i in 1..number_of_items loop
      c := @ & strings.image( natural( i-1 ) );
    end loop;
    return c;
  end get_first_combination;

  -- get_last_combination
  -- return the highest value (e.g. 4,4,4 for 3 items
  -- with a maximum value of 5).

  function get_last_combination return string is
    c : string;
  begin
    for i in 1..number_of_items loop
      c := @ & strings.image( max_item_value-1 );
    end loop;
    return c;
  end get_last_combination;

  combination : string := get_first_combination;
  last_combination : constant string := get_last_combination;

  item : natural; -- a number from the combination
  bad : boolean; -- true if we know a value is too big
  s : string;    -- a temp string for deleting leading space

begin
  put_line( combination );
  while combination /= last_combination loop

    -- the combination is 3 numbers with leading spaces
    -- so the field positions start at 2 (1 is a null string)

    for i in reverse 1..number_of_items loop
        item := numerics.value( strings.field( combination, i+1, ' ') );
        if item < max_item_value-1 then
           item := @+1;
           s := strings.image( item );
           s := strings.delete( s, 1, 1 );
           strings.replace( combination, i+1, s, ' ' );
           bad := false;
           for j in i+1..number_of_items loop
              item := numerics.value( strings.field( combination, j, ' ') );
              if item < max_item_value-1 then
                 item := @+1;
                 s := strings.image( item );
                 s := strings.delete( s, 1, 1 );
                 strings.replace( combination, j+1, s, ' ' );
              else
                 bad;
                  end if;
           end loop;
           exit;
        end if;
    end loop;
        if not bad then
           put_line( combination );
    end if;
  end loop;
end combinations;

-- VIM editor formatting instructions
-- vim: ft=spar