"""
Alternatywny algorytm przecięcia i testy (niezawarte w książce)

================================================================================

Wyniki (zobacz rozdział 21):

>>> min(timeit.repeat("from inter3 import intersect; intersect('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.005092659033834934
>>> min(timeit.repeat("from inter3 import intersect; intersect('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.005093390122056007
>>> min(timeit.repeat("from inter3 import intersect; intersect('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.005092829931527376

>>> min(timeit.repeat("from inter3 import intersectX; intersectX('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.0018285661935806274
>>> min(timeit.repeat("from inter3 import intersectX; intersectX('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.0018283897079527378
>>> min(timeit.repeat("from inter3 import intersectX; intersectX('HAKOWAĆ'*100, 'KOD'*100, 'KASA'*100)", number=100, repeat=100))
0.0018289494328200817

================================================================================

>>> from inter3 import intersect, intersectX
>>> s1, s2, s3 = 'HAKOWAĆ', 'KOD', 'KASA'
>>> 
>>> def tester(func, items, *, trace=True):
...        for i in range(len(items)):
...            items = items[1:] + items[:1]
...            if trace: print(items)
...            print(sorted(func(*items)))
... 
>>> tester(intersect, (s1, s2, s3))
('KOD', 'KASA', 'HAKOWAĆ')
['K']
('KASA', 'HAKOWAĆ', 'KOD')
['K']
('HAKOWAĆ', 'KOD', 'KASA')
['K']
>>> tester(intersectX, (s1, s2, s3))
('KOD', 'KASA', 'HAKOWAĆ')
['K']
('KASA', 'HACKK', 'KOD')
['K']
('HAKOWAĆ', 'KOD', 'KASA')
['K']
================================================================================
"""

def intersectX(*args):
    res = []
    for x in args[0]:     
        if x not in res:
            res.append(x) 
    for other in args[1:]:
        for x in res.copy():
            if x not in other:
                res.remove(x) 
    return res


def intersect(*args):
    res = []
    for x in args[0]:                    # Przejście przez pierwszą sekwencję
        if x in res: continue            # Pominięcie duplikatów w [0]
        for other in args[1:]:           # Dla pozostałych argumentów args
            if x not in other: break     # Czy w other jest element x?
        else:                            # Nie - wyjdź z pętli
            res.append(x)                # Tak - dodaj elementy na koniec
    return res


def union(*args):
    res = []
    for seq in args:                     # Dla wszystkich argumentów
        for x in seq:                    # Dla wszytskich elementów z tego argumentu
            if not x in res:
                res.append(x)            # Dodanie nowych elementów do wyniku
    return res

