Gray code is a form of binary encoding where transitions between consecutive numbers differ by only one bit. This is a useful encoding for reducing hardware data hazards with values that change rapidly and/or connect to slower hardware as inputs. It is also useful for generating inputs for Karnaugh maps.

Here is an exemple of what the code look like:

```
0:    0000
1:    0001
2:    0011
3:    0010
4:    0110
5:    0111
6:    0101
7:    0100
8:    1100
```

The goal of this kata is to build two function bin2gray and gray2bin wich will convert natural binary to Gray Code and vice-versa. We will use the "binary reflected Gray code". The input and output will be arrays of 0 and 1, MSB at index 0.

There are "simple" formula to implement these functions. It is a very interesting exercise to find them by yourself.

All input will be correct binary arrays.

Difficulty: introductory

Starter code:

def bin2gray(bits):
	

Solutions:
def bin2gray(bits):
  bits.reverse()
  return list(reversed([x if i >= len(bits) - 1 or bits[i + 1] == 0 else 1 - x for i, x in enumerate(bits)]))
  
def gray2bin(bits):
  for i, x in enumerate(bits):
    if i > 0 and bits[i - 1] != 0: bits[i] = 1 - x
  return bits

def bitlist(func):
    def wrapper(bits):
        i = int(''.join([str(b) for b in bits]), 2)
        result = func(i)
        return [int(b) for b in bin(result)[2:]]
    return wrapper

@bitlist
def bin2gray(bits):
    return bits >> 1 ^ bits

@bitlist
def gray2bin(bits):
    mask = bits >> 1
    while(mask != 0):
         bits ^= mask
         mask >>= 1
    return bits


def bin2gray(bits):
    return [1-x if i and bits[i-1] else x for i,x in enumerate(bits)]

def gray2bin(bits):
    result, memo = [], bits[0]
    for i,x in enumerate(bits):
        if i and x:
            result.append(1-memo)
        else:
            result.append(memo)
        memo = result[-1]
    return result

bin2gray=lambda b:[b[0]]+[b[i+1]^j for i,j in enumerate(b[:-1])]
def gray2bin(g):
    b = [g[0]]
    for i in g[1:]:
        b.append(b[-1] ^ i)
    return b

def bin2gray(bits):
    return bits[:1] + [b1 ^ b2 for b1, b2 in zip(bits, bits[1:])]

def gray2bin(bits):
    return [reduce(lambda x, y: x ^y, bits[:i+1], 0) for i in range(len(bits))]

def bin2gray(bits):
    gray=[]
    gray.append(bits[0])
    for index in range(1,len(bits),1):
        gray.append(bits[index-1]^bits[index])    
    return gray
    
def gray2bin(bits):
    bin=[]
    bin.append(bits[0])
    for index in range(1,len(bits),1):
        bin.append(bin[index-1]^bits[index])
    return bin   

def bin2gray(bits):
    return [x^y for x,y in zip(bits,[0]+bits)]
def gray2bin(bits):
    return [reduce(lambda x,y:x^y,bits[:i+1]) for i, _ in enumerate(bits)]

def bin2gray(bits):
    g = [bits[0]] * len(bits)
    for i in range(1, len(bits)):
        g[i] = bits[i] ^ bits[i - 1]
    return g


def gray2bin(bits):
    b = [bits[0]] * len(bits)
    for i in range(1, len(bits)):
        b[i] = bits[i] ^ b[i - 1]
    return b


def i2l(i):
    l = []
    while i != 0:
        l.append(i % 2)
        i >>= 1
    l.reverse()
    return l if l else [0]
    
def l2i(l):
    i = 0
    for b in l:
        i = i * 2 + b
    return i
    
def bin2gray(bits):
    bits = l2i(bits)
    return i2l(bits ^ (bits >> 1))
def gray2bin(bits):
    bits = l2i(bits)
    m = bits >> 1
    while m:
        bits = bits ^ m
        m >>= 1
    return i2l(bits)