Загрузка данных


from itertools import product


def bit(value) -> int:
    return int(bool(value))


def print_table(headers: list[str], rows: list[tuple]) -> None:
    print(" ".join(headers))
    for row in rows:
        print(" ".join(str(x) for x in row))


def variable_names(n: int) -> list[str]:
    return [chr(ord("A") + i) for i in range(n)]


def task1():
    # Таблицы истинности для НЕ, И, ИЛИ, исключающего ИЛИ
    print("НЕ")
    print_table(["A", "¬A"], [(a, bit(not a)) for a in [0, 1]])
    operations = {
        "И": lambda a, b: a and b,
        "ИЛИ": lambda a, b: a or b,
        "XOR": lambda a, b: a ^ b,
    }
    for name, op in operations.items():
        print(name)
        print_table(["A", "B", "F"], [(a, b, bit(op(a, b))) for a in [0, 1] for b in [0, 1]])


def task2():
    # F(A,B) = ¬A ∨ B
    rows = [(a, b, bit(not a or b)) for a in [0, 1] for b in [0, 1]]
    print_table(["A", "B", "F"], rows)
    ones = sum(row[2] for row in rows)
    print(f"Наборов, при которых F = 1: {ones}")  # 3


def task3():
    # F(A,B,C) = (A ∧ ¬B) ∨ C
    rows = [(a, b, c, bit((a and not b) or c))
            for a in [0, 1] for b in [0, 1] for c in [0, 1]]
    print_table(["A", "B", "C", "F"], rows)
    print("Наборы, при которых F = 1:")
    for a, b, c, f in rows:
        if f:
            print(f"A={a} B={b} C={c}")


def task4():
    # Коммутативность для И и ИЛИ
    ok_and = ok_or = True
    print("A B A∧B B∧A A∨B B∨A")
    for a in [0, 1]:
        for b in [0, 1]:
            l_and, r_and = bit(a and b), bit(b and a)
            l_or, r_or = bit(a or b), bit(b or a)
            print(a, b, l_and, r_and, l_or, r_or)
            ok_and &= l_and == r_and
            ok_or &= l_or == r_or
    print(f"A ∧ B = B ∧ A: {ok_and}")
    print(f"A ∨ B = B ∨ A: {ok_or}")
    print("Вывод: закон коммутативности выполняется" if ok_and and ok_or
          else "Вывод: закон не выполняется")


def task5():
    # Ассоциативность ИЛИ
    equal = True
    print("A B C (A∨B)∨C A∨(B∨C)")
    for a, b, c in product([0, 1], repeat=3):
        left = bit((a or b) or c)
        right = bit(a or (b or c))
        print(a, b, c, left, right)
        equal &= left == right
    print(f"Законы совпадают: {equal}")
    print("Вывод: закон ассоциативности для ИЛИ выполняется" if equal
          else "Вывод: закон не выполняется")


def task6():
    # Закон де Моргана: ¬(A ∧ B) и ¬A ∨ ¬B
    equal = True
    print("A B ¬(A∧B) ¬A∨¬B")
    for a, b in product([0, 1], repeat=2):
        left = bit(not (a and b))
        right = bit((not a) or (not b))
        print(a, b, left, right)
        equal &= left == right
    print(f"Эквивалентны: {equal}")


def task7():
    # Таблица истинности для функции от n переменных
    n = int(input("Введите число переменных: "))  # 3
    names = variable_names(n)

    def f(*values) -> int:
        # F = 1, если число единиц среди переменных нечётно (A ⊕ B ⊕ C ⊕ ...)
        return sum(values) % 2

    print_table(names + ["F"], [(*values, f(*values)) for values in product([0, 1], repeat=n)])
    print(f"Всего наборов: {2 ** n}")


def task8():
    # Сравнение двух логических функций
    pairs = [
        # (число переменных, описание F1, F1, описание F2, F2)
        (3, "A ∧ (B ∨ C)", lambda a, b, c: bit(a and (b or c)),
            "(A ∧ B) ∨ (A ∧ C)", lambda a, b, c: bit((a and b) or (a and c))),
        (2, "A ∨ B", lambda a, b: bit(a or b),
            "A ⊕ B", lambda a, b: bit(a ^ b)),
    ]
    for n, text1, f1, text2, f2 in pairs:
        names = variable_names(n)
        print(f"F1 = {text1}, F2 = {text2}")
        print_table(names + ["F1", "F2"],
                    [(*values, f1(*values), f2(*values)) for values in product([0, 1], repeat=n)])

        differences = [values for values in product([0, 1], repeat=n)
                       if f1(*values) != f2(*values)]
        print(f"Эквивалентны: {not differences}")
        if differences:
            print("Наборы, на которых результаты различаются:")
            for values in differences:
                assignment = " ".join(f"{name}={v}" for name, v in zip(names, values))
                print(f"{assignment}: F1={f1(*values)}, F2={f2(*values)}")
        print()


match int(input("Номер задания: ")):
    case 1:
        task1()
    case 2:
        task2()
    case 3:
        task3()
    case 4:
        task4()
    case 5:
        task5()
    case 6:
        task6()
    case 7:
        task7()
    case 8:
        task8()