Как преобразовать операторы условия, которые производят логическое значение, в выражение, включающее только не, и и или

Я изучаю рэкет/схему и наткнулся на онлайн-ресурс, в котором говорится, что если функция, написанная с использованием условия, дает true или false, ее можно переписать, используя только не, и и или. Я разработал несколько простых примеров, в которых мне удалось преобразовать условные операторы в операторы, включающие только не и и или. Мой вопрос заключается в том, есть ли способ сразу увидеть логику при преобразовании между этими двумя типами операторов. Я понимаю, что не всегда практично преобразовывать каждое условное выражение в комбинацию не, а и или, но мне интересно узнать о логике, лежащей в основе процесса преобразования. Заранее спасибо.

(Если что-то в вопросе не имеет смысла, оставьте комментарий, и я постараюсь уточнить, что я хочу понять)


person user14346904    schedule 26.09.2020    source источник
comment
Возможно, вам следует привести пример cond, который вы не видите, как конвертировать?   -  person Sylwester    schedule 27.09.2020
comment
У меня нет примера конда не вижу как конвертировать. Мне просто интересно, есть ли какой-нибудь логический метод/алгоритм для преобразования любого оператора cond, который приводит к логическому значению, в комбинацию не и и или.   -  person user14346904    schedule 27.09.2020
comment
Это слишком сложно, чтобы объяснять здесь, но поищите карты Карно и булеву алгебру.   -  person am121    schedule 27.09.2020
comment
stackoverflow.com/help/how-to-ask   -  person alinsoar    schedule 28.09.2020
comment
@ am121 это неправильно. Km используются для сжатия логических выражений.   -  person alinsoar    schedule 30.09.2020


Ответы (3)


Все условные выражения (и не только те, которые оцениваются как истина/ложь) могут быть переписаны с использованием только логических комбинаторов. Это связано с тем, как оцениваются логические операторы в Scheme/Racket. Например, логически (and a b) будет истинным, если оба a и b истинны, а в противном случае ложны. Но в Racket результатом (and a b) будет b, если и a, и b правдивы, а в противном случае - ложь. То есть оценка продолжается вправо до тех пор, пока не встретится либо последний аргумент, либо ложное значение. В этот момент оценка останавливается, и это значение (которое может быть логическим, но не обязательно) возвращается. Поскольку and и or не просто выводят логические значения, их можно использовать вместо условных выражений.

E.g.

(if #t 'hello 'bye) ;=> hello
(or (and #t 'hello) 'bye) ;=> hello
(if #f 'hello 'bye) ;=> bye
(or (and #f 'hello) 'bye) ;=> bye
(cond [#f 'hello]
      [#f 'bye]
      [#t 'aloha]) ;=> aloha
(or (and #f 'hello)
    (and #f 'bye)
    (and #t 'aloha)) ;=> aloha

Но обычно вы не хотели бы использовать их таким образом, поскольку их трудно читать. Как правило, в большинстве случаев используйте if и cond, а не элементарные логические операторы. Если вас интересует только действие при положительном или отрицательном результате условного выражения, вы можете использовать when или unless. Если вы заботитесь об обработке как положительных, так и отрицательных результатов, но один из них является логическим результатом, как в этом примере:

(if (positive? n)
  #t
  (even? n))

... тогда это был бы случай, когда логический оператор был бы предпочтительнее, например:

(or (positive? n) (even? n))

Если оба плеча условного оператора if являются логическими значениями, например:

(if (> n 3)
  #t
  #f)

... затем просто замените все условное выражение самим условием:

(> n 3)

В противном случае придерживайтесь if и cond.

person mindthief    schedule 27.09.2020
comment
Вы не можете написать, например, (if some-condition #f #t) как (or (and some-condition #f) #t). Конечно, условное выражение - это неправильный способ выражения отрицания, но OP, похоже, спрашивает о cond выражениях, которые оцениваются как логическое значение. - person ad absurdum; 28.09.2020
comment
Это хороший момент, значения #f в последующей позиции потребуют специальной обработки. Для этого конкретного примера, следуя рекомендациям в ответе, вместо этого будет написано (not some-condition), но вы правы, что это не относится к общему случаю ложных последовательных выражений. - person mindthief; 28.09.2020
comment
Большое тебе спасибо. Я ценю все примеры. - person user14346904; 28.09.2020
comment
повторное ложное следствие, действительно (or (and #t #f) 'bye) ;=> bye, но (or (and #t #f) (and (not #t) 'bye)) ;=> #f правильно. наверное тоже надо ввести temp var через let, в общем. - person Will Ness; 11.11.2020

Как только вы преобразуете cond во вложенные if, вы всегда можете превратить его в and or и not следующим образом:

(if A B C) --> (or (and A B) (and (not A) C))

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

(if A B #f) --> (and A B)
(if A B #t) --> (or (not A) B)
(if A #f C) --> (and (not A) C)
(if A #t C) --> (or A C)

(примечание: указанное выше or может возвращать другое истинное значение, отличное от #t, что делает его технически другим, но эквивалентным при использовании в качестве логического значения)

Еще одна вещь, которую я должен отметить, это то, что иногда вы можете преобразовать несколько ветвей cond в and or not без предварительного преобразования в ifs. Например, 3-ветвь cond:

(cond [A B]
      [C D]
      [else E])
-->
(or (and A B)
    (and (not A) C D)
    (and (not A) (not C) E))

Или 4-ветвь cond:

(cond [A B]
      [C D]
      [E F]
      [else G])
-->
(or (and A B)
    (and (not A) C D)
    (and (not A) (not C) E F)
    (and (not A) (not C) (not E) G))

Каждый and соответствует условной ветви, а and каждой условной ветви содержит nots для каждого предыдущего условия в дополнение к своему собственному условию.

Вы можете применить более общее правило:

for i from 1 through n,
(cond [Q_i A_i]
      ...
      [else E])
-->
on each i, for j from 1 through i-1,
(or (and (not Q_j) ... Q_i A_i)
    ...
    (and (not Q_i) ... E)
person Alex Knauth    schedule 30.09.2020
comment
(lambda (x) (not (not x))) превратит истинное значение в логическое. - person Will Ness; 11.11.2020

Прежде всего, вам нужно преобразовать язык условий в последовательность последовательностей if-then-else, что тривиально.

После этого вы можете переписать условные операторы if в логические операторы. Вы можете заглянуть в руководство по логике высказываний, чтобы узнать об этом. Или посмотрите здесь.

Кстати. Запрещено вставлять домашнее задание при переполнении стека.

person alinsoar    schedule 27.09.2020
comment
Большое тебе спасибо. Да, я позабочусь о том, чтобы не задавать домашних вопросов о переполнении стека. - person user14346904; 28.09.2020
comment
@user14346904 user14346904 Вы можете задавать вопросы, но вам нужно показать, что вы пробовали, а не только сам вопрос. Прочитайте stackoverflow.com/help/how-to-ask. - person alinsoar; 28.09.2020