Reputation: 405
Just as a project out of fun, I wanted to build a simple binary encoder with Python. After that worked very well, I moved on to upgrade it as an encoder and a decoder... and suddenly, it doesn't seem to work (only the second option, the first option still works fine).
The error I get when I want to decode for example '0100 0001'
, which stands for "A"
, is as follows:
Your message to decode: 0100 0010
KeyError Traceback (most recent call last)
C:\Users\marco\AppData\Local\Enthought\Canopy32\App\appdata\canopy-1.4.0.1938.win-x86\lib\site-packages\IPython\utils\py3compat.pyc in execfile(fname, glob, loc)
195 else:
196 filename = fname
--> 197 exec compile(scripttext, filename, 'exec') in glob, loc
198 else:
199 def execfile(fname, *where):
C:\Users\marco\Dropbox\1_TUDelft\4Q\AE1205 Python\my own codes\binary encoder.py in <module>()
41 messageDecode = raw_input("Your message to decode: ")
42 for character in messageDecode:
---> 43 print inverseBINARY[character],
KeyError: '0'
My suspicion is that it is the last command, the print
command, however I do not know how to correct it... Any suggestions?
Here is the code:
BINARY = {"A":"0100 0001",
"B":"0100 0010",
"C":"0100 0011",
"D":"0100 0100",
"E":"0100 0101",
"F":"0100 0110",
"G":"0100 0111",
"H":"0100 1000",
"I":"0100 1001",
"J":"0100 1010",
"K":"0100 1011",
"L":"0100 1100",
"M":"0100 1101",
"N":"0100 1110",
"O":"0100 1111",
"P":"0101 0000",
"Q":"0101 0001",
"R":"0101 0010",
"S":"0101 0011",
"T":"0101 0100",
"U":"0101 0101",
"V":"0101 0110",
"W":"0101 0111",
"X":"0101 1000",
"Y":"0101 1001",
"Z":"0101 1010",
" ":"0100 0000",
".":"0010 1110",
",":"0010 1100",
"?":"0011 1111"}
inverseBINARY = {v:k for k,v in BINARY.items()}
question = input("Do you wish to encode(press 1) or decode(press 2) into/from binary?")
if question == 1:
messageEncode = raw_input("Your message to encode: ")
for character in messageEncode:
print BINARY[character.upper()],
if question == 2:
messageDecode = raw_input("Your message to decode: ")
for character in messageDecode:
print inverseBINARY[character],
Upvotes: 1
Views: 9360
Reputation: 122142
To convert ascii to binary:
>>> format(ord('A'), 'b')
'1000001'
To convert binary to ascii:
>>> chr(int('1000001',2))
'A'
Here's a more compact version of your code:
question = raw_input("Your message to encode/decode: ")
try:
question = int(question, 2) # Checks if inptu is binary.
print 'Decoding...'
print chr(question)
except:
print 'Encoding...'
print "".join([format(ord(i), 'b') for i in question])
[test]:
alvas@ubi:~$ python test.py
Your message to encode/decode: 1000001
Decoding...
A
alvas@ubi:~$ python test.py
Your message to encode/decode: A
Encoding...
1000001
Upvotes: -1
Reputation: 1123250
You are looping over the individual characters of the input message, but you need to instead look for groups of 9 characters (2 times 4 binary digits and the space). Your mapping has keys like '0100 1001'
, not '0'
and '1'
and ' '
The simplest approach (albeit a bit brittle) would be to loop over indices in steps of 10 characters (1 extra for the space between the characters), then grab 9 characters:
for i in xrange(0, len(messageDecode), 10):
group = messageDecode[i:i + 9]
print inverseBINARY[group],
The xrange()
object produces integers 10 apart; so 0
, 10
, 20
, etc. The messageDecode
string is then sliced to grab 9 characters starting at that index, so messageDecode[0:9]
and messageDecode[10:19]
, messageDecode[20:29]
, etc.
A more robust approach would be to remove all spaces and grab blocks every 8 characters; that'd leave room for extra spaces in between, but you do have to re-insert that space to match your keys:
messageDecode = messageDecode.replace(' ', '')
for i in xrange(0, len(messageDecode), 8):
group = messageDecode[i:i + 4] + ' ' + messageDecode[i + 4:i + 8]
print inverseBINARY[group],
or you could perhaps not include the spaces in your inverseBINARY
mapping here:
inverseBINARY = {v.replace(' ', ''): k for k, v in BINARY.items()}
and then simply slice every 8 characters:
messageDecode = messageDecode.replace(' ', '')
for i in xrange(0, len(messageDecode), 8):
group = messageDecode[i:i + 8]
print inverseBINARY[group],
Upvotes: 3
Reputation: 9333
if you want to decode binary why not use native functions as the binary number and chr
?
>>> print chr(0b01000010)
B
EDIT
Ok then, this is how i would solve that:
from string import letters, punctuation
encode_data = {letter:bin(ord(letter)) for letter in letters+punctuation+' '}
decode_data = {bin(ord(letter)):letter for letter in letters+punctuation+' '}
def encode(message):
return [encode_data[letter] for letter in message]
def decode(table):
return [decode_data[item] for item in table]
encoded = encode('hello there')
print decode(encoded) # ['h', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'e', 'r', 'e']
Upvotes: -1