Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Shifty solution in Clear category for Bit Message by PositronicLlama
#!/usr/bin/python
"""Parse an SMS-like message."""
import base64
import codecs
import datetime
def decode_time(byte):
"""Swap nibbles in the given byte, and return hex interpreted as decimal."""
return ((byte & 0x0F) * 10) + (byte >> 4)
def _unpack7(data):
"""Yield 7-bit records from a stream of data."""
offset = 0
prev = 0
for byte in data:
yield chr((prev >> (8 - offset)) | ((byte & (0x7F >> offset)) << offset))
# Handle the 'extra' character
if offset == 6:
yield chr((byte & 0xFE) >> 1)
prev = byte
offset = (offset + 1) % 7
def decode_7(data):
"""Decode a 7-bit encoded packed message and return a (string, decoded_bytes) tuple."""
return (''.join(_unpack7(data)), len(data))
def decode_8(data):
"""Decode an 8-bit encoded message and return a (string, decoded_bytes) tuple."""
return (''.join(chr(byte) for byte in data), len(data))
# CheckiO does not allow access to 'codecs.decoder', so the following uses
# 'codecs.lookup' instead.
DECODERS = {0: decode_7,
1: decode_8,
2: codecs.lookup('utf-16-be').decode}
def checkio(data):
"""Return a formatted record from the given hex encoded string."""
b = base64.b16decode(data.strip().upper())
type_, time_data, tz, msg_len, msg_data = b[0], b[1:7], b[7], b[8], b[9:]
# Swizzle the time records into the correct format.
# The format is undocumented except in comments and test cases.
# It's a hexadecimal interpreted as decimal, but with swapped nibbles.
time_data = [decode_time(byte) for byte in time_data]
year, month, day, hour, minute, second = time_data
# Handle year (undocumented range is 1970 - 2069)
if year < 70:
year += 100
year += 1900
# Handle timezone
neg, tz = tz & 0x08, ((tz & 0x07) * 10) + (tz >> 4)
tz = tz // 4
if neg:
tz = -tz
# Format the date and time. Handle timezone separately since we don't
# want to implement a tzinfo class.
dt = datetime.datetime(year, month, day, hour, minute, second)
dt_str = dt.strftime('%d %b %Y %H:%M:%S')
dt_str += ' GMT {:+}'.format(tz)
# Extract bits 2-3 from the type record as the format
fmt = (type_ & 0x0C) >> 2
decoder = DECODERS[fmt]
msg, _ = decoder(msg_data)
return [dt_str, msg_len, msg[:msg_len]]
if __name__ == '__main__':
assert(checkio('002080629173148007EDF27C1E3E9701') ==
['26 Aug 2002 19:37:41 GMT +2', 7, 'message']), "First Test"
assert(checkio('00317050201171820FD3323BDC0ED341C4303DEC3E8700') ==
['05 Jul 2013 02:11:17 GMT +7', 15, 'Selamat Datang!']), "Second Test, 7 bit"
assert(checkio('000130925161956915C8729E054A82C26D50DA0D7296EFA0EC5BBE06') ==
['29 Mar 2010 15:16:59 GMT -4', 21, 'Hey, I am in New York']), "Third Test, negative timezone"
assert(checkio('08071010101010611F04180441043A043B044E04470435043D043804350020043F043E04340442043204350440043604340430043504420020043F0440043004320438043B043E') ==
['01 Jan 1970 01:01:01 GMT +4', 31, 'Исключение подтверждает правило']), "Fourth Test, simulate 32-bit signed integer real life problem"
assert(checkio('088310913041804C23805E4E0D82E5805E4E4B002C805E4E4B4E0D82E5898B4E4B002C898B4E4B4E0D82E577E54E4B002C77E54E4B4E0D82E5884C4E4B002C5B7881F365BC884C4E4B800C6B6277E3') ==
['19 Jan 2038 03:14:08 GMT -11', 35, '聞不若聞之,聞之不若見之,見之不若知之,知之不若行之,學至於行之而止矣']), "But, we pass Y2K38 problem"
Aug. 24, 2013