Lisp - [преобразование КНФ в правильную КНФ]
---
...Я работаю антинаучным аферистом...
внутреннее представление обрабатываемых символьных выражений - тоже
("через задницу" наверное не стоит)
Могу потом перевести и на Елисп, устанавливать Common не хочу.
На выбор.
Есть прямой способ, без оптимизаций и прочих наворотов.
---
...Я работаю антинаучным аферистом...
Если сделаешь с комментами будет супер. Елисп подойдет , только расшарь его потом плиз.
---
...Я работаю...
(define (uniq lst)
(if (null? lst) lst
(let ulst (uniq (cdr lst
(if (member (car lst) ulst) ulst lst
(uniq '(a b c d e f
(uniq 'a a) (b b) (c c
(uniq '(a a b c a d b c
(uniq '(a (a a) a (a a) (a a) a
(define (check-var-i var df)
(and (member var df) (member (list 'not var) df
(define (check-var var df)
(if (and (list? var) (eqv? 'not (car var
(check-var-i (cadr var) df)
(check-var-i var df
(display "check-var") (newline)
(check-var 'a '(a b c
(check-var 'a 'not a) b c
(check-var 'a 'not a) b a c
(define (simplify-disj df)
(cond null? df) df)
equal? '(#f)
(uniq (map check-var df
(make-list (length df) df
df)
(else #t
(display "simplify-disj") (newline)
(simplify-disj '(a
(simplify-disj '(a b c d
(simplify-disj 'not a) b (not c) d
(simplify-disj 'not a) b (not c) c d
(simplify-disj '(a b c a (not c) b a d
(newline)
(define (filter p l)
(if (null? l) l
(if (p (car l
(cons (car l) (filter p (cdr l
(filter p (cdr l
(lambda (x) (not (eqv? #t x
(define (not-#t? x) (not (eqv? #t x
(define (simplify-conj cf)
(if (member #f cf) #f
(let pcnf
(uniq (map simplify-disj (filter not-#t? cf
(if (member #f pcnf) #f
(filter not-#t? pcnf
(simplify-conj
'a b c d)
(a (not a) b c d)
#f
(a c d)
(a b c d
(simplify-conj
'a b c d)
(a (not a) b c d)
(a c d)
(a b c d
Scheme R5.
Проверялось на Guile:
cat file.scm | guile
Вопросы?
---
...Я работаю антинаучным аферистом...
![](/images/graemlins/smile.gif)
книжку по лиспу сейчас возьму и буду врубаться
thx тебе огромный, но ты не мог бы хоть немного комментариев поставить - где там что происходит?
\\ и инета сейчас нет, чтоб почитать тот сайт
;; -*- coding: cyrillic-alternativnyj; -*-
; $Id: knf.scm,v 1.2 2006/05/17 13:39:48 user Exp $
; Нам понадобится работать со списком, как с множеством,
; то есть, надо исключать повторные вхождения.
(define (uniq lst)
(if (null? lst) lst
(let ulst (uniq (cdr lst
(if (member (car lst) ulst) ulst lst
; Проверка:
(uniq '(a b c d e f
(uniq 'a a) (b b) (c c
(uniq '(a a b c a d b c
(uniq '(a (a a) a (a a) (a a) a
; Проверяем вхождение переменной и её отрицания в дизъюнктивную форму.
(define (check-var-i var df)
(and (member var df) (member (list 'not var) df
; Поскольку переменная может встретиться в виде отрицания,
; возможно, потребуется снять объемлющее "not"
(define (check-var var df)
(if (and (list? var) (eqv? 'not (car var
(check-var-i (cadr var) df)
(check-var-i var df
; Проверка:
(check-var 'a '(a b c
(check-var 'a 'not a) b c
(check-var 'a 'not a) b a c
(check-var '(not a) 'not a) b a c
; Упрощение ДФ: исключение повторов, проверка на то,
; что она не сводится к тождественной.
(define (simplify-disj df)
(cond null? df) df)
equal? '(#f)
(uniq (map check-var df
(make-list (length df) df
df)
(else #t
(begin (display "Testing simplify-disj") (newline
(simplify-disj '(a
(simplify-disj '(a b c d
(simplify-disj 'not a) b (not c) d
(simplify-disj 'not a) b (not c) c d
(simplify-disj '(a b c a (not c) b a d
(newline)
; Выборка членов списка, удовлетворяющих условию p.
(define (filter p l)
(if (null? l) l
(if (p (car l
(cons (car l) (filter p (cdr l
(filter p (cdr l
(define (not-#t? x) (not (eqv? #t x
; Упрощение конъюнктивной формы:
; отсечение тождественно ложных и тождественно истинных членов,
; упрощение входящих дизъюнктивных форм, устранение повторов.
(define (simplify-conj cf)
(if (member #f cf) #f
(let pcnf
(uniq (map simplify-disj (filter not-#t? cf
(if (member #f pcnf) #f
(filter not-#t? pcnf
; Проверка
(simplify-conj
'a b c d)
(a (not a) b c d)
#f
(a c d)
(a b c d
(simplify-conj
'a b c d)
(a (not a) b c d)
(a c d)
(a b c d
---
...Я работаю...
Тут все слова понятны, а на каком диалекте шепчешь ты, я не знаю,
да и ты сам --- не сказал.
---
...Я работаю антинаучным аферистом...
![](/images/graemlins/blush.gif)
;; -*- coding: cyrillic-alternativnyj; -*-
; $Id: knf.el,v 1.3 2006/05/17 14:18:22 user Exp $
; Нам понадобится работать со списком, как с множеством,
; то есть, надо исключать повторные вхождения.
(defun uniq (lst)
(if (null lst) lst
(let ulst (uniq (cdr lst
(if (member (car lst) ulst) ulst lst
; Проверка:
(uniq '(a b c d e f
(uniq 'a a) (b b) (c c
(uniq '(a a b c a d b c
(uniq '(a (a a) a (a a) (a a) a
; Проверяем вхождение переменной и её отрицания в дизъюнктивную форму.
(defun check-var-i (var df)
(and (member var df) (member (list 'not var) df
; Поскольку переменная может встретиться в виде отрицания,
; возможно, потребуется снять объемлющее "not"
(defun check-var (var df)
(if (and (listp var) (eq 'not (car var
(check-var-i (cadr var) df)
(check-var-i var df
; Проверка:
(check-var 'a '(a b c
(check-var 'a 'not a) b c
(check-var 'a 'not a) b a c
(check-var '(not a) 'not a) b a c
(defun maplist (f l)
(if (null l) l
(cons (apply f (list (car l (maplist f (cdr l
(defun mapl (f l)
(if (member nil l) nil
(cons (apply f (maplist 'car l
(mapl f (maplist 'cdr l
(defun map (f &all l) (mapl f l
; Упрощение ДФ: исключение повторов, проверка на то,
; что она не сводится к тождественной.
(defun simplify-disj (df)
(cond null df) df)
equal '(nil)
(uniq (mapl 'check-var (list df
(make-list (length df) df
df)
(t t
(simplify-disj '(a
(simplify-disj '(a b c d
(simplify-disj 'not a) b (not c) d
(simplify-disj 'not a) b (not c) c d
(simplify-disj '(a b c a (not c) b a d
(newline)
; Выборка членов списка, удовлетворяющих условию p.
(defun filter (p l)
(if (null l) l
(if (apply p (list (car l
(cons (car l) (filter p (cdr l
(filter p (cdr l
(defun not-t (x) (not (eq t x
; Упрощение конъюнктивной формы:
; отсечение тождественно ложных и тождественно истинных членов,
; упрощение входящих дизъюнктивных форм, устранение повторов.
(defun simplify-conj (cf)
(if (member nil cf) nil
(let pcnf
(uniq (mapl 'simplify-disj (list (filter 'not-t cf
(if (member nil pcnf) nil
(filter 'not-t pcnf
; Проверка
(simplify-conj
'a b c d)
(a (not a) b c d)
nil
(a c d)
(a b c d
(simplify-conj
'a b c d)
(a (not a) b c d)
(a c d)
(a b c d
---
INSTITUTE's Name Shows That It's Totally Unrelated To Emacs.
muchas gracias
===================================================================
RCS file: RCS/knf.scm,v
retrieving revision 1.2
diff -u -r1.2 knf.scm
--- knf.scm 2006/05/17 13:39:48 1.2
+++ knf.scm 2006/05/17 17:48:09
@@ -1,5 +1,5 @@
;; -*- coding: cyrillic-alternativnyj; -*-
-; $Id: knf.scm,v 1.2 2006/05/17 13:39:48 user Exp $
+; $Id: knf.scm,v 1.4 2006/05/17 17:46:17 user Exp $
; Нам понадобится работать со списком, как с множеством,
; то есть, надо исключать повторные вхождения.
@@ -31,15 +31,17 @@
(check-var 'a 'not a) b a c
(check-var '(not a) 'not a) b a c
+; Проверка на то, что все члены списка равны заданному.
+(define (all? el lst) (equal? (list el) (uniq lst
+
; Упрощение ДФ: исключение повторов, проверка на то,
; что она не сводится к тождественной.
(define (simplify-disj df)
- (cond null? df) df)
- equal? '(#f)
- (uniq (map check-var df
- (make-list (length df) df
- df)
- (else #t
+ (cond
+ all? #f df) #f)
+; member #t df) #t)
+ all? #f (map check-var df (make-list (length df) df df)
+ (else #t
(begin (display "Testing simplify-disj") (newline
@@ -48,14 +50,14 @@
(simplify-disj 'not a) b (not c) d
(simplify-disj 'not a) b (not c) c d
(simplify-disj '(a b c a (not c) b a d
+(simplify-disj '(#f #f #f
(newline)
; Выборка членов списка, удовлетворяющих условию p.
(define (filter p l)
- (if (null? l) l
- (if (p (car l
- (cons (car l) (filter p (cdr l
- (filter p (cdr l
+ (cond null? l) l)
+ p (car l (cons (car l) (filter p (cdr l
+ (else (filter p (cdr l
(define (not-#t? x) (not (eqv? #t x
@@ -82,3 +84,11 @@
(a (not a) b c d)
(a c d)
(a b c d
+
+(simplify-conj
+ 'a b c d)
+ (a (not a) b c d)
+ (a c d)
+ (#f #f)
+ (a c d c)
+ (a b c d
---
"Потому что Аллах не ведёт людей неверных."
![](/images/graemlins/smile.gif)
Ну теперь-то я знаю, как выглядит удобный, читабельный и интуитивно-очевидный код, которого так не хватает всем этим ламерским ООП-языкам.
![](/images/graemlins/lol.gif)
Емакс-лисп --- это полноценный Лисп.
Да, в Емакс-лиспе, в силу его особенностей, нет map.
В какой библиотеке находится filter, я не помню, а потому просто доопределил.
Точно так же я не заморачивался и с другими вещами,
поскольку было требование побыстрее, а не попроще и получше.
Вот когда стандарт Common LISP будет помещаться на 50 страницах,
тогда вернёмся к обсуждению его достоинств, а покуда это не так,
Common LISP будет похуже фортрана, поскольку последний превосходит Common LISP
как по простоте, так и по функциональности стандартного кода.
Мало того, кто-кто, а ты вообще молчал бы, что-то от тебя решения не увидели --- в кусты спрятался.
---
...Я работаю антинаучным аферистом...
Ну теперь-то я знаю, как выглядит удобный, читабельный и интуитивно-очевидный код, которого так не хватает всем этим ламерским ООП-языкамЧего смешного то? Вполне понятный и легко читаемый код. На C++ многие гораздо хуже пишут.
Мало того, кто-кто, а ты вообще молчал бы, что-то от тебя решения не увидели --- в кусты спрятался.Просто я так и не понял в чем заключается задача
![](/images/graemlins/wink.gif)
---
...Я работаю антинаучным аферистом...
Утверждается, что код может прочитать только человек, очень хорошо знакомый с этим языком.
Чего смешного то? Вполне понятный и легко читаемый код. На C++ многие гораздо хуже пишут.
(simplify-conj
'a b c d)
(a (not a) b c d)
nil
(a c d)
(a b c d
Вот это мне НИ О ЧЁМ не говорит, то есть вообще. Даже плохо написанный код на С++ содержал бы какие-то слова, которые могли бы натолкнуть на мысль. А тут полный ноль. И не надо орать "ботай матчасть", как некоторые любят делать. Приведённый код неудобно читать.
В данном случае - нет
![](/images/graemlins/smile.gif)
Ну то есть, слово SimplifyConj содержал бы тоже
![](/images/graemlins/smile.gif)
![](/images/graemlins/smile.gif)
Слова main, do, while, if, else и return наталкивают просто на офигенные мысли.
А уж про обозначение "==" я вообще молчу.
---
...Я работаю антинаучным аферистом...
Предъяви код.
---
"Истина всегда конкретна."
Главное, что они вообще наталкивают на мысли. Где начинается твоя программа и как она начинается вообще нельзя понять. А if/else наталкивают на вполне определённые мысли. Про "==" я уже давно писал, что все языки определяют присваивание и сравнение по-своему, в паскале, например, есть ":=".
Слова main, do, while, if, else и return наталкивают просто на офигенные мысли.
А уж про обозначение "==" я вообще молчу.
Помнишь, что ты отвечал, когда я тебя просил предъявить код на ЛИСПе для кучи задач, в которые ты лез спорить? А сейчас тебе за год попалась-таки задача, которая хорошо ложится на фя, и ты начинаешь петушиться.
Предъяви код.
Программа начинается с начала и заканчивается концом.
Вообще же, умение дифференцировать простые линейные формы
должно было быть выработано ещё в старшей группе детского сада.
> А if/else наталкивают на вполне определённые мысли.
Прикинь, слова "define," "map," "filter" тоже наталкивают на определённые мысли!
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
можешь воспользоваться этим --- просто перевести со Схемы на Си.
Чисто для сравнения.
Я и продолжаю утверждать, что императивное программирование --- отстой.
---
...Я работаю антинаучным аферистом...
Давай поступим вот так: придём в старшую группу детского сада и всех детишек попросим (дословно) "продифференцировать простые линейные формы". Как ты думаешь, что после этого будут думать детишки про дядю контру?
Вообще же, умение дифференцировать простые линейные формы
должно было быть выработано ещё в старшей группе детского сада.
![](/images/icons/grin.gif)
История знает случаи, когда у тебя тоже было такое "преимущество". Естественно, для человека, который не знает ЛИСПа, это вовсе не преимущество. Если бы я и стал сейчас писать код на Си, то сначала бы прочитал про алгоритм решения поставленной задачи.
У тебя есть преимущество в виде уже работающего кода,
можешь воспользоваться этим --- просто перевести со Схемы на Си.
Нет.
Таких случаев пока что не наблюдалось: насильники пишут
в стиле "настоящих программистов", с циклами на пять страниц и т.п.
Когда ты мне покажешь прилично написанную программу,
то есть состоящую из подпрограмм длиной не более 6-8 строк,
тогда и будешь говорить о читаемости.
---
"Мы диалектику учили не по Гегелю."
тогда может чё-нть сваяю.
> ДНФ - правильная, если каждая ее элементарная конъюнкция
> не содержит повторных вхождений одной переменной.
---
...Я работаю антинаучным аферистом...
> ДНФ - правильная...
vs
> Что такое правильная КНФ?
Твои проблемы, что ты не на ту строку посмотрел.
У меня то же самое, когда код на C++ с шаблонами наблюдаю - не знаю, куда смотреть, чтобы понять что-то.
Я честно посмотрел всю программу.
Твои проблемы, что ты не на ту строку посмотрел.
![](/images/icons/mad.gif)
Начинается она в начале, как уже было сказано.
> что-то печатает на экран
Печатается на экран тестовый пример, разумеется. А что ещё могло бы?
![](/images/icons/grin.gif)
Хотя пример неточный, может Lynn и LISP поймёт.
Не важно, что могло. Мой пост был о том, что я просмотрел всю программу.
Давай поступим вот так: придём в старшую группу детского сада и всех детишек попросим (дословно) "продифференцировать простые линейные формы". Как ты думаешь, что после этого будут думать детишки про дядю контру?"продифференцировать простые линейные формы" - имеется в виду отличать треугольник от квадрата и т.д. Некоторые просто физиологически не могут вести себя (в т.ч. говорить) по-человечески.
Смысл моего поста не в этом.
"продифференцировать простые линейные формы" - имеется в виду отличать треугольник от квадрата и т.д. Некоторые просто физиологически не могут вести себя (в т.ч. говорить) по-человечески.
![](/images/icons/grin.gif)
Физик.
> ДНФ - правильная...
vs
> Что такое правильная КНФ?
Мышление напрочь отбило?
Есть такой способ, по аналогии.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
Посимвольно? Я так тоже C++ могу просматривать, это не поможет понять, что там делают эти шаблоны.
А я и не утверждаю, что всё будет понятно. А поняв, что такое шаблоны в одном языке, можно потом понять, что они делают и как работают в других языках. Впрочем, ФЯ тоже должны быть похожи в этом плане.
Посимвольно? Я так тоже C++ могу просматривать, это не поможет понять, что там делают эти шаблоны.
---
...Я работаю антинаучным аферистом...
Мышление напрочь отбило?Как показывает практика придумывать определения "по аналогии", особо не разбираясь в предметной области может быть чревато.
Есть такой способ, по аналогии.
Что такое функция в твоём понимании?
Очевидно, что ты так и не понял, что такое функция.
что такое конъюнкция, и почему есть двойственность?
---
...Я работаю антинаучным аферистом...
---
...Я работаю антинаучным аферистом...
Да, ты реально любишь, когда люди тебя не понимают. Проблемы с самоутверждением, что ли? Выражайся яснее, чтобы смертным, типа меня, было понятно. Зависимость чего от чего? Результата от аргументов?
Однозначная зависимость.
У тебя явные проблемы с мышлением.
А что ещё может быть?
Сравни "А есть функция Б и В" и "А однозначно зависит от Б и В."
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
(simplify-conj
'a b c d e e e
выдаёт результат
guile> a b c d e e e
Написано, что повторных вхождений быть не должно. Или я не правильно понял формат входных данных?
Вот ещё не ясно, такое выражение
(simplify-conj
'(
(a b c d e)
(abc)
(abc)
)
)
выдаёт
a b c d e) (abc) (abc
в то время как
(simplify-conj
'(
(abc)
(abc)
)
)
выдаёт
abc
Ты предлагаешь мне объяснять, что такое дизъюнкция,Какая ещё двойственность?
что такое конъюнкция, и почему есть двойственность?
Ты мне предлагаешь рассказать тебе основы мат.логики?
(define (uniq lst)
(if (null? lst) lst
(let ulst (uniq (cdr lst
(if (member (car lst) ulst) ulst
(cons (car lst) ulst
(define (simplify-disj df)
(cond
all? #f df) #f)
; member #t df) #t)
all? #f (map check-var df (make-list (length df) df
(uniq df
(else #t
А ещё элементарные дизъюнкции надо отсортировать.
---
...Я работаю...
эти все поправки - улучшения работы уже правильной программы или же это багофиксы?
Смотря как послностью сформулировать задачу. Ещё надо добавить код, чтобы (a b c) и (c a b) считались одинаковыми и оптимизировались.
Предъяви код.Стёрто, чтобы не наезжали без повода.
Ну-ка предъявите ОО решение на приплюсях, яве или чём ещё.Python:
def simplify_disj(disj):
ctos= (None, '', '!')
els= {}
for el in disj.split(' '):
if el[0] == '!':
el= el[1:]
vl= 2
else: vl= 1
els[el]= els.get(el, 0) | vl
return ' '.join(ctos[els[el]]+el for el in sorted(els.iterkeys if els[el] != 3)
def simplify_cnf(cnf):
return ''.join('('+disj+')' for disj in set(simplify_disj(disj) for disj in cnf[1:-1].split(''.difference(['']
# Unit testing section:
if __name__ == '__main__':
totest= ("(a b !c)",
"(a a b !c !a b)",
"(a a !a)",
"(a a !aa b)",
"(a ba b)",
"(a b a dd b c !a)")
for cnf in totest:
print cnf, '->', simplify_cnf(cnf)
> Парсер строки и преобразование тут в одном флаконе.
Про модульность на вашей работе не слышали?
Достаточно понимать самые основы Lisp чтобы понять код. При условии понимания синтаксиса --- код тривиален. Я бы разделил сложность кода на сложность синтаксическую и алгоритмическую. Здесь алгоритмическая близка к нулю — код простой.
> Вот это мне НИ О ЧЁМ не говорит, то есть вообще. Даже плохо написанный код на С++ содержал бы какие-то слова, которые могли бы натолкнуть на мысль.
Несогласен. Вот например, сравни с таким кодом (boost_concept_check.h из стандартной поставки gcc 4.0.3)
template <class _ReversibleContainer>
struct _Mutable_ReversibleContainerConcept
{
typedef typename _ReversibleContainer::iterator _Iterator;
typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator;
void __constraints {
__function_requires<_ReversibleContainerConcept<_ReversibleContainer> >
__function_requires<
_Mutable_ForwardContainerConcept<_ReversibleContainer> >
__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >
__function_requires<
_Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >
_Reverse_iterator __i = __c.rbegin;
__i = __c.rend;
}
_ReversibleContainer __c;
};
Человек не рюхающий C++ не поймет тут ничего.
> А тут полный ноль. И не надо орать "ботай матчасть", как некоторые любят делать. Приведённый код неудобно читать
Код просто не похож на C. И все. Других особенностей у него нет.
Почему все так бояцца скобочной записи? IMHO очень простая вещь.
Про модульность на вашей работе не слышали?Я написал эту функцию за 10 минут просто чтобы показать, что написать вообще можно.
"Real programmer can program FORTRAN in any language."
Если ты способен писать такое, то принимать от тебя ссылки на "уставший" --- преступление.
> Работает в два раза быстрее
А это вообще не рассматривается, "machine cycles are cheap."
---
...Я работаю антинаучным аферистом...
Конечно можно, только не модульно и непонятно. Кто бы сомневался.
К вопросу о словах: в твоём коде спецсимволов больше, чем слов.
Если ты способен писать такое, то принимать от тебя ссылки на "уставший" --- преступление.В чём твои проблемы? Я пришёл с работы и накатал код, не вижу в этом ничего плохого. Впрочем, не стоило этого делать конктретно в этом топике.
А это вообще не рассматривается, "machine cycles are cheap."
Да что ты говоришь?..
#include "stdafx.h"
#include <vector>
#include <string>
#include <set>
#include <iostream>
#include <map>
#include <time.h>
class CSimpleDisj
{
std::map<std::string, bool> m_mapVars;
typedef std::map<std::string, bool>::iterator TIterator;
typedef std::pair<std::string, bool> TPair;
public:
bool operator < (const CSimpleDisj& rfSrc) const
{
return m_mapVars < rfSrc.m_mapVars;
}
bool AddVariable(std::string rfVarName, bool bNotFlag)
{
TIterator iter = m_mapVars.find(rfVarName);
if (iter == m_mapVars.end
{
m_mapVars.insert(TPair(rfVarName, bNotFlag;
return true;
}
else
if (iter->second != bNotFlag)
{
//std::cout << "Disj rejected." << std::endl;
m_mapVars.clear;
return false;
}
else
return true;
}
bool HasVariables
{
return m_mapVars.size > 0;
}
void Clear
{
m_mapVars.clear;
}
void DebugPrint
{
for (TIterator iter = m_mapVars.begin; iter != m_mapVars.end; )
{
std::cout << (iter->second ? "not " : "") << iter->first;
iter++;
if (iter != m_mapVars.end
std::cout << ' ';
}
}
};
class CConjDisj
{
std::set<CSimpleDisj> m_setDisj;
typedef std::set<CSimpleDisj>::iterator TIterator;
CSimpleDisj m_cTempDisj;
bool m_bSkipDisj;
public:
void AddVariable(std::string& rfVarName, bool bNotFlag)
{
if (m_bSkipDisj)
return;
//std::cout << "Variable: " << (bNotFlag ? "not " : "") << rfVarName << std::endl;
m_bSkipDisj = !m_cTempDisj.AddVariable(rfVarName, bNotFlag);
}
void EndOfDisj
{
m_bSkipDisj = false;
if (m_cTempDisj.HasVariables
{
TIterator iter = m_setDisj.find(m_cTempDisj);
if (iter == m_setDisj.end
{
//std::cout << "New disj added." << std::endl;
m_setDisj.insert(m_cTempDisj);
}
else
{
//std::cout << "Same disj, rejected." << std::endl;
}
m_cTempDisj.Clear;
}
}
CConjDisj : m_bSkipDisj(false)
{
}
void DebugPrint
{
for (TIterator iter = m_setDisj.begin; iter != m_setDisj.end; iter++)
{
std::cout << '(';
iter->DebugPrint;
std::cout << ')' << std::endl;
}
}
};
void ParseString(const char* strData, CConjDisj& rfResult) throw(std::runtime_error)
{
int nBracerFlag = 0;
std::string strToken;
bool bNotFlag = false;
for (const char* c = strData; *c != '\0'; c++)
{
switch (*c)
{
case '(':
if (++nBracerFlag > 1)
throw std::runtime_error("Parse error.");
break;
case ')':
if (--nBracerFlag < 0 || bNotFlag)
throw std::runtime_error("Parse error.");
case ' ':
if (strToken.length > 0)
{
if (strToken == "not")
bNotFlag = !bNotFlag;
else
{
rfResult.AddVariable(strToken, bNotFlag);
bNotFlag = false;
}
strToken.clear;
}
if (nBracerFlag == 0)
rfResult.EndOfDisj;
break;
default:
if (nBracerFlag != 1)
throw std::runtime_error("Parse error.");
if *c < 'a' || *c > 'z') && (*c < 'A' || *c > 'Z'
throw std::runtime_error("Invalid character.");
strToken += *c;
}
}
}
int main(int argc, char* argv[])
{
__time64_t nTime = _time64(NULL);
const char* strConjDisj = "(a b c) (a b cd e f e e) (c b a) (a b c) (a b cd e f e e)"
"(a b not c not not c k) (e a b cd e f) (a not not c b b) (not k k)";
try
{
for (int i = 0; i < 100000; i++)
{
CConjDisj cConjDisj;
ParseString(strConjDisj, cConjDisj);
//cConjDisj.DebugPrint;
}
}
catch(std::runtime_error cError)
{
std::cout << "Error: " << cError.what << std::endl;
}
std::cout << "All done, time: " << _time64(NULL)-nTime << std::endl;
std::cin.get;
return 0;
}
То же --- с main.
В общем, насильники ещё раз показали, как они понимают читаемость.
---
...Я работаю антинаучным аферистом...
В общем, насильники ещё раз показали, как они понимают читаемость.
Да, извини, забыл написать p... Жалко, что ты без этого никак не можешь читать код.
Почему все так бояцца скобочной записи? IMHO очень простая вещь.Я не боюсь и даже не буду спорить, что она простая. Но прочитать её занимает просто уйму времени. Потому что кроме скобок других разделителей нет.
Достаточно понимать самые основы Lisp чтобы понять код.Да код-то я в итоге смогу понять. Синтаксис. Но вот разворачивать в уме семантику - это нечто нетривиальное. Плюс ко всему, большая часть задач вовсе не для ЛИСПа. Думаю, что у него вполне ограниченная область применения, в которой он тихонечко рулит. Глобальный спор о том, что мирового господства у ФЯ нет и быть не может. Никогда. Только кто-то никак с этим не смирится.
Насколько я смог осилить эту мешанину из неприличных символов, ни в каком - перемешано со служебным кодом. Этого последнего также слишком много.
потому что она тупая, а не простая.
я понимаю - почему компьютер работает только с ноликами/единичками, или только со скобочками - он тупой и ему это положено.
но я не понимаю, почему такой же тупости должен придерживаться и человек, который априори может работать и с намного более сложными вещами.
Ну и в каком месте здесь происходит преобразование?Просто тебя в детском саду не научили дифферинцировать простые линейные формы.
Насколько я смог осилить эту мешанину из неприличных символов, ни в каком - перемешано со служебным кодом. Этого последнего также слишком много.
Не вижу класса/метода/функции, в названии которой были бы слова, означающие, что именно там определено преобразование.
Не вижу класса/метода/функции, в названии которой были бы слова, означающие, что именно там определено преобразование.Скопируй в ноутпад и переименуй ParseString в ParseStringAndStoreToResultSimplified и AddVariable в AddVariableAndSimplify.
В курсе, что "упростить" и "сохранить" --- это два разных глагола?
А теперь подумай, что лучше отражает действительность
"(define result (simplified conj-form" или твоё "ParseStringAndStoreToResultSimplified".
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
значит, модульность не появилась
> AddVariable в AddVariableAndSimplify
смесь собственно преобразования с несущественными причудами реализации
никакой абстракции данных
где подпрограмма, к которой на входе одна форма, а на выходе - она же после преобразования?
Скажи, почему ты программируешь не на естественном языке?
---
...Я работаю антинаучным аферистом...
потому что компьютер тупой и не понимает естественный язык.
так устроит?
![](/images/graemlins/smile.gif)
using System;
using System.Collections;
namespace KNF
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
public static string[] Expressions = new string[]
{
"A*B+C",
"A+B*C",
"A+B*C+D",
"A*B+C*D",
"(A)",
"A*(B+C)",
"(A+B)*C",
"A",
"^A",
"^A+B",
"^(A+B)",
"A+^B*^C",
"A+B+C+D",
"(A+B)*(^A+B)",
"(A*B)+(^A*B)",
"(A+B)*(^A+B)*(A+^B)"
};
public static string[] Process(string[] expressions)
{
ArrayList results = new ArrayList;
foreach (string ex in expressions)
{
string expression = ex.Trim;
if (expression == "")
continue;
try
{
Expression expr = Parse(expression);
//OutputTree(expr);
Output(expr);
Expression notExpr = new NotExpression(expr);
Expression knfExpr = Knf(notExpr);
//OutputTree(knfExpr);
Expression mulExpr = BinToMultiply(knfExpr);
Expression simExpr = Simplify(mulExpr);
Output(knfExpr);
//OutputTree(knfExpr);
//OutputTree(mulExpr);
Output(simExpr);
Console.WriteLine;
bool isKnf = IsKnf(BinToMultiply(expr;
results.Add(string.Format("{2}!({0}) = {1}", expr, simExpr,
isKnf? " ":"[не кнф] ";
}
catch (Exception exc)
{
results.Add(string.Format("Ошибка - {0}", exc.Message;
}
}
return (string[])results.ToArray(typeof(string;
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
MainForm form = new MainForm;
System.Windows.Forms.Application.Run(form);
//string expression = "!A&B";
}
static bool IsKnf(Expression expr)
{
if (expr is MultiplyExpression)
{
MultiplyExpression mul = (MultiplyExpression)expr;
if (mul.Operation == Operation.And)
{
bool isKnf = true;
foreach (Expression childExpr in mul.Expressions)
{
if (!IsElementaryDnf(childExpr
isKnf = false;
}
return isKnf;
}
}
return IsElementaryDnf(expr);
}
static bool IsElementaryDnf(Expression expr)
{
if (expr is MultiplyExpression)
{
MultiplyExpression mul = (MultiplyExpression)expr;
if (mul.Operation == Operation.Or)
{
bool isDnf = true;
foreach (Expression childExpr in mul.Expressions)
{
if (!IsSimply(childExpr
isDnf = false;
}
return isDnf;
}
}
return IsSimply(expr);
}
static bool IsSimply(Expression expr)
{
if (expr is NotExpression)
{
NotExpression not = (NotExpression)expr;
return IsVariable(not.Expression);
}
return IsVariable(expr);
}
static bool IsVariable(Expression expr)
{
return expr is VariableExpression;
}
static Expression Simplify(Expression expr)
{
if (expr is MultiplyExpression)
{
MultiplyExpression mulExpr = (MultiplyExpression)expr;
if (mulExpr.Operation == Operation.Or)
{
Hashtable posIndex = new Hashtable;
Hashtable negIndex = new Hashtable;
ArrayList other= new ArrayList;
foreach (Expression ex in mulExpr.Expressions)
{
if (ex is VariableExpression)
{
posIndex[VariableExpression)ex).Variable] = ex;
}
else if (ex is NotExpression && NotExpression)ex).Expression is VariableExpression)
{
negIndex[VariableExpressionNotExpression)ex).Expression).Variable] = ex;
}
else
other.Add(ex);
}
ArrayList result = new ArrayList;
foreach (DictionaryEntry entry in posIndex)
{
if (negIndex.ContainsKey(entry.Key
return new VariableExpression("T");
result.Add(entry.Value);
}
result.AddRange(negIndex.Values);
result.AddRange(other);
return new MultiplyExpression(mulExpr.Operation,
(Expression[])result.ToArray(typeof(Expression;
}
if (mulExpr.Operation == Operation.And)
{
//ArrayList expressions = new ArrayList;
Hashtable exprIndex = new Hashtable;
foreach (Expression childEx in mulExpr.Expressions)
{
Expression ex = Simplify(childEx);
if (ex is VariableExpression && VariableExpression)ex).Variable == "T")
continue;
exprIndex[ex.ToString] = ex;
}
if (exprIndex.Count == 0)
return new VariableExpression("T");
return new MultiplyExpression(Operation.And,
(Expression[])new ArrayList(exprIndex.Values).ToArray(typeof(Expression;
}
ArrayList exprs = new ArrayList;
foreach (Expression ex in mulExpr.Expressions)
exprs.Add(Simplify(ex;
return new MultiplyExpression(mulExpr.Operation, (Expression[])exprs.ToArray(typeof(Expression;
}
return expr;
}
// static string Simplify_GetLexem(Expression expr)
// {
// if (expr is NotExpression)
// return Simplify_GetLexemNotExpression)expr).Expression);
// if (expr is VariableExpression)
// return VariableExpression)expr).Variable;
// return null;
// }
static Expression BinToMultiply(Expression expr)
{
if (expr is NotExpression)
return new NotExpression(BinToMultiplyNotExpression)expr).Expression;
if (expr is BinaryExpression)
{
BinaryExpression binExpr = (BinaryExpression)expr;
ArrayList exprs = new ArrayList;
foreach (Expression childExpr in BinToMultiply_Accumulate(binExpr.Operation, binExpr
exprs.Add(BinToMultiply(childExpr;
return new MultiplyExpression(binExpr.Operation,
(Expression[])exprs.ToArray(typeof(Expression;
}
return expr;
}
static ICollection BinToMultiply_Accumulate(string operation, Expression expr)
{
if (expr is BinaryExpression)
{
BinaryExpression binExpr = (BinaryExpression)expr;
if (binExpr.Operation == operation)
{
ArrayList expressions = new ArrayList;
expressions.AddRange(BinToMultiply_Accumulate(operation, binExpr.Left;
expressions.AddRange(BinToMultiply_Accumulate(operation, binExpr.Right;
return expressions;
> Скажи, почему ты программируешь не на естественном языке?Ыыыы. Никто не понимает естественный язык, к сожалению.
потому что компьютер тупой и не понимает естественный язык.
Лисп простой язык, никаких вопросов. Лисп хорошо читаем. Но ЛИСПОВИКИ- полные долбаебы. С вами невозможно нормально общаться.
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
охрененно просто и понятно...
мой моск умер...
![](/images/graemlins/crazy.gif)
> потому что компьютер тупой и не понимает естественный язык.
Как из этого следует потребность изобретения языка с сильно неоднородным, как у сей, синтаксисом?
---
...Я работаю антинаучным аферистом...
ох....еть!А чего ты хочешь? Тут же задачи принципиально разные получаются: в лиспе строкоразбиратель встроенный, то есть преобразуемую ДНФ можно писАть без кавычек.
охрененно просто и понятно...
мой моск умер...
Даркгрей запостил код синтаксического анализатора, который переводит строчку в дерево, потом по-бырому преобразует дерево, потом выводит дерево обратно.
я правильно понимаю, что правильного решение до сих пор нет?
где подпрограмма, к которой на входе одна форма, а на выходе - она же после преобразования?Поищи, она там есть.
public static string[] Process(string[] expressions)
{
ArrayList results = new ArrayList;
foreach (string ex in expressions)
{
string expression = ex.Trim;
if (expression == "")
continue;
try
{
Expression expr = Parse(expression);
Output(expr);
Expression notExpr = new NotExpression(expr);
Expression knfExpr = Knf(notExpr);
Expression mulExpr = BinToMultiply(knfExpr);
Expression simExpr = Simplify(mulExpr);
Output(knfExpr);
Output(simExpr);
Console.WriteLine;
bool isKnf = IsKnf(BinToMultiply(expr;
results.Add(string.Format("{2}!({0}) = {1}", expr, simExpr,
isKnf? " ":"[не кнф] ";
}
catch (Exception exc)
{
results.Add(string.Format("Ошибка - {0}", exc.Message;
}
}
return (string[])results.ToArray(typeof(string;
}
В первом же определении ты в три раза перекрыл пределы по читаемости.
Слабоватая модульность.
Я уж не говорю, что выражения, наподобие
ArrayList results = new ArrayList;
сильно избыточны, а потому создают впечатление,
что ты программируешь на ассемблере.
---
...Я работаю антинаучным аферистом...
но это же пиздец!
---
...Я работаю антинаучным аферистом...
никто не говорил, что будет просто и понятно - это я просто на просьбу -а показать понятные отдельные функции.
кстати, запощенный код решает более общую задачу, чем стоит в треде -
запощенный код - произвольное выражение приводит к упрощенной КНФ
> то есть преобразуемую ДНФ можно писАть без кавычек.
Не вопрос, могу перевести на SML, там нет "встроенного строкоразбирателя."
---
...Я работаю антинаучным аферистом...
А теперь подумай, что лучше отражает действительностьДействительность - первое, процесс получения действительности - второе. Большинство людей мыслят сначала процесс, потом результат. И пишут 1 + 1 = 2, а не = 2 (+ 1 1). А вообще давай ка вернёмся в конструктив. Где твои исправления для сортировки внутри ДФов, чтобы (a b c) и (b c a) считались одинаковыми?
"(define result (simplified conj-form" или твоё "ParseStringAndStoreToResultSimplified".
В первом же определении ты в три раза перекрыл пределы по читаемости.ыыы. А зачем ты к сишарповому коду применяешь какие-то свои пределы по читаемости?
Слабоватая модульность.
Из логических элементов там один цикл, линейная последовательность действий и обработчик ошибок. Разбивать это дальше довольно глупо, ИМХО.
При наличии подсветки, нормальных отступов и пустых строк этод метод читается со скоростью чуть меньшей чем для естественного текста.
В первом же определении ты в три раза перекрыл пределы по читаемости.Да? А вот для меня пределы читаемости вполне перекрывает наличие более трёх закрывающих скобок на одной строке.
функция Simplify, как-то не очень отдельная и понятная (там прямо внутри - какие-то хеш-таблицы сразу возникают, списки массивов и прочие сложности и очень длинная
> И пишут 1 + 1 = 2
Где ты нашёл таких людей?
Давай выйдем на улицу и поспрашиваем, что такое, например, дуб.
Могу заранее объявить, что большинство людей скажут: "Дуб --- это [дерево такое]..."---
а не "вот такое-то и такое-то есть дуб."
---
"Расширь своё сознание!"
процесс - это сначала разбираем, потом упрощаем, потом куда-то сохраняем (а может, мы не хотим сохранять, а сразу на экран хотим!)
в примере контры парсера не было, так что его можно не учитывать, и я на него в других примерах не смотрел
а вот то, что нет выделенной функции упрощения, а вместо неё функция, которая делает всё - недостаток
странно, что ты не понимаешь этого, ты наверное с вмк?
а как ты без словарей собрался упрощать вот такое выражение:
AB + A^B
?
абстракция данных в примере такой сложности уже не помешает
Пределы не мои, а общие.
И относятся они не только к коду.
> Из логических элементов там один цикл, линейная
> последовательность действий и обработчик ошибок.
Из логических элементов достаточно композиции функций.
> При наличии подсветки, нормальных отступов и пустых строк
> этод метод читается со скоростью чуть меньшей чем для естественного текста.
"Читаемость" не сводится к тому, насколько просто читать,
но вашему восприятию это, судя по всему, недоступно.
Читаемость --- это когда можно легко прочитать и воспринять _всё_.
И про подсветку не надо, потому что текст _с_цветом_ ---
это уже совершенно другой текст.
Смотри, например, colorForth Чарльза Мура.
---
...Я работаю антинаучным аферистом...
т.е. правильность кода ты определяешь именно по этому условию?
Я разрешаю считать код общественным достоянием
со всеми вытекающими последствиями.
---
...Я работаю антинаучным аферистом...
Определение ParseString перекрывает пределы читаемости, по меньшей мере, в два раза.КОНТРА, ты вообще что программируешь. Из личного опыта, думаю многие со мной согласятся, для читабельности лучше пусть метод в один экран не влазит, и местами код повторяется, чем у тебя будет куча небольших методов и большая вложенность вызовов.
То же --- с main.
В общем, насильники ещё раз показали, как они понимают читаемость.
Из личного опыта, думаю многие со мной согласятся, для читабельности лучше пусть метод в один экран не влазит, и местами код повторяется, чем у тебя будет куча небольших методов и большая вложенность вызовов.Гы, я не соглашусь.
Потому что читаемость - вещь субъективная. То, что есть миллион сишников, которые согласны с тобой, никак не влияет на существование миллиона лисповиков, которые согласны с Контрой. При этом ваш спор выглядит как спор двух идиотов.
Слабоватая модульность.
Код должен быть короткий, вот такой: perl -e '$?s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'
Коротко и понятно.
КОНТРА, ты вообще что программируешь. Из личного опыта, думаю многие со мной согласятся, для читабельности лучше пусть метод в один экран не влазит, и местами код повторяется, чем у тебя будет куча небольших методов и большая вложенность вызовов.Это обскурантистский взгляд на программирование, истоки которого лежат в повальном использовании императивных языков низкого уровня в прошлом. Сейчас без разницы размер функций, компилятор лучше знает, как их заинлайнить.
То Fj: Да, видимо, недоразвитые мозги, плохо, что на Лиспе не прогаю. Правда, в шахматы без доски играть я тоже не умею.
Имена пробовал давать описательные, а не абы как?
У меня "load" и "load-pref[erence]s" обычно занимаются разным делом,
несмотря на то, что лезут смотреть в одно и то же место.
---
...Я работаю антинаучным аферистом...
Здесь предел перекрывается примерно в 5 раз.
В курсе, что "знак" и "знак алфавита" --- это две большие разницы?
---
"Расширь своё сознание!"
![](/images/graemlins/wink.gif)
У меня "load" и "load-pref[erence]s" обычно занимаются разным делом,Очень описательно. А что будешь делать если отдельный модуль в твоей проге будет несколько больше, чем сабж этого треда?
несмотря на то, что лезут смотреть в одно и то же место.
---
...Я работаю антинаучным аферистом...
Расскажи мне пожалуйста, что такое знак, что такое знак алфавита, и как ты оцениваешь читабельность.
Хоть бы байтов парочку поменял, что лиА это оно? Я просто был совершенно не уверен =)
кстати, кто-то из вас двоих, тебя и Braindead-а, её и спрашивал.
Соответственно --- оценка читаемости.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
Оставить комментарий
ThatsMe
народ, помогите написать эту програмку. или может у кого завалялась. поидее для знающих людей должно быть легко. времени сейчас позарез - разбираться некогда. напишите в приват какое вознаграждение вас устроитзы ДНФ - правильная, если каждая ее элементарная конъюнкция не содержит повторных вхождений одной переменной.