In [1]:
"""
    Some masks and the number of 16 bit words
    in our code, in this case, its 8. After
    we "sythesize" the other "strand of RNA
    code", we will have 8, 32 bit words, which
    as a whole is analogous to DNA.
"""
L_MASK = int('0x0000ffff', 16)
H_MASK = int('0xffff0000', 16)
ERBITS = int('0xffff0000', 16)
NLINES = 8
NERROR = NLINES - 1

In [2]:
"""
    Basically some aliases to avoid ( (((  ))) )
"""
fixRight = lambda x: x >> 16
fixLeft = lambda x: x << 16

In [3]:
"""
    Set up some commands for generating (pseudo) random
    16 bit code words and the complementary "strand of
    RNA code".
    
    riskyProc() is some simple case of a set of procedures,
    operations, or coditions, (such as transmittion, storage,
    recovery)
"""
from random import randint
KEY = randint(1, 2**16)
randCode = lambda : randint(0,2**16) # Generate a random code within 16 bit range
genCodePair = lambda code: (fixLeft(code ^ KEY) & H_MASK) + ( code & L_MASK ) # Generate the Complement ("hRNA + lRNA = DNA")
unZip = lambda prog: [(fixRight(x & H_MASK), x & L_MASK) for x in prog]
printBin32 = lambda x: bin(x)[2:].zfill(32) # Convert x to a binary string
printBin16 = lambda x: bin(x)[2:].zfill(16) # dido
def riskyProc(prog):
    rN = randint(0,len(prog)-1)
    prog[rN] = prog[rN] & ERBITS

In [4]:
"""
    dispCode() takes a code list (whole_code_list) and displays it
    after checking the code for errors, if there are errors, a notice
    is displayed too.
"""
def dispCode(whole_code_list):
    tup_list = unZip(whole_code_list)
    x = [(printBin32(whole_code_list[x]) ,(printBin16(tup_list[x][0]), printBin16(tup_list[x][1]) ) ) for x in range(len(tup_list))]
    for l in x:
        ls_int = int('0b' + l[1][0],2)
        rs_int = int('0b' + l[1][1],2)
        if KEY ^ ls_int == rs_int:
            print l
        else:
            print l, "<----- ERROR", (ls_int, rs_int, KEY ^ ls_int), "(a, b, a ^ b)"
    print "\n"
Prog = [genCodePair(randCode()) for x in range(NLINES)] # Generate a program (Prog) in this case.
backUp = [int(i) for i in Prog] # Make back up
print "Good code:"
dispCode(Prog)
for i in range(NERROR):
    riskyProc(Prog)
print "Bad code:"
dispCode(Prog)


Good code:
('00111000111101111100000100100100', ('0011100011110111', '1100000100100100'))
('01101101110101111001010000000100', ('0110110111010111', '1001010000000100'))
('11000010001001110011101111110100', ('1100001000100111', '0011101111110100'))
('01100010101001111001101101110100', ('0110001010100111', '1001101101110100'))
('11011100010000010010010110010010', ('1101110001000001', '0010010110010010'))
('00111001010001111100000010010100', ('0011100101000111', '1100000010010100'))
('10111001111100110100000000100000', ('1011100111110011', '0100000000100000'))
('11000111010101000011111010000111', ('1100011101010100', '0011111010000111'))


Bad code:
('00111000111101110000000000000000', ('0011100011110111', '0000000000000000')) <----- ERROR (14583, 0, 49444) (a, b, a ^ b)
('01101101110101110000000000000000', ('0110110111010111', '0000000000000000')) <----- ERROR (28119, 0, 37892) (a, b, a ^ b)
('11000010001001110011101111110100', ('1100001000100111', '0011101111110100'))
('01100010101001111001101101110100', ('0110001010100111', '1001101101110100'))
('11011100010000010010010110010010', ('1101110001000001', '0010010110010010'))
('00111001010001111100000010010100', ('0011100101000111', '1100000010010100'))
('10111001111100110000000000000000', ('1011100111110011', '0000000000000000')) <----- ERROR (47603, 0, 16416) (a, b, a ^ b)
('11000111010101000000000000000000', ('1100011101010100', '0000000000000000')) <----- ERROR (51028, 0, 16007) (a, b, a ^ b)



In [5]:
def healCode(tup_list, key):
    Prog = []
    for i in range(len(tup_list)):
        if key ^ tup_list[i][0] != tup_list[i][1]:
            """
            Need to determine if error is on left or right (higher or lower signifcant bits)
            # Some algebra
            [1] a1 ^ b1 = x
            [2] a2 ^ b2 = x
            [3] a1 ^ x = b1
            [4] b1 ^ x = a1
            [5] a1 ^ b1 = a2 ^ b2
            [6] a1 ^ (a2 ^ b2) = b1 "[2], [3]"
            [7] b1 ^ (a2 ^ b2) = a1 "[2], [4]"
            For now, I know the error is on the right....
            
            edge-case: What if error in both side?
                        - We know that key stores information about all variables.
                        - All variables and their correct complements encode the key.
                        - Things are tied together, look for a way to find a1 and b1 given
                           a1' and b1' such that a1' is a1 with error and b1' is b1 with error.
                        - QUESTION: Say -> a1' ^ b1' = x'; does x' encode information about
                                    the error in a1' and b1'? What is x ^ x'?
            """
            a1, b1 = tup_list[i]
            a2, b2 = None, None
            if i > 0:
                a2, b2 = tup_list[i-1]
            elif len(tup_list) > 1:
                for j in range(len(tup_list)-1):
                    if j == i:
                        continue
                    elif key ^ tup_list[j][0] == tup_list[j][1]:
                        a2, b2 = tup_list[j]
                        break
                else:
                    raise Exception()
                
            tup_list[i] = ( a1, a1 ^ (a2 ^ b2) ) # [6] (a1, b1) = (a1 , a1 ^ (a2, b2))
        Prog.append(fixLeft(tup_list[i][0]) + tup_list[i][1])
    return Prog

Prog = healCode(unZip(Prog), KEY)
print "Healed code"
dispCode(Prog)
print "Original code"
dispCode(backUp)
print "Healed code == Original code :", Prog == backUp


Healed code
('00111000111101111100000100100100', ('0011100011110111', '1100000100100100'))
('01101101110101111001010000000100', ('0110110111010111', '1001010000000100'))
('11000010001001110011101111110100', ('1100001000100111', '0011101111110100'))
('01100010101001111001101101110100', ('0110001010100111', '1001101101110100'))
('11011100010000010010010110010010', ('1101110001000001', '0010010110010010'))
('00111001010001111100000010010100', ('0011100101000111', '1100000010010100'))
('10111001111100110100000000100000', ('1011100111110011', '0100000000100000'))
('11000111010101000011111010000111', ('1100011101010100', '0011111010000111'))


Original code
('00111000111101111100000100100100', ('0011100011110111', '1100000100100100'))
('01101101110101111001010000000100', ('0110110111010111', '1001010000000100'))
('11000010001001110011101111110100', ('1100001000100111', '0011101111110100'))
('01100010101001111001101101110100', ('0110001010100111', '1001101101110100'))
('11011100010000010010010110010010', ('1101110001000001', '0010010110010010'))
('00111001010001111100000010010100', ('0011100101000111', '1100000010010100'))
('10111001111100110100000000100000', ('1011100111110011', '0100000000100000'))
('11000111010101000011111010000111', ('1100011101010100', '0011111010000111'))


Healed code == Original code : True

In [ ]: