def _allSame(xs):
"""allSame([x]) -> x0 == x1 == .. == xn"""
#""" ## for short xs:
xs = tuple(xs)
return not xs or xs.count(xs[0]) == len(xs)
#"""
""" ## for looong xs:
xs = iter(xs)
try:
p = next(xs)
except StopIteration:
return True
return all(p == x for x in xs)
"""
def equivalent(*iterables, keyfunc=lambda x:x):
return all(map(_allSame, zip(*map(keyfunc, iterables))))
###########################
from functools import partial
isVowel = set('AЕЁИОУЫЭЮЯаеёиоуыэюя').__contains__
print('equivalent "ололо", "ороро" ->',
equivalent("ололо", "ороро", keyfunc=partial(map, isVowel))
# >>> True
)
print('equivalent "ололо", "ороро", "битард" ->',
equivalent("ололо", "ороро", "битард", keyfunc=partial(map, isVowel))
# >>> False
)
from itertools import groupby
def deltaCV(cs):
for c, _ in groupby(map(isVowel, cs)):
yield c
print('equivalent "ололо", "ороро", "ооооллоло" ->',
equivalent("ололо", "ороро", "ооооллоло", keyfunc=deltaCV)
# >>> True
)
print('equivalent "ололо", "ороро", "трооооллоло" ->',
equivalent("ололо", "ороро", "трооооллоло", keyfunc=deltaCV)
# >>> False
)
ZGVmIF9hbGxTYW1lKHhzKToKCSIiImFsbFNhbWUoW3hdKSAtPiB4MCA9PSB4MSA9PSAuLiA9PSB4biIiIgoJCgkjIiIiICAgICMjIGZvciBzaG9ydCB4czoKCXhzID0gdHVwbGUoeHMpCglyZXR1cm4gbm90IHhzIG9yIHhzLmNvdW50KHhzWzBdKSA9PSBsZW4oeHMpCgkjIiIiCgkiIiIgICAgIyMgZm9yIGxvb29uZyB4czoKCXhzID0gaXRlcih4cykKCQoJdHJ5OgoJCXAgPSBuZXh0KHhzKQoJCglleGNlcHQgU3RvcEl0ZXJhdGlvbjoKCQlyZXR1cm4gVHJ1ZQoJCglyZXR1cm4gYWxsKHAgPT0geCBmb3IgeCBpbiB4cykKCSIiIgoKZGVmIGVxdWl2YWxlbnQoKml0ZXJhYmxlcywga2V5ZnVuYz1sYW1iZGEgeDp4KToKCXJldHVybiBhbGwobWFwKF9hbGxTYW1lLCB6aXAoKm1hcChrZXlmdW5jLCBpdGVyYWJsZXMpKSkpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCmZyb20gZnVuY3Rvb2xzIGltcG9ydCBwYXJ0aWFsCgppc1Zvd2VsID0gc2V0KCdB0JXQgdCY0J7Qo9Cr0K3QrtCv0LDQtdGR0LjQvtGD0YvRjdGO0Y8nKS5fX2NvbnRhaW5zX18KCnByaW50KCdlcXVpdmFsZW50ICLQvtC70L7Qu9C+IiwgItC+0YDQvtGA0L4iIC0+JywKCWVxdWl2YWxlbnQoItC+0LvQvtC70L4iLCAi0L7RgNC+0YDQviIsIGtleWZ1bmM9cGFydGlhbChtYXAsIGlzVm93ZWwpKQoJIyA+Pj4gVHJ1ZQopCnByaW50KCdlcXVpdmFsZW50ICLQvtC70L7Qu9C+IiwgItC+0YDQvtGA0L4iLCAi0LHQuNGC0LDRgNC0IiAtPicsCgllcXVpdmFsZW50KCLQvtC70L7Qu9C+IiwgItC+0YDQvtGA0L4iLCAi0LHQuNGC0LDRgNC0Iiwga2V5ZnVuYz1wYXJ0aWFsKG1hcCwgaXNWb3dlbCkpCgkjID4+PiBGYWxzZQopCgpmcm9tIGl0ZXJ0b29scyBpbXBvcnQgZ3JvdXBieQoKZGVmIGRlbHRhQ1YoY3MpOgoJZm9yIGMsIF8gaW4gZ3JvdXBieShtYXAoaXNWb3dlbCwgY3MpKToKCQl5aWVsZCBjCgpwcmludCgnZXF1aXZhbGVudCAi0L7Qu9C+0LvQviIsICLQvtGA0L7RgNC+IiwgItC+0L7QvtC+0LvQu9C+0LvQviIgLT4nLAoJZXF1aXZhbGVudCgi0L7Qu9C+0LvQviIsICLQvtGA0L7RgNC+IiwgItC+0L7QvtC+0LvQu9C+0LvQviIsIGtleWZ1bmM9ZGVsdGFDVikKCSMgPj4+IFRydWUKKQpwcmludCgnZXF1aXZhbGVudCAi0L7Qu9C+0LvQviIsICLQvtGA0L7RgNC+IiwgItGC0YDQvtC+0L7QvtC70LvQvtC70L4iIC0+JywKCWVxdWl2YWxlbnQoItC+0LvQvtC70L4iLCAi0L7RgNC+0YDQviIsICLRgtGA0L7QvtC+0L7Qu9C70L7Qu9C+Iiwga2V5ZnVuYz1kZWx0YUNWKQoJIyA+Pj4gRmFsc2UKKQ==