Gray code

sub gray_encode ( Int $n --> Int ) {
    return $n +^ ( $n +> 1 );
}

sub gray_decode ( Int $n is copy --> Int ) {
    my $mask = 1 +< (32-2);
    $n +^= $mask +> 1 if $n +& $mask while $mask +>= 1;
    return $n;
}

for ^32 -> $n {
    my $g = gray_encode($n);
    my $d = gray_decode($g);
    printf "%2d: %5b => %5b => %5b: %2d\n", $n, $n, $g, $d, $d;
    die if $d != $n;
}

Output:

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

Raku distinguishes numeric bitwise operators with a leading + sign, so +< and +> are left and right shift, while +& is a bitwise AND, while +^ is bitwise XOR (here used as part of an assignment metaoperator).

Last updated