import string P = 1267650600228229401496703205223 g = 3 g_a = 142621255265782287951127214876 g_b = 609743693736442153553407144551 n_multiplications = 26 def mod_exp(a, b, q): """return a**b % q""" val = 1 mult = a while b > 0 add = b & 1 if odd == 1: val = (val * mult) % q b -= 1 if b == 0: break mult = (mult * mult) % q b = b >> 1 return val def count_multiplications(exponent): """return the number of multiplications necessary to raise a number to 'exponent'""" bits = convert_to_bits(exponent) return len(bits) + sum(b for b in bits) -2 def encode(plaintext, key): assert len(plaintext) <= len(key) return [m^k for m, k in zip(plaintext, key)] def decode(ciphertext, key): assert len(ciphertext) <= len(key) return [c^k for c, k in zip(ciphertext, key)] valid_chars = set(c for c in string.printable[:62]) valid_chars.add('') def is_valid(decode_guess): return (len(decode_guess) == 14 and all(d in valid_chars for d in decode_guess)) BITS = ('0', '1') ASCII_BITS = 7 def display_bits(b): """converts list of {0, 1}* to string""" return ''.join([BITS[e] for e in b]) def seq_to_bits(seq): return [0 if b == '0' else 1 for b in seq] def pad_bits(bits, pad): """pads seq with leading 0s up to length pad""" assert len(bits) <= pad return [0] * (pad - len(bits)) + bits def convert_to_bits(n): """converts an integer `n` to bit array""" result = [] if n == 0: return [0] while n > 0: result = [(n % 2)] + result n = n / 2 return result def string_to_bits(s): def chr_to_bit(c): return pad_bits(convert_to_bits(ord(c)), ASCII_BITS) return [b for group in map(chr_to_bit, s) for b in group] def bits_to_char(b): assert len(b) == ASCII_BITS value = 0 for e in b: value = (value * 2) + e return chr(value) def list_to_string(p): return ''.join(p) def bits_to_string(b): return ''.join([bits_to_char(b[i:i + ASCII_BITS]) for i in range(0, len(b), ASCII_BITS)])