# your code goes here
import time
from functools import wraps
from threading import Thread
import random
import string
def time_it(f):
"""
run the function 100,000 times and print time
"""
@wraps(f)
def wrapper(*args, **kwargs):
start_time = time.time()
for i in range(10000):
r = f(*args, **kwargs)
print(f.__name__, time.time() - start_time)
return r
return wrapper
@time_it
def find_max_alpha_sequence_optimal_way(source):
answer = [source[0],]
for l in source[1:]:
if l >= answer[-1][-1]:
answer[-1] += l
else:
answer.append(l)
return max(answer, key=lambda x: len(x))
@time_it
def find_max_alpha_sequence(source):
answer = [source[0],]
for l in source[1:]:
if l >= answer[-1][-1]:
answer[-1] += l
else:
answer.append(l)
return sorted(answer, key=lambda x: len(x))[-1]
@time_it
def max_alpha_sub(s):
def split_by_alpha_order(s):
start = 0
for i,(a,b) in enumerate(zip(s,s[1:])):
if a>b:
yield s[start:i+1]
start = i+1
yield s[start:]
return max(split_by_alpha_order(s),key=len)
@time_it
def max_alpha_sub_simple(s):
if not s:
return s
start = 0
max = (0,1)
for index in range(1,len(s)+1):
if index == len(s) or s[index-1]>s[index]:
if index - start>max[1]-max[0]:
max=(start,index)
start = index
functions = (
find_max_alpha_sequence,
find_max_alpha_sequence_optimal_way,
max_alpha_sub,
max_alpha_sub_simple
)
str = ''.join(random.choice(string.ascii_letters) for _ in range(100))
for f in functions:
t = Thread(target=f, args=(str,))
t.start()
IyB5b3VyIGNvZGUgZ29lcyBoZXJlCmltcG9ydCB0aW1lCiAKZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHdyYXBzCmZyb20gdGhyZWFkaW5nIGltcG9ydCBUaHJlYWQKCmltcG9ydCByYW5kb20KaW1wb3J0IHN0cmluZwogCmRlZiB0aW1lX2l0KGYpOgogICAgIiIiCiAgICBydW4gdGhlIGZ1bmN0aW9uIDEwMCwwMDAgdGltZXMgYW5kIHByaW50IHRpbWUKICAgICIiIgogICAgQHdyYXBzKGYpCiAgICBkZWYgd3JhcHBlcigqYXJncywgKiprd2FyZ3MpOgogICAgICAgIHN0YXJ0X3RpbWUgPSB0aW1lLnRpbWUoKQogICAgICAgIGZvciBpIGluIHJhbmdlKDEwMDAwKTogCiAgICAgICAgICAgIHIgPSBmKCphcmdzLCAqKmt3YXJncykKICAgICAgICBwcmludChmLl9fbmFtZV9fLCB0aW1lLnRpbWUoKSAtIHN0YXJ0X3RpbWUpCiAgICAgICAgcmV0dXJuIHIKICAgIHJldHVybiB3cmFwcGVyCiAgICAKICAgIApAdGltZV9pdApkZWYgZmluZF9tYXhfYWxwaGFfc2VxdWVuY2Vfb3B0aW1hbF93YXkoc291cmNlKToKICAgIGFuc3dlciA9IFtzb3VyY2VbMF0sXQogICAgZm9yIGwgaW4gc291cmNlWzE6XToKICAgICAgICBpZiBsID49IGFuc3dlclstMV1bLTFdOgogICAgICAgICAgICBhbnN3ZXJbLTFdICs9IGwKICAgICAgICBlbHNlOgogICAgICAgICAgICBhbnN3ZXIuYXBwZW5kKGwpCiAgICByZXR1cm4gbWF4KGFuc3dlciwga2V5PWxhbWJkYSB4OiBsZW4oeCkpIAogCkB0aW1lX2l0CmRlZiBmaW5kX21heF9hbHBoYV9zZXF1ZW5jZShzb3VyY2UpOgogICAgYW5zd2VyID0gW3NvdXJjZVswXSxdCiAgICBmb3IgbCBpbiBzb3VyY2VbMTpdOgogICAgICAgIGlmIGwgPj0gYW5zd2VyWy0xXVstMV06CiAgICAgICAgICAgIGFuc3dlclstMV0gKz0gbAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGFuc3dlci5hcHBlbmQobCkKICAgIHJldHVybiBzb3J0ZWQoYW5zd2VyLCBrZXk9bGFtYmRhIHg6IGxlbih4KSlbLTFdCiAKQHRpbWVfaXQKZGVmIG1heF9hbHBoYV9zdWIocyk6CiAgICBkZWYgc3BsaXRfYnlfYWxwaGFfb3JkZXIocyk6CiAgICAgICAgc3RhcnQgPSAwCiAgICAgICAgZm9yIGksKGEsYikgaW4gZW51bWVyYXRlKHppcChzLHNbMTpdKSk6CiAgICAgICAgICAgIGlmIGE+YjoKICAgICAgICAgICAgICAgIHlpZWxkIHNbc3RhcnQ6aSsxXQogICAgICAgICAgICAgICAgc3RhcnQgPSBpKzEKICAgICAgICB5aWVsZCBzW3N0YXJ0Ol0KICAgIHJldHVybiBtYXgoc3BsaXRfYnlfYWxwaGFfb3JkZXIocyksa2V5PWxlbikKIApAdGltZV9pdApkZWYgbWF4X2FscGhhX3N1Yl9zaW1wbGUocyk6CiAgICBpZiBub3QgczoKICAgICAgICByZXR1cm4gcwogICAgCiAgICBzdGFydCA9IDAKICAgIG1heCA9ICgwLDEpCiAgICBmb3IgaW5kZXggaW4gcmFuZ2UoMSxsZW4ocykrMSk6CiAgICAgICAgaWYgaW5kZXggPT0gbGVuKHMpIG9yIHNbaW5kZXgtMV0+c1tpbmRleF06CiAgICAgICAgICAgIGlmIGluZGV4IC0gc3RhcnQ+bWF4WzFdLW1heFswXToKICAgICAgICAgICAgICAgIG1heD0oc3RhcnQsaW5kZXgpCiAgICAgICAgICAgIHN0YXJ0ID0gaW5kZXgKIApmdW5jdGlvbnMgPSAoCiAgICBmaW5kX21heF9hbHBoYV9zZXF1ZW5jZSwKICAgIGZpbmRfbWF4X2FscGhhX3NlcXVlbmNlX29wdGltYWxfd2F5LAogICAgbWF4X2FscGhhX3N1YiwKICAgIG1heF9hbHBoYV9zdWJfc2ltcGxlCiAgICApCiAKc3RyID0gJycuam9pbihyYW5kb20uY2hvaWNlKHN0cmluZy5hc2NpaV9sZXR0ZXJzKSBmb3IgXyBpbiByYW5nZSgxMDApKQogCmZvciBmIGluIGZ1bmN0aW9uczoKICAgIHQgPSBUaHJlYWQodGFyZ2V0PWYsIGFyZ3M9KHN0ciwpKQogICAgdC5zdGFydCgpCiAgICAK