Задание 2:
таблицы истинности

Второй способ решения — перебор расстановок.
11 класс, углублённый уровень.

Перебор вложенными циклами вы уже знаете. Сегодня — способ, при котором программа сама подбирает, какая переменная стоит в каком столбце. Приём тот же, что в задании 1: перебрать все расстановки и проверить каждую.

Что спрашивают

Функция F задана выражением F = ((x → y) ∨ (z ≡ x)) ∧ (w → z). Дан фрагмент её таблицы истинности — три строки, и не подписано, какому столбцу какая переменная досталась.

????F
00111
00100
01110

Ответ — буквы в порядке столбцов, подряд и без разделителей.

Как мы это делали: вложенные циклы

for x in range(2):
    for y in range(2):
        for z in range(2):
            for w in range(2):
                F = ((x <= y) or (z == x)) and (w <= z)
                if F == 1:
                    print(x, y, z, w)

Программа печатает все наборы, на которых F = 1, — а дальше человек глазами прикладывает их к строкам фрагмента.

Пусть столбцы
перебирает программа

Вся идея второго способа — в двух строках:

for p in permutations('xyzw'):
    p = ''.join(p)

permutations из модуля itertools выдаёт все 24 расстановки букв, join склеивает каждую в строку: 'xyzw', 'xywz', … 'zwxy'. Каждая — гипотеза: «в первом столбце z, во втором w, в третьем x, в четвёртом y». Ровно как расстановка букв по пунктам в задании 1.

Где стоит x: index

Пусть гипотеза p = 'zwxy', а строка таблицы row = (0, 0, 1, 1, 1) — четыре значения и пятым F.

номер (с нуля)01234
буква pzwxyF
значение row00111
p.index('x')          2   # номер места буквы x в строке p
row[p.index('x')]     1   # значение из этого столбца

Четыре переменные — четыре строки

x = row[p.index('x')]
y = row[p.index('y')]
z = row[p.index('z')]
w = row[p.index('w')]

F = ((x <= y) or (z == x)) and (w <= z)

После четырёх строк x, y, z, w — обычные переменные Python со значениями из этой строки таблицы. Выражение F пишется прямо, как в условии.

Сверяем с F

table = [(0, 0, 1, 1, 1),
         (0, 0, 1, 0, 0),
         (0, 1, 1, 1, 0)]

Таблица переписывается с листа как есть: строка за строкой, вместе со значением F. F — пятое число, а номера считаются с нуля, значит row[4].

Собираем проверку гипотезы

ok = True
for row in table:
    x = row[p.index('x')]
    y = row[p.index('y')]
    z = row[p.index('z')]
    w = row[p.index('w')]
    F = ((x <= y) or (z == x)) and (w <= z)
    if F != row[4]:
        ok = False
if ok:
    print(p)

Решение целиком

from itertools import *

table = [(0, 0, 1, 1, 1), (0, 0, 1, 0, 0), (0, 1, 1, 1, 0)]

for p in permutations('xyzw'):
    p = ''.join(p)
    ok = True
    for row in table:
        x = row[p.index('x')]
        y = row[p.index('y')]
        z = row[p.index('z')]
        w = row[p.index('w')]
        F = ((x <= y) or (z == x)) and (w <= z)
        if F != row[4]:
            ok = False
    if ok:
        print(p)

zwxy

Импликация — это <=

ABA → BA ≤ B
0011
0111
1000
1111

Весь перевод

¬A → not A
A ∧ B → A and B
A ∨ B → A or B
A → B → A <= B
A ≡ B → A == B

Если в таблице
есть пропуски

Демоверсия 2024, базовый уровень.

F = (x ∧ ¬y) ∨ (y ≡ z) ∨ ¬w

????F
000
1000
1010

Пустых клеток четыре. Значит и заполнений — 2⁴ = 16.

Пропуски перебирает product

from itertools import *

for a1, a2, a3, a4 in product([0, 1], repeat=4):
    table = [(a1, a2, 0, 0, 0), (1, 0, a3, 0, 0), (1, 0, 1, a4, 0)]
    if len(table) == len(set(table)):
        for p in permutations('xyzw'):
            p = ''.join(p)
            ok = True
            for row in table:
                ...             # те же строки, что и раньше
            if ok:
                print(p)

wzyx

Строчка, о которой забывают

    if len(table) == len(set(table)):
        for p in permutations('xyzw'):
            ...

В условии сказано: строки фрагмента различны. Заполнив пропуски наугад, можно получить две одинаковые строки — с таким вариантом дальше работать нельзя, перестановки для него не перебираем.

Где здесь ошибаются

ОшибкаЧто получится
x < y вместо x <= y импликация становится неверной при x = y = 1
y = row[p.index('x')] две переменные из одного столбца — программа врёт молча
row[3] вместо row[4] F сравнивается не с F, а с последним столбцом переменных
permutations('xyz') при четырёх переменных ValueError: p.index('w') не находит букву
ok = False в начале ничего не печатается: сбросить флаг можно, взвести — нечем
забыть set(table) лишние ответы там, где ответ один
from itertools import * забыт NameError: permutations не определено

А вот пропущенное p = ''.join(p) ошибкой не считается: index на кортеже работает так же, а ответ вы всё равно вписываете руками — кортеж на экране читается не хуже.

Шаблон: держите под рукой

from itertools import *

for a1, a2, a3 in product([0, 1], repeat=3):
    table = [(a1, 0, 1, a2, 0), (1, 1, a3, 0, 0), (0, 1, 1, 1, 0)]
    if len(table) == len(set(table)):
        for p in permutations('xyzw'):
            p = ''.join(p)
            ok = True
            for row in table:
                x = row[p.index('x')]
                y = row[p.index('y')]
                z = row[p.index('z')]
                w = row[p.index('w')]
                F = ...             # выражение: → это <=, ≡ это ==
                if F != row[4]:
                    ok = False
            if ok:
                print(p)

Пропусков на ЕГЭ бывает пять или семь: меняется только число a1…a7 и repeat. Всё остальное переносится без правок.

За работу

Открывайте практикум.

Шесть задач. Первые четыре — про то, как этот код устроен: их считают в голове. Два задания 2 решайте программой: набрали один раз — дальше меняете только table и строку с F.

Материалы подготовлены с использованием технологий искусственного интеллекта. Пробел раскрыть и дальше · ← → слайды