File : gray.sp


Number   Binary     Gray Decoded
     0     2#0#     2#0#       0
     1     2#1#     2#1#       1
     2    2#10#    2#11#       2
     3    2#11#    2#10#       3
     4   2#100#   2#110#       4
     5   2#101#   2#111#       5
     6   2#110#   2#101#       6
     7   2#111#   2#100#       7
     8  2#1000#  2#1100#       8
     9  2#1001#  2#1101#       9
    10  2#1010#  2#1111#      10
    11  2#1011#  2#1110#      11
    12  2#1100#  2#1010#      12
    13  2#1101#  2#1011#      13
    14  2#1110#  2#1001#      14
    15  2#1111#  2#1000#      15
    16 2#10000# 2#11000#      16
    17 2#10001# 2#11001#      17
    18 2#10010# 2#11011#      18
    19 2#10011# 2#11010#      19
    20 2#10100# 2#11110#      20
    21 2#10101# 2#11111#      21
    22 2#10110# 2#11101#      22
    23 2#10111# 2#11100#      23
    24 2#11000# 2#10100#      24
    25 2#11001# 2#10101#      25
    26 2#11010# 2#10111#      26
    27 2#11011# 2#10110#      27
    28 2#11100# 2#10010#      28
    29 2#11101# 2#10011#      29
    30 2#11110# 2#10001#      30
    31 2#11111# 2#10000#      31

#!/usr/local/bin/spar

pragma annotate( summary, "gray" );
pragma annotate( description, "Gray code is a form of binary encoding where " );
pragma annotate( description, "transitions between consecutive numbers differ by" );
pragma annotate( description, "only one bit. Create functions to encode a number" );
pragma annotate( description, "to and decode a number from Gray code. Display the" );
pragma annotate( description, "normal binary representations, Gray code" );
pragma annotate( description, "representations, and decoded Gray code values for all" );
pragma annotate( description, "5-bit binary numbers (0-31 inclusive, leading 0's not" );
pragma annotate( description, "necessary).  There are many possible Gray codes. The" );
pragma annotate( description, "following encodes what is called 'binary reflected" );
pragma annotate( description, "Gray code.'"  );
pragma annotate( see_also, "http://rosettacode.org/wiki/Gray_code" );
pragma annotate( author, "Ken O. Burtch" );
pragma license( unrestricted );

pragma restriction( no_external_commands );

procedure gray is

   bits : constant natural := 5;
   subtype nat_values is natural;

   function encode (binary : nat_values) return nat_values is
   begin
      return binary xor numerics.shift_right (binary, 1);
   end encode;

   -- SparForte 1.3 cannot print to numbers to different bases but we
   -- we can write a function

   function intToBin( nat_value : nat_values ) return string is
     result : string;
     v      : nat_values := nat_value;
   begin
     if v = 0 then
        result := '0';
     else
       while v > 0 loop
         if (v and 1) = 1 then
            result := '1' & @;
         else
            result := '0' & @;
         end if;
         v := numerics.shift_right( @, 1 );
       end loop;
     end if;
     return "2#" & result & "#";
   end intToBin;

   function decode (gray : nat_values) return nat_values is
      binary : nat_values;
      bit    : nat_values;
      mask   : nat_values := 2 ** (bits - 1);
   begin
      bit    := gray and mask;
      binary := bit;
      for i in 2 .. bits loop
         bit    := numerics.shift_right (@, 1);
         mask   := numerics.shift_right (mask, 1);
         bit    := (gray and mask) xor @;
         binary := @ + bit;
      end loop;
      return binary;
   end decode;

   j       : nat_values;
   ibinstr : string;
   jbinstr : string;

begin
   put_line ("Number   Binary     Gray Decoded");
   for i in 0..31 loop
      j := encode (i);
      -- convert i and j to base 2 representation
      ibinstr := intToBin(i);
      jbinstr := intToBin(j);
      -- for binary strings, right-justify
      put (i, "ZZZZZ9" ) @
          (' ' & strings.insert( ibinstr, 1, (8-strings.length(ibinstr)) * ' ' ) ) @
          (' ' & strings.insert( jbinstr, 1, (8-strings.length(jbinstr)) * ' ' ) ) @
          ( "  " ) @ (decode (j), "ZZZZZ9" );
      new_line;
   end loop;
end gray;

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