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)])