Skip to main content
slightly simplify the code
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32
#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#function to convert a word to its index(+1) in Lbase
num = lambda w: Lbase.index(w)+1

#base-64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change a bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b**i for i in range(len(L))])
    L = []
    while n > 0:
        nn = L.append(1+(n-1)//newb%newb)
        an = (n - nn*newb
        L.append(a1)
        n = nn//newb
    return L

#convert a bijective list-repr. to base-64 string-repr.
def list_to_str(Lin):
    L24 = [num[Lbase.index(w)+1 for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base-64 string to the corresponding base-64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#function to convert a word to its index(+1) in Lbase
num = lambda w: Lbase.index(w)+1

#base-64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change a bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b**i for i in range(len(L))])
    L = []
    while n > 0:
        nn = (n-1)//newb
        a = n - nn*newb
        L.append(a)
        n = nn
    return L

#convert a bijective list-repr. to base-64 string-repr.
def list_to_str(Lin):
    L24 = [num(w) for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base-64 string to the corresponding base-64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#base-64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change a bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b**i for i in range(len(L))])
    L = []
    while n > 0:
        L.append(1+(n-1)%newb)
        n = (n-1)//newb
    return L

#convert a bijective list-repr. to base-64 string-repr.
def list_to_str(Lin):
    L24 = [Lbase.index(w)+1 for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base-64 string to the corresponding base-64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
convert Sage to Python(2 & 3); comment on output length for various alphabet sizes
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32

SagePython (output-length: 18 or 19, mean 18.80)

#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#function to convert a word to its index(+1) in Lbase
num = lambda w: Lbase.index(w)+1

#base64#base-64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change thea bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b^i[L[i]*b**i for i in range(len(L))])
    L = []
    while n > 0:
        nn = ceil(n/newb) - 1)//newb
        a = n - nn*newb
        L.append(a)
        n = nn
    return L

#convert a bijective list-repr. to base64base-64 string-repr.
def list_to_str(Lin):
    L24 = [num(w) for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base64base-64 string to the corresponding base64base-64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
Lin = ["GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT"]

#convert input list to a base64base-64 string  
lts = list_to_str(Lin) 

#convert the base64base-64 str back to the list   
stl = str_to_list(lts)

print (len(lts))
print (lts)
print (stl == Lin)

This uses bijective numeration (which has no 0 digit) to get invertibility. I don't know whether some run-length encoding might help reduce the output string length.

NBNB: When using a 64base-character alphabet64 with this method, all output strings for the above problem are either 18 or 19 characters. A(A million random inputs gave an average of 18.80.) The same method works with larger alphabets; e.g., with size 72, a million random inputs all had output strings of length 18, and with size 90 they all had length 17.other bases:

base         output-length
---------    -------------
56 - 58      19
59 - 69      18 or 19
70 - 73      18
74 - 88      17 or 18
89 - 96      17
...          ...
233 - 256    14

Sage (output-length: 18 or 19, mean 18.80)

#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#function to convert a word to its index(+1) in Lbase
num = lambda w: Lbase.index(w)+1

#base64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change the bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b^i for i in range(len(L))])
    L = []
    while n > 0:
        nn = ceil(n/newb) - 1
        a = n - nn*newb
        L.append(a)
        n = nn
    return L

#convert a bijective list-repr. to base64 string-repr.
def list_to_str(Lin):
    L24 = [num(w) for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base64 string to the corresponding base64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
Lin = ["GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT"]

#convert input list to a base64 string  
lts = list_to_str(Lin) 

#convert the base64 str back to the list   
stl = str_to_list(lts)

print len(lts)
print lts
print stl == Lin

This uses bijective numeration (which has no 0 digit) to get invertibility. I don't know whether some run-length encoding might help reduce the output string length.

NB: When using a 64-character alphabet with this method, all output strings for the above problem are either 18 or 19 characters. A million random inputs gave an average of 18.80. The same method works with larger alphabets; e.g., with size 72, a million random inputs all had output strings of length 18, and with size 90 they all had length 17.

Python (output-length: 18 or 19, mean 18.80)

#list of the 24 possible words 
Lbase = ['GTAC','GTCA','GATC','GACT','GCTA','GCAT','TGAC',\
'TGCA','TAGC','TACG','TCGA','TCAG','AGTC','AGCT','ATGC',\
'ATCG','ACGT','ACTG','CGTA','CGAT','CTGA','CTAG','CAGT','CATG']

#function to convert a word to its index(+1) in Lbase
num = lambda w: Lbase.index(w)+1

#base-64 alphabet (used only in the output string-representation) 
alph = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

#change a bijective list-representation base from b to newb 
def chg_bij_base(L, b, newb):
    n = sum([L[i]*b**i for i in range(len(L))])
    L = []
    while n > 0:
        nn = (n-1)//newb
        a = n - nn*newb
        L.append(a)
        n = nn
    return L

#convert a bijective list-repr. to base-64 string-repr.
def list_to_str(Lin):
    L24 = [num(w) for w in Lin]
    L64 = chg_bij_base(L24,24,64) 
    return ''.join([alph[i-1] for i in L64])
    
#convert a base-64 string to the corresponding base-64 list-repr.
def str_to_list(s):
    L64 = [alph.index(c)+1 for c in s]
    L24 = chg_bij_base(L64,64,24)
    return [Lbase[i-1] for i in L24]
Lin = ["GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT", "GTAC", "CATG", "TACG", "GACT"]

#convert input list to a base-64 string  
lts = list_to_str(Lin) 

#convert the base-64 str back to the list   
stl = str_to_list(lts)

print(len(lts))
print(lts)
print(stl == Lin)

This uses bijective numeration (which has no 0 digit) to get invertibility.

NB: When using base-64 with this method, all output strings for the above problem are either 18 or 19 characters. (A million random inputs gave an average of 18.80.) The same method works with other bases:

base         output-length
---------    -------------
56 - 58      19
59 - 69      18 or 19
70 - 73      18
74 - 88      17 or 18
89 - 96      17
...          ...
233 - 256    14
include results for 72-character alphabet
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32

NB: When using a 64-character alphabet with this method, all output strings for the above problem are either 18 or 19 characters. A million random inputs gave an average of 18.80. The same method works with larger alphabets; e.g., with size 9072, a million random inputs allall had output strings of length 18, and with size 90 they all had length 17.

NB: When using a 64-character alphabet with this method, all output strings for the above problem are either 18 or 19 characters. A million random inputs gave an average of 18.80. The same method works with larger alphabets; e.g., with size 90, a million random inputs all had output strings of length 17.

NB: When using a 64-character alphabet with this method, all output strings for the above problem are either 18 or 19 characters. A million random inputs gave an average of 18.80. The same method works with larger alphabets; e.g., with size 72, a million random inputs all had output strings of length 18, and with size 90 they all had length 17.

add comment re output-lengths
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32
Loading
fix typo
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32
Loading
Source Link
r.e.s.
  • 3.1k
  • 22
  • 32
Loading