2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Логическая формула на Си
Сообщение06.05.2009, 14:31 


25/12/08
11
Доброго времени суток !
Не получается продумать задачу:
Вычислить значение ДНФ (дизъюнктивно нормальная формула) для заданных значений встречающихся в ней переменных.
По совету преподавателя для этого можно использовать два типа данных очередь (можно и стек), где в первую кладутся операнды, а во вторую операции. А также использовать обратную или прямую польскую запись...
Операций всего три: дизъюнкция, конъюнкция, отрицание.
Вот еще описание ДНФ на метаязыке:
Код:
ДНФ::={false пробелы
            элементарная-конъюнкция
            элементарная-конъюнкция OR пробелы ДНФ}
элементарная конъюнкция::={элементарный-множитель
                                             элементарный-множитель элементарная конъюнкция}
элементарный множитель::={переменная
                                            NOT пробелы переменная}
переменная::={буква пробелы}
пробелы::={символ-пробела
                  символ-пробела пробелы}
                                             

Вышенаписанное описание списано с учебника и может никакой полезной информации не нести.
Еще НУЖНО сделать таблицу (именно типа данных на Си) для присвоения значения переменным в формуле TRUE либо FALSE (может 0 или 1).
Вот не знаю как это связать и написать оссобо сложные типы днных на Си, особенно не понятно использование таблицы... можно ее и опустить... :?
З.ы. ну и еще для задания стека и т.д. я использую тип struct

 Профиль  
                  
 
 
Сообщение06.05.2009, 15:04 
Заслуженный участник


18/03/07
1068
dimaudi писал(а):
По совету преподавателя для этого можно использовать два типа данных очередь (можно и стек), где в первую кладутся операнды, а во вторую операции. А также использовать обратную или прямую польскую запись...


Что-нибудь типа алгоритма Дейкстры, наверное. Если непонятно, погуглите по словосочетанию «разбор/вычисление арифметического выражения» и сделайте наподобие.

Наверняка ДНФ можно разобрать и посчитать с меньшими затратами, чем произвольную логическую формулу, но неохота думать/вспоминать/искать.

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

В общем, так: преобразуем формулу в обратную польскую нотацию алгоритмом Дейкстры, а уж её-то мы вычислить для соответствующих значений переменных сможем легко. Вы, конечно, понимаете, что перед разбором может понадобиться выкинуть из формулы все пробелы и, возможно, добавить значки конъюнкции.

 Профиль  
                  
 
 
Сообщение06.05.2009, 19:01 


25/12/08
11
так мимо пробежав глазами по алгоритму Дейкстры увидел что он для графов и деревьев в основном... хотя в принципе конечно можно использовать, просто хотелось бы чтонить более очевидное)

 Профиль  
                  
 
 
Сообщение06.05.2009, 19:13 
Заслуженный участник
Аватара пользователя


06/10/08
6422
Не нужна здесь обратная польская.
Берем поданную на вход строку-ДНФ, идем по строке слева направо, убираем все пробелы, буквы оставляем как есть, "OR" меняем на "|"
сравниваем строку с "false". Если "false" - выдаем false
Если не false - еще раз проходим по строке, заменяем буквы на их значения. И еще раз проходим, вычисляя результат.
Скажем, после подстановки получилось
"0010|10|111|000"
Видим 0 - идем вправо до ближайшей палочки
Видим единицу - просто делаем шаг вправо. Если мы так дошли до палочки - выдаем true. Если нет - увидели 0 и опять до следующего разделителя.

 Профиль  
                  
 
 
Сообщение06.05.2009, 19:48 


25/12/08
11
Xaositect писал(а):
Не нужна здесь обратная польская.
Берем поданную на вход строку-ДНФ, идем по строке слева направо, убираем все пробелы, буквы оставляем как есть, "OR" меняем на "|"
сравниваем строку с "false". Если "false" - выдаем false
Если не false - еще раз проходим по строке, заменяем буквы на их значения. И еще раз проходим, вычисляя результат.
Скажем, после подстановки получилось
"0010|10|111|000"
Видим 0 - идем вправо до ближайшей палочки
Видим единицу - просто делаем шаг вправо. Если мы так дошли до палочки - выдаем true. Если нет - увидели 0 и опять до следующего разделителя.

Сравниваем с false, т.е. с 0 ?
OR меняем на | т.е. на логическое "или" на языке Си, тогда AND надо поменять на & ?
И надо еще что-то делать с отрицанием... т.е. если перед буквой стоит NOT, то значение надо заменить на противоположное ? Также для этого можно использовать 1 стек или очередь, складывая в него элементы вместе с операциями по порядку или все же надо использовать 2 стека (один для элементов, другой для операций) ?

 Профиль  
                  
 
 
Сообщение06.05.2009, 19:53 
Заслуженный участник
Аватара пользователя


06/10/08
6422
dimaudi в сообщении #211555 писал(а):
Сравниваем с false, т.е. с 0 ?
OR меняем на | т.е. на логическое "или" на языке Си, тогда AND надо поменять на & ?
И надо еще что-то делать с отрицанием... т.е. если перед буквой стоит NOT, то значение надо заменить на противоположное ? Также для этого можно использовать 1 стек или очередь, складывая в него элементы вместе с операциями по порядку или все же надо использовать 2 стека (один для элементов, другой для операций) ?

Сравниваем с "false", т.е. строкой. функцией strcmp.
OR меняем на символ '|'. Вообще, все преобразования символьные.
Про NOT забыл. Да, надо их в начальной строке тоже замечать и лучше, как и OR, менять на что-нибудь односимвольное, например. '-'. Соответственно, если перед буквой -, то инвертируем значение.

Стеков вообще не надо, в том и прелесть :)
Это потому что язык у нас не КС, а рекурсивный.

 Профиль  
                  
 
 
Сообщение06.05.2009, 20:00 


25/12/08
11
Xaositect писал(а):

Стеков вообще не надо, в том и прелесть :)
Это потому что язык у нас не КС, а рекурсивный.

мне надо обязательно использовать стек или ему подобные :cry:
но все равно не так уж и сложно все это дело теперь подстроить...

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group