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


from itertools import product

NAMES = "xyzuvw"

def table(f, n: int) -> list:
    return [(values, int(f(*values))) for values in product((0, 1), repeat=n)]

def literal(name: str, value: int, positive_if: int) -> str:
    return name if value == positive_if else "¬" + name

def dnf_terms(rows: list) -> list:
    n = len(rows[0][0])
    return [" ∧ ".join(literal(NAMES[i], values[i], 1) for i in range(n))
            for values, result in rows if result == 1]

def knf_clauses(rows: list) -> list:
    n = len(rows[0][0])
    return ["(" + " ∨ ".join(literal(NAMES[i], values[i], 0) for i in range(n)) + ")"
            for values, result in rows if result == 0]

def dnf(f, n: int) -> str:
    terms = dnf_terms(table(f, n))
    return " ∨ ".join(terms) if terms else "0"

def knf(f, n: int) -> str:
    clauses = knf_clauses(table(f, n))
    return " ∧ ".join(clauses) if clauses else "1"

def from_bits(bits: str):
    n = len(bits).bit_length() - 1
    results = [int(b) for b in bits]
    return (lambda *values: results[int("".join(map(str, values)), 2)]), n

def equivalent(f1, f2, n: int) -> bool:
    return all(r1 == r2 for (_, r1), (_, r2) in zip(table(f1, n), table(f2, n)))

def task1():
    f = lambda x, y: (not x) or y
    print("f = ¬x ∨ y")
    print("ДНФ:", dnf(f, 2)) # ¬x ∧ ¬y ∨ ¬x ∧ y ∨ x ∧ y

def task2():
    f = lambda x, y: x and not y
    print("f = x ∧ ¬y")
    print("КНФ:", knf(f, 2)) # (x ∨ y) ∧ (x ∨ ¬y) ∧ (¬x ∨ ¬y)

def task3():
    f = lambda x, y, z: x or (y and z)
    print("f = x ∨ (y ∧ z)")
    print("ДНФ:", dnf(f, 3))
    print("КНФ:", knf(f, 3))

def task4():
    bits = input("Значения функции от x, y (4 бита, например 1011): ")
    if len(bits) != 4:
        raise ValueError("Нужно ровно 4 бита")
    f, n = from_bits(bits)
    print("x y f")
    for values, result in table(f, n):
        print(*values, result)
    print("ДНФ:", dnf(f, n)) # 1011 -> ¬x ∧ ¬y ∨ x ∧ ¬y ∨ x ∧ y

def task5():
    bits = input("Значения функции от x, y, z (8 бит, например 11110000): ")
    if len(bits) != 8:
        raise ValueError("Нужно ровно 8 бит")
    f, n = from_bits(bits)
    print("x y z f")
    for values, result in table(f, n):
        print(*values, result)
    print("КНФ:", knf(f, n))

def task6():
    pairs = (
        ("x → y и ¬x ∨ y", lambda x, y, z: (not x) or y, lambda x, y, z: (not x) or y),
        ("x ∧ (y ∨ z) и (x ∧ y) ∨ (x ∧ z)", lambda x, y, z: x and (y or z),
         lambda x, y, z: (x and y) or (x and z)),
        ("x ∨ (y ∧ z) и (x ∨ y) ∧ z", lambda x, y, z: x or (y and z),
         lambda x, y, z: (x or y) and z),
    )
    for title, f1, f2 in pairs:
        print(title)
        for values, r1 in table(f1, 3):
            r2 = int(f2(*values))
            print(*values, r1, r2)
        print("Эквивалентны:", equivalent(f1, f2, 3))
    # третья пара: False (набор 1 0 0)

def task7():
    functions = {
        "AND": lambda *v: all(v),
        "OR": lambda *v: any(v),
        "XOR": lambda *v: sum(v) % 2 == 1,
    }
    print(f"{'n':>2} | {'AND':>5} | {'OR':>5} | {'XOR':>5} | {'2^n':>5}")
    for n in range(1, 7):
        counts = [len(dnf_terms(table(f, n))) for f in functions.values()]
        print(f"{n:>2} | {counts[0]:>5} | {counts[1]:>5} | {counts[2]:>5} | {2 ** n:>5}")
    print("Максимум элементарных конъюнкций: 2^n")

def task8():
    functions = (
        ("x ∨ (y ∧ z)", lambda x, y, z: x or (y and z)),
        ("x ∧ (y ∨ z)", lambda x, y, z: x and (y or z)),
        ("x ⊕ y ⊕ z", lambda x, y, z: (x + y + z) % 2 == 1),
        ("x ∧ y ∧ z", lambda x, y, z: x and y and z),
        ("x ∨ y ∨ z", lambda x, y, z: x or y or z),
    )
    print(f"{'Функция':<14} | {'ДНФ термов':>10} | {'КНФ скобок':>10} | {'ДНФ симв.':>9} | {'КНФ симв.':>9} | Короче")
    for title, f in functions:
        d, k = dnf(f, 3), knf(f, 3)
        nd, nk = len(dnf_terms(table(f, 3))), len(knf_clauses(table(f, 3)))
        shorter = "ДНФ" if nd < nk else "КНФ" if nk < nd else "равны"
        print(f"{title:<14} | {nd:>10} | {nk:>10} | {len(d):>9} | {len(k):>9} | {shorter}")

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()