2012-01-02 34 views
6

Mục tiêu: Chuyển đổi nhị phân để chuỗinhị phân thành chuỗi, tốt hơn từ điển?

Ví dụ: 0111010001100101011100110111010001100011011011110110010001100101 -> testCode (không gian)

tôi sử dụng một từ điển và chức năng của tôi, tôi tìm kiếm một cách tốt hơn và hiệu quả hơn

from textwrap import wrap 

DICO = {'\x00': '00', '\x04': '0100', '\x08': '01000', '\x0c': '01100', 
'\x10': '010000', '\x14': '010100', '\x18': '011000', '\x1c': '011100', 
' ': '0100000', '$': '0100100', '(': '0101000', ',': '0101100', '0': '0110000', 
'4': '0110100', '8': '0111000', '<': '0111100', '@': '01000000', 
'D': '01000100', 'H': '01001000', 'L': '01001100', 'P': '01010000', 
'T': '01010100', 'X': '01011000', '\\': '01011100', '`': '01100000', 
'd': '01100100', 'h': '01101000', 'l': '01101100', 'p': '01110000', 
't': '01110100', 'x': '01111000', '|': '01111100', '\x03': '011', 
'\x07': '0111', '\x0b': '01011', '\x0f': '01111', '\x13': '010011', 
'\x17': '010111', '\x1b': '011011', '\x1f': '011111', '#': '0100011', 
"'": '0100111', '+': '0101011', '/': '0101111', '3': '0110011', '7': '0110111', 
';': '0111011', '?': '0111111', 'C': '01000011', 'G': '01000111', 
'K': '01001011', 'O': '01001111', 'S': '01010011', 'W': '01010111', 
'[': '01011011', '_': '01011111', 'c': '01100011', 'g': '01100111', 
'k': '01101011', 'o': '01101111', 's': '01110011', 'w': '01110111', 
'{': '01111011', '\x7f': '01111111', '\x02': '010', '\x06': '0110', 
'\n': '01010', '\x0e': '01110', '\x12': '010010', '\x16': '010110', 
'\x1a': '011010', '\x1e': '011110', '"': '0100010', '&': '0100110', 
'*': '0101010', '.': '0101110', '2': '0110010', '6': '0110110', ':': '0111010', 
'>': '0111110', 'B': '01000010', 'F': '01000110', 'J': '01001010', 
'N': '01001110', 'R': '01010010', 'V': '01010110', 'Z': '01011010', 
'^': '01011110', 'b': '01100010', 'f': '01100110', 'j': '01101010', 
'n': '01101110', 'r': '01110010', 'v': '01110110', 'z': '01111010', 
'~': '01111110', '\x01': '01', '\x05': '0101', '\t': '01001', '\r': '01101', 
'\x11': '010001', '\x15': '010101', '\x19': '011001', '\x1d': '011101', 
'!': '0100001', '%': '0100101', ')': '0101001', '-': '0101101', 
'1': '0110001', '5': '0110101', '9': '0111001', '=': '0111101', 
'A': '01000001', 'E': '01000101', 'I': '01001001', 'M': '01001101', 
'Q': '01010001', 'U': '01010101', 'Y': '01011001', ']': '01011101', 
'a': '01100001', 'e': '01100101', 'i': '01101001', 'm': '01101101', 
'q': '01110001', 'u': '01110101', 'y': '01111001', '}': '01111101'} 

def decrypt(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     for i, j in DICO.items(): 
      if j == b: 
       ch += i 
    return ch 

cảm ơn trước,

+1

Chính xác bạn muốn cải thiện điều gì? Không gian hoặc thời gian phức tạp?Thuật toán nào bạn sử dụng hiện tại, bạn chỉ cần tách chuỗi? – RedX

+6

Làm thế nào để bạn quyết định nếu chuỗi '010001' là '0100' (=' \ x04') theo sau là bắt đầu của một chuỗi '01', hoặc là bắt đầu của một ký tự dấu băm,' 0100011'? Nếu tất cả các ký tự có cùng số lượng bit (có thể đoán trước là 7 hoặc 8 bit), thì tại sao mã không cho '\ x00' được viết là' 00000000' trong ví dụ của bạn, nhưng '00'? Các dữ liệu ví dụ để lại rất nhiều chỗ cho việc giải thích ... – hochl

+0

@Redx, cảm ơn phản hồi của bạn, tôi tìm kiếm thời gian thực hiện tốt hơn, tôi giữ mã của tôi – Fred

Trả lời

2

bạn đã thử

def decrypt(binary): 
    """Function to convert binary into string""" 
    return ''.join((chr(int(p, 2)) for p in grouper(8,binary,''))) 

nơi mú được lấy từ đây http://docs.python.org/library/itertools.html#recipes

hoặc

def decrypt2(binary): 
    """Function to convert binary into string""" 
    return ''.join((DICO_INVERTED[p] for p in grouper(8,binary,''))) 

mà tránh để tạo ra danh sách tạm thời

EDIT như tôi đã được choisen là câu trả lời "đúng" tôi phải thú nhận rằng tôi đã sử dụng các câu trả lời khác. Vấn đề là ở đây không sử dụng danh sách máy phát điện nhưng biểu thức máy phát và vòng lặp

+0

Rất tốt !!!! ngoại lệ, cảm ơn – Fred

+0

bạn đã kiểm tra cái nào bằng từ điển hoặc từ khác? –

+0

trung bình 14 giây, đề xuất của bạn cho 0,006 giây, siêu điểm, cảm ơn rất nhiều – Fred

14
''.join([ chr(int(p, 2)) for p in wrap(binstr, 8) ]) 

Điều này làm gì: wrap đầu tiên chia chuỗi của bạn thành các phần của 8. Sau đó, tôi lặp qua mỗi một, và chuyển đổi nó thành một số nguyên (cơ số 2). Mỗi số nguyên được chuyển đổi bây giờ được bao phủ một ký tự với chr. Cuối cùng tôi quấn nó lên với một số ''.join để đập vỡ tất cả cùng nhau.

Một cắn nhiều hơn một phân tích về mỗi bước của chr(int(p, 2)):

>>> int('01101010', 2) 
106 
>>> chr(106) 
'j' 

Để làm cho nó phù hợp với mô hình của bạn ở trên:

def decrypt(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     ch += chr(int(b, 2)) 
    return ch 

hoặc

def decrypt(binary): 
    """Function to convert binary into string""" 
    return ''.join([ chr(int(p, 2)) for p in wrap(binary, 8) ]) 

Đây là chắc chắn nhanh hơn vì nó chỉ là làm toán học tại chỗ, không lặp đi lặp lại thông qua từ điển hơn và hơn. Thêm vào đó, nó dễ đọc hơn.

+0

cho thời gian, nó tương đương! – Fred

+0

Chuỗi của bạn lớn đến mức nào? Nó có thể là 'bọc' đang chiếm đa số thời gian và không có gì nhiều bạn có thể làm về điều đó. Dù bằng cách nào, đây vẫn là cách dễ đọc hơn so với tính quái dị của một từ điển. –

+0

Tôi không biết để bọc nhưng từ điển cho chiều dài 5000 -> 1,94 giây và mã của bạn -> 3,45 giây – Fred

3

Nếu tốc độ thực thi là điều quan trọng nhất đối với bạn, tại sao không đảo ngược vai trò của khóa và giá trị trong dict của bạn ?! (Nếu bạn cũng cần dict hiện tại, bạn có thể tạo một phiên bản ngược như thế này {v:k for k, v in DICO.items()})

Bây giờ, bạn tìm trực tiếp bản dịch tìm kiếm bằng khóa thay vì lặp qua toàn bộ dict.

chức năng mới của bạn sẽ trông như thế này:

def decrypt2(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     if b in DICO_INVERTED: 
      ch += DICO_INVERTED[b] 
    return ch 

Tùy thuộc vào kích thước của chuỗi nhị phân của bạn, bạn có thể đạt được một số thời gian bằng cách thay đổi cách bạn xây dựng đầu ra dây của bạn (xem Efficient String Concatenation in Python hoặc performance tips - string concatenation). Sử dụng join có vẻ đầy hứa hẹn. Tôi sẽ cung cấp cho nó một thử: ''.join(DICO_INVERTED.get(b, '') for b in binary)

+1

Tôi cũng khuyên bạn nên tạo dict với mã thay vì gõ nó ra. –

+0

@orangeoctopus, tôi không gõ dict;) – Fred

+0

@ gecco, nó hiệu quả hơn, cảm ơn! – Fred

Các vấn đề liên quan