Gray code
Karnaugh maps
Create functions to encode a number to and decode a number from Gray code.

Display the normal binary representations, Gray code representations, and decoded Gray code values for all 5-bit binary numbers (0-31 inclusive, leading 0's not necessary).

There are many possible Gray codes. The following encodes what is called "binary reflected Gray code."

Encoding (MSB is bit 0, b is binary, g is Gray code):

if b[i-1] = 1
   g[i] = not b[i]
else
   g[i] = b[i]
Or:

g = b xor (b logically right shifted 1 time)
Decoding (MSB is bit 0, b is binary, g is Gray code):

b[0] = g[0]

for other bits:
b[i] = g[i] xor b[i-1]
Reference
 Converting Between Gray and Binary Codes. It includes step-by-step animations.
let gray_encode b =
  b lxor (b lsr 1)
 
let gray_decode n =
  let rec aux p n =
    if n = 0 then p
    else aux (p lxor n) (n lsr 1)
  in
  aux n (n lsr 1)
 
let bool_string len n =
  let s = Bytes.make len '0' in
  let rec aux i n =
    if n land 1 = 1 then Bytes.set s i '1';
    if i <= 0 then (Bytes.to_string s)
    else aux (pred i) (n lsr 1)
  in
  aux (pred len) n
 
let () =
  let s = bool_string 5 in
  for i = 0 to pred 32 do
    let g = gray_encode i in
    let b = gray_decode g in
    Printf.printf "%2d : %s => %s => %s : %2d\n" i (s i) (s g) (s b) b
  done