"""Тема урока: методы множеств
Методы union(), intersection(), difference(), symmetric_difference()
Методы update(), intersection_update(), difference_update(), symmetric_difference_update()
Операторы &, |, -, ^
Аннотация. Урок посвящен методам множеств, которые реализуют основные операции над множествами.

Операции над множествами
Основные операции над множествами:

объединение множеств;
пересечение множеств;
разность множеств;
симметрическая разность множеств.
Для каждой операции есть метод и оператор.

Объединение множеств: метод union()
Объединение множеств это множество, состоящее из элементов, принадлежащих хотя бы одному из объединяемых множеств.
Для этой операции существует метод union().

​

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1.union(myset2)
print(myset3)
выводит (порядок элементов может отличаться):

{1, 2, 3, 4, 5, 6, 7, 8}
​Обратите внимание, метод union() возвращает новое множество в которое входят все элементы множеств myset1 и myset2.
 Для изменения текущего множества используется метод update().

Для объединения двух множеств можно также использовать оператор |.

Результат выполнения приведенного ниже кода:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1 | myset2
print(myset3)
аналогичен предыдущему.

Пересечение множеств: метод intersection()
Пересечение множеств это множество, состоящее из элементов, принадлежащих одновременно каждому из пересекающихся
 множеств. Для этой операции существует метод intersection().

​

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1.intersection(myset2)
print(myset3)
выводит (порядок элементов может отличаться):

{3, 4}
​Обратите внимание, метод intersection() возвращает новое множество в которое входят общие элементы множеств
myset1 и myset2. Для изменения текущего множество используется метод intersection_update().

Для пересечения двух множеств можно также использовать оператор &.

Результат выполнения приведенного ниже кода:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1 & myset2
print(myset3)
аналогичен предыдущему.

Разность множеств: метод difference()
Разность множеств это множество, в которое входят все элементы первого множества, не входящие во второе множество.
 Для этой операции существует метод difference().

​

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1.difference(myset2)
print(myset3)
выводит (порядок элементов может отличаться):

{1, 2, 5}
Для разности двух множеств можно также использовать оператор -.

Результат выполнения приведенного ниже кода:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1 - myset2
print(myset3)
аналогичен предыдущему.

Обратите внимание: для операции разности множеств важен порядок, в котором указаны множества. Если поменять местами
 myset1 и myset2, нас ожидает совсем другой результат: элементы входящие в множество myset2 и которых нет в множестве
  myset1.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset2.difference(myset1)
print(myset3)
выводит (порядок элементов может отличаться):

{8, 6, 7}
Симметрическая разность: метод symmetric_difference()
Симметрическая разность множеств это множество, включающее все элементы исходных множеств, не принадлежащие
одновременно обоим исходным множествам. Для этой операции существует метод symmetric_difference().

​

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1.symmetric_difference(myset2)
print(myset3)
выводит (порядок элементов может отличаться):

{1, 2, 5, 6, 7, 8}
Для симметрической разности двух множеств можно также использовать оператор ^.

Результат выполнения приведенного ниже кода:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset3 = myset1 ^ myset2
print(myset3)
аналогичен предыдущему.

​Обратите внимание: для операции симметрической разности порядок множеств не важен, на то она и симметрическая:
 myset1 ^ myset2 == myset2 ^ myset1.

Методы множеств, изменяющие текущие множества
Методы union(), intersection(), difference(), symmetric_difference() не изменяют исходные множества, а возвращают
новые. Часто на практике нужно изменять исходные множества. Для таких целей используются парные методы update(),
intersection_update(), difference_update(), symmetric_difference_update().

Метод update()
Метод update() изменяет исходное множество по объединению.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1.update(myset2)      # изменяем множество myset1
print(myset1)
выводит (порядок элементов может отличаться):

{1, 2, 3, 4, 5, 6, 7, 8}
Аналогичный результат получается, если использовать оператор |=:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1 |= myset2
print(myset1)
Метод intersection_update()
Метод intersection_update() изменяет исходное множество по пересечению.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1.intersection_update(myset2)      # изменяем множество myset1
print(myset1)
выводит (порядок элементов может отличаться):

{3, 4}
Аналогичный результат получается, если использовать оператор &=:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1 &= myset2
print(myset1)
Метод difference_update()
Метод difference_update() изменяет исходное множество по разности.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1.difference_update(myset2)      # изменяем множество myset1
print(myset1)
выводит (порядок элементов может отличаться):

{1, 2, 5}
Аналогичный результат получается, если использовать оператор -=:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1 -= myset2
print(myset1)
Метод symmetric_difference_update()
Метод symmetric_difference_update() изменяет исходное множество по симметрической разности.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1.symmetric_difference_update(myset2)      # изменяем множество myset1
print(myset1)
выводит (порядок элементов может отличаться):

{1, 2, 5, 6, 7, 8}
Аналогичный результат получается, если использовать оператор ^=:

myset1 = {1, 2, 3, 4, 5}
myset2 = {3, 4, 6, 7, 8}

myset1 ^= myset2
print(myset1)
Примечания
Примечание 1. Все основные операции над множествами выполнятся двумя способами: при помощи метода или соответствующего
ему оператора. Различие в том, что метод может принимать в качестве аргумента не только множество (тип данных set),
 но и любой итерируемый объект (список, строку, кортеж).

Приведенный ниже код:

mylist = [2021, 2020, 2019, 2018, 2017, 2016]
mytuple = (2021, 2020, 2016)
mystr = 'abcd'

myset = {2009, 2010, 2016}

print(myset.union(mystr))              # объединяем со строкой
print(myset.intersection(mylist))      # пересекаем со списком
print(myset.difference(mytuple))       # находим разность с кортежем
выводит (порядок элементов может отличаться):

{2016, 'c', 'b', 'a', 'd', 2009, 2010}
{2016}
{2009, 2010}
Приведенный ниже код:

mylist = [2021, 2020, 2019, 2018, 2017, 2016]
mytuple = (2021, 2020, 2016)
mystr = 'abcd'

myset = {2009, 2010, 2016}

print(myset | mystr)
print(myset & mylist)
print(myset - mytuple)
приводит к возникновению ошибок:

TypeError: unsupported operand type(s) for |: 'set' and 'str'
TypeError: unsupported operand type(s) for &: 'set' and 'list'
TypeError: unsupported operand type(s) for -: 'set' and 'tuple'
Примечание 2. Некоторые методы (union(), intersection(), difference()) и операторы (|, &, -, ^) позволяют совершать
операции над несколькими множествами сразу.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5, 6}
myset2 = {2, 3, 4, 5}
myset3 = {5, 6, 7, 8}

union1 = myset1.union(myset2, myset3)
union2 = myset1 | myset2 | myset3

difference1 = myset1.difference(myset2, myset3)
difference2 = myset1 - myset2 - myset3            # порядок выполнения слева-направо

print(union1 == union2)
print(difference1 == difference2)
выводит:

True
True
Примечание 3. Оператор ^ симметрической разности позволяет использовать несколько множеств, а метод
symmetric_difference() – нет.

Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5, 6}
myset2 = {2, 3, 4, 7}
myset3 = {6, 20, 30}

symdifference = myset1 ^ myset2 ^ myset3  # порядок выполнения слева-направо

print(symdifference)
выводит (порядок элементов может отличаться):

{1, 5, 7, 20, 30}
 Приведенный ниже код:

myset1 = {1, 2, 3, 4, 5, 6}
myset2 = {2, 3, 4, 7}
myset3 = {6, 20, 30}

symdifference = myset1.symmetric_difference(myset2, myset3)

print(symdifference)
приводит к ошибке:

TypeError: symmetric_difference() takes exactly one argument (2 given)
Примечание 4. Таблица соответствия методов и операторов над множествами.

A | B
A.union(B)
Возвращает множество, являющееся объединением множеств A и B
A |= B
A.update(B)
Добавляет в множество A все элементы из множества B
A & B
A.intersection(B)
Возвращает множество, являющееся пересечением множеств A и B
A &= B
A.intersection_update(B)
Оставляет в множестве A только те элементы, которые есть в множестве B
A - B
A.difference(B)
Возвращает разность множеств A и B
A -= B
A.difference_update(B)
Удаляет из множества A все элементы, входящие в B
A ^ B
A.symmetric_difference(B)
Возвращает симметрическую разность множеств A и B
A ^= B
A.symmetric_difference_update(B)
Записывает в A симметрическую разность множеств A и B"""
from functools import reduce
from operator import and_

'''Количество совпадающих
На вход программе подаются две строки текста, содержащие числа. Напишите программу, которая определяет количество 
чисел, которые есть как в первой строке, так и во второй.

Формат входных данных
На вход программе подаются две строки текста, содержащие числа, отделенные символом пробела.

Формат выходных данных
Программа должна вывести количество чисел, содержащихся одновременно как в первой строке, так и во второй.

Sample Input 1:

1 3 2
4 3 2
Sample Output 1:

2
Sample Input 2:

1 2 6 4 5 7
10 2 3 4 8
Sample Output 2:

2
Sample Input 3:

1 7 3 8 10 2 5
6 5 2 8 4 3 7
Sample Output 3:

5'''

# myset1 = set(input().split())
# myset2 = set(input().split())
#
# myset3 = myset1.intersection(myset2)
# print(len(myset3))


# print(len(set(input().split()) & set(input().split())))


# print(len(set(input().split()).intersection(set(input().split()))))


# print(len(set.intersection(*(set(input().split()) for _ in '..'))))


# seta, setb = set(input().split()), set(input().split())
# print(len(seta & setb))

'''Общие числа
На вход программе подаются две строки текста, содержащие числа. Напишите программу, которая выводит все числа в 
порядке возрастания, которые есть как в первой строке, так и во второй.

Формат входных данных
На вход программе подаются две строки текста, содержащие числа, отделенные символом пробела.

Формат выходных данных
Программа должна вывести множество чисел, встречающихся в обеих строках.

Sample Input 1:

1 2 3
1 2 4 5
Sample Output 1:

1 2
Sample Input 2:

1 3 5
5 3 1
Sample Output 2:

1 3 5'''

# f1 = set(map(int, input().split()))
# f2 = set(map(int, input().split()))
# f3 = f1 & f2
# f3 = sorted(f3)
# print(*f3, sep=' ')

# print(*sorted(set(input().split()) & set(input().split()), key=int))

# print(*sorted(map(int, set(input().split()) & set(input().split()))))


# set1, set2 = set(map(int, input().split())), set(map(int, input().split()))
# print(*sorted(set1 & set2))


'''Числа первой строки
На вход программе подаются две строки текста, содержащие числа. Напишите программу, которая выводит все числа в 
порядке возрастания, которые есть в первой строке, но отсутствуют во второй.

Формат входных данных
На вход программе подаются две строки текста, содержащие числа, отделенные символом пробела.

Формат выходных данных
Программа должна вывести множество чисел, встречающихся только в первой строке.

Sample Input 1:

1 2 3 4
5 6 7 8
Sample Output 1:

1 2 3 4
Sample Input 2:

1 2 3 4 5
1 2 3 4 6
Sample Output 2:

5'''

# print(*sorted(map(int, set(input().split()) - set(input().split()))))


'''Общие цифры
На вход программе подается натуральное число nn, а затем nn различных натуральных чисел, каждое на отдельной строке.
 Напишите программу, которая выводит все общие цифры в порядке возрастания у всех введенных чисел.

Формат входных данных
На вход программе подаются натуральное число n \ge 1n≥1, а затем nn различных натуральных чисел, каждое на отдельной 
строке.

Формат выходных данных
Программа должна вывести цифры в соответствии с условием задачи. Если общих цифр нет, то ничего выводить не нужно.

Sample Input 1:

4
12345
236
3452222
9302
Sample Output 1:

2 3
Sample Input 2:

6
1234567890
87654321
34567890
987234356
1236789
987532
Sample Output 2:

3 7 8'''

# n = int(input())
# a = [{int(i) for i in input()} for _ in range(n)]
# print(*sorted(set.intersection(*a)))


# print(*sorted(set.intersection(*map(set, [set(input()) for _ in range(int(input()))]))))


# n = int(input())
# numbers = [input() for _ in range(n)]
#
# num_set = set(numbers[0]).intersection(*numbers)
# print(*sorted(num_set))

# n, my_set = int(input()), set(input())
#
# for _ in range(n - 1):
#     my_set = my_set & set(input())
#
# print(*sorted(my_set, key=int))




