|
||
| Правила | Регистрация | Пользователи | Сообщения за день | | Поиск | | Справка по форуму | Файлообменник | |
|
![]() |
Поиск в этой теме |
![]() |
#1 | |
Как создать маркер c использованием acadЛИСП?
инженер
Оренбург
Регистрация: 18.04.2007
Сообщений: 71
|
||
Просмотров: 4575
|
|
||||
Moderator
LISP, C# (ACAD 200[9,12,13,14]) Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406
|
Попробуй поиск по форуму (слово "автонум*") - может, и найдешь решение.
__________________
Моя библиотека lisp-функций --- Обращение ко мне - на "ты". Все, что сказано - личное мнение. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Спасибо всем, кто откликнулся.
Позволю себе несколько уточнить задачу. Начнем с примера U-1.1.0 здесь U это префикс и он может быть любым, т.е. должна быть возможность задать его в виде набора символов (U, DD, AA, etc); - черточка это дефис, он тоже может быть любым из набора символов '-', '.',' ', либо его может и не быть вовсе; первая единица - это инфикс - просто целое число, которое задается; точка за первой единицей - это разделитель из набора символов '.', '-', '/', ' ', последнее это пробел, присутствует в выражении обязательно. Разелитель и дефис в одном выражении могут быть разными, а могут и совпадать, поэтому это разные синтаксические конструкции; вторая единица - это тоже инфикс; точка за ним это разделитель; инфиксов может быть произвольное количество либо вообще может и не быть; 0 - это постфикс или суффикс, к нему должна применятся операция инкремент, т.е. его значение увеличивается каждый раз на 1 начиная с некоторого заданного значения. В первом свое посте я привел синтаксическую нотацию данного маркера. Это просто описание синтаксиса данного регулярного выражения. Никаких пояснений я не привел в надежде на то, что программисты понимают без дополнительных разъяснений что это такое. Так вот задачу можно перефразировать следующим образом. 1. Необходимо создать генератор регулярного выражения с указанным синтаксисом. 2. Создать парсер, который будет разбирать поданное ему на вход регулярное выражение и, если оно соответствует указанному синтаксису, то принимать его выделяя из него синтаксические конструкции - префикс, инфикс, постфикс и разделители, создавая при этом список значений и принимая его за образец для генерации последующих выражений. Это необходимо для того, что бы при использовании данной команды мне не надо было каждый раз вводить все параметры регулярного выражения, а я мог бы просто ткнуть в существующее регулярное выражение, которое послужит образцом либо задать образец прямо в командной строке, например ВВ1-2. Тем самым избавляясь от необходимости создавать диалоги, иметь кучу опций и прочие неудобства. Кроме того, имея такой парсер можно будет создать команду, которая будет анализировать весь текст, выбирать из него те выражения, которые будут соответствовать данному регулярному выражению, подсчитывать число типов вхождений по префиксу, заполнять спецификацию, да и еще много чего можно придумать. И при этом можно обходиться без блоков, без атрибутов. А если нужны дополнительные данные для заполнения, к примеру спецификации, всегда можно создать обычный текстовый файл, в котором будут хрвнится эти данные и выбирать их от туда по ключу, значением которого выступает префикс регулярного выражения. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Мне нужен только маркер. Но этот маркер должен быть в состоянии сгенерировать и разобрать регулярное выражение указанного типа.
У меня создается такое впечатление, что необходимо еще растоковать что такое регулярное выражение, хотя, все же я надеюсь на то, что господа программисты, обитающие на этом форуме, все же знают что такое регулярное выражение и что такое синтаксис регулярного выражения и как он записывается. Ну и можно обратиться к вики http://ru.wikipedia.org/wiki/%D0%A0%...BD%D0%B8%D1%8F На С или С++ такого рода программа делается со скоростью с которой вы можете набивать текст и никаких трудностей не предствляет. В использовании лиспа у меня очень малый опыт, поэтому я и обратился сюда. И мне нужна программа на лиспе именно в такой постановке - обработка регулярного выражения указанного типа. |
|||
![]() |
|
||||
Помогаю, кому делать нечего. Регистрация: 27.03.2009
Русская деревня
Сообщений: 394
|
Извините, здесь к сожалению не все профессиональные программисты.
Я, например, инженер-механик, работаю конструктором, программироыванием балуюсь по долгу службы. Если Вы профессиональный программист, Вам должно быть легко освоить еще один язык. Классический Lisp достаточно прост для понимания. А разбираться с парсерами грабберами и регулярными выражениями мне уже не по годам. С уважением, E-degtyarev. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Цитата:
![]() |
|||
![]() |
|
||||
Moderator
LISP, C# (ACAD 200[9,12,13,14]) Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406
|
По-моему, именно из-за неопределенности префикса и разделителя нарисовывается некоторая проблема: к примеру, текст 11.1.1 - его как разбирать? Может, я просто не задал префикс? Или он равен "1"?
По идее надо вводить какие-то ограничения. Или я ошибаюсь?
__________________
Моя библиотека lisp-функций --- Обращение ко мне - на "ты". Все, что сказано - личное мнение. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Да, я не расписал достаточно подробно префикс.
Префикс это текст. А текст это буква за которой следуют буквы. В этом случае разночтений не возникнет потому как за префиксом следует дефис, это либо '-', либо '.', либо ничего, либо пробел. И даже в случае "ничего" следующим символом будет цифра (и еще цифры). И если за ней следует точка или другой разделитель, то это инфикс, которого может быть несколько. Если разделителя нет, то это однозначно постфикс. Тотже синтаксис, но другими словами и более сжато [a-zA-Z]+[-|\.|' ']?([0-9]+[\.|-])*[0-9]+ где ? это один из указанных символов, которого может и не быть + это один или более * это 0 или более под данный синтаксис попадают выражения DD-1, DD-2, DD1, DD2 A-1.1.2, А-1.2.5 К1.2, К1.3 Е-1.12.41.1000.100 и т.д DD, A, K, E это префиксы. И префикс по условию присутствует всегда. Привожу исправленный синтаксис. Код:
Последний раз редактировалось Serge_BN, 07.09.2009 в 11:31. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
О, это чудо! Это работает! И даже, еще получаем остаток.
Просто замечательно. По ходу дела у меня есть вопросы. Функция wsmatch принимает в качестве параметра некое выражение. В хелпе я не нашел правила и синтаксис этих выражений. В частности символы @, #, где можно найти подробнее об этом? Почему написано '. и '/ я догадываюсь, но, опять-таки, где это можно прочитать? И следующее, если вас не затруднит, обратная задача. Сгенерировать по заданному шаблону выражение с инкрементом постфикса. Пожалуйста. ![]() |
|||
![]() |
|
||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
|
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Спасибо за дополнительную инфу.
Пытаюсь понять как это работает и заодно начинаю осознавать, что лисп обладает очень большой мощьностью при минимальном количестве выразительных средств. Интересно, как бы можно было создать на нем некий шаблон конечного автомата со стеком для обработки контекстно свободных грамматик? Но это так, пока теория. ![]() Я впишу в код свои комменты. Если что не правильно, поправьте, плз. Код:
Не понятно вот что, зачем нужны операции ' и как работает mapcar в паре с apply. И в завершении этого цикла необходим некий драйвер для использования написанных функций. т.е. вызывается команда, например mmark (make marker), она запрашивает образец, который можно ввести в командной строке либо указать мышкой в существующий на чертеже, после чего команда запрашивает точку вставки сформированного маркера, потом следующую точку и т.д. пока не будет нажата клавиша Esc. либо правая кнопка мыши ![]() Замечание. Протестировал функцию (test "21A-1.2.10") и пр. с намеренными "неправильными" выражениями. Обнаружил побочный эффект. 21A-1.2.10 попало в остаток??? и естественно инкремент не может быть применен. Т.е. получается, что все выражения попадают под эту грамматику. Это не правильно. Функция, все-таки должна вернуть либо nil либо пустой список (что удобнее и правильнее??) в случае, если тестируемое выражение не удовлетворяет шаблону регулярного выражения. Последний раз редактировалось Serge_BN, 09.09.2009 в 08:50. |
|||
![]() |
|
|||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
Цитата:
Здесь Код:
Код:
Цитата:
Код:
Код:
Цитата:
Код:
Возвращает Т для "правильного" списка: Код:
Цитата:
Последний раз редактировалось CB, 09.09.2009 в 11:54. |
||||
![]() |
|
||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
Цитата:
PS: Естественно функция test, сделанная раньше, должна быть загружена. Код:
Последний раз редактировалось CB, 10.09.2009 в 16:49. |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Команду протестировал. Работает нормально и по Esc выходит в пустом чертеже. Огромное спасибо. Получилось то, что надо. Уже применяю в работе.
Некоторые строки мне не понятны Код:
Код:
![]() А из этого что-либо мне видится следующее. Сейчас имеется функция test, я бы обозвал ее, все-таки mparse, потому как она выполняет именно разбор выражения. Далее, есть небольшой довесок к ней, который определяет принадлежит ли данное выражение указанной грамматике. Этот довесок можно оформить в виде функции mtest, котороя будет принимать список от mparse и возвращать Т если выражение соответствует грамматике М (маркер). Таким образом применяя эти две функции к множеству всех выражений мы можем получить подмножество всех маркеров в данном чертеже. И есть, надо только оформить в виде функции, генератор регулярного вражения удовлетворяющего грамматике М, обзавем ее mgen (marker generator). Но само по себе множество всех маркеров не очень интересно. Хотелось бы иметь функцию mfind, которая была бы способна находить среди множества всех маркеров маркер удовлетворяющий заданному условию. Например, найти все маркеры с прeфиксом R, или BTH. Префикс можно задать списком (R), (К, ВТН, ВТМ) и т.п. Кроме того, можно было бы критерием поиска задать поиск маркеров с заданными префиксом и инфиксом, ну и для полноты можно задать префикс, инфикс и потфикс, что бы найти конкретный маркер. Возможно задать не полный префикс или инфикс, например (префикс ВТН инфикс 2.*) или (префикс ВТ*)(инфикс 2.*) Найденные маркеры можно размещать в списке, который будет пуст, если ничего не найдено. Имея такой список можно довольно легко подсчитать количество вхождений всех маркеров заданного типа, например количество R, C, D. Там где есть поиск, может быть и замена. Заменить префикс, заменить инфикс для указанного префикса. Ну и конечно функция delete. На основе этого можно создать довольно мощный инструмент для работы с текстовыми данными в чертеже, и областью применения которого могут быть чертежи из разделов СС, автоматизации, ЭО и т.п. Эх как меня занесло далеко. Но, вообще, меня интересуют сейчас возможности лисп по обработке контекстно свободных грамматик. Потому как регулярные выражения обладают наименьшей мощностью из всех типов грамматик, хотя и довольно часто применяются на практике. Но для реализации КС-грамматики необходим автомат со стеком. Как, интересно, обстоят дела в лиспе со стеком? Как его тут можно реализовать? Да и автомат как реализовать мне не ясно? Но это уже от недостаточного знания лиспа. Блн, последний абзац надо воспринимать как свободные блуждания в туманной области. Ну что же. Первый цикл завершен успешно. Приступим к следующему. ![]() Дополнение. Для полноты поиска надо еще сделать поиск первого маркера и поиск последнего маркера. Причем P1.1.5>P1.1.2, P1.3.1>P1.2.100, т.е. при сравнении учитывать инфиксы поразрядно, а потом сравнивать постфикс. Попробую сконструировать функцию mfind_last. Как всегда m - приставка, означающая функцию для работы с маркерами, find_last - наити последний (с наибольшим номером) маркер Код:
Точка в шаблоне говорит о том что это инфикс а не постфикс. Тогда функция mfind_last будет выглядеть так Код:
Далее. На основе фильтра mf можно создать функцию mcount для подсчета количества элементов по шаблону, например (mcount "DD"), (mcount "BTH"), (mcount "RJ*"), (mcount "BTM1.2.*) - все BTM в первом подъезде на втором этаже или от ЩА2, кто как там обозначает. Код:
На основе функции mfind_last можно создать функцию madd.template, которая будет находить последний (с наибольшим номером) элемент и генерировать новый маркер (функция mgen). Тем самым будет гарантировано, что разные элементы имеют разные маркеры. У функции mgen должен быть параметр - 0 - не изменять постфикс; - 1 (или +) - инкремент постфикса; - 2 (или -) - декремент постфикса. - по умолчанию действует 1 (или +), т.е. инкремент. Блоки. Маркер может быть привязан к атрибуту блока. При вставке блока будет вызываться mgen, генерируя новый маркер. Ну обработка блоков с маркерами и прочими атрибутами это уже отдельная песня. Ее споем чуть по позже. Сейчас надо определить функции замены и удаления маркера. Код:
Последний раз редактировалось Serge_BN, 11.09.2009 в 11:25. |
|||
![]() |
|
||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
Практически все, что написано выше достаточно легко реализуется в LISP'е. Просто для начала сильно много информации. Начнем с mfind:
Код:
С сортировкой не совсем ясно... Сортируем по убыванию Код:
|
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Код:
![]() Вот здесь будем поступать как изложено в правилах для функции >. Тогда вот это Код:
Примеры. К1.2.100 < К1.3.0, K1.2.100 < K1.2.101, K1.2.100 < K2.1.100 Получается, что вес инфикса тем больше чем левее он записан. Код:
Присмотрелся вот к этому Код:
И еще, по инфиксам. 1.2.3. - это не один большой инфикс, это, все-таки три разных инфикса 1, 2, 3. Где наибольшим весом обладает 1( первый инфикс), а инфикс 3 обладает наименьшим весом из приведенных 1.2.3. Последний раз редактировалось Serge_BN, 11.09.2009 в 14:24. |
|||
![]() |
|
||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
Цитата:
Дальше этот набор нужно уточнить на соответствие грамматике, причем именно на этом этапе необходимо определиться как задавать маску выбора. Ведь наверняка придется искать маркеры с конкретным "префиксом" и "инфиксом", чтобы менять "постфикс". Что касается сортировки, тут все ясно. Где-то на этом форуме мне попадался код, который выложил или VVA или kpblc для корректрой сортировки текста с цифрами. Я попытался ускорить его, но по моему не совсем удачно. Если дадут ссылку на тот лисп, можно его использовать, а пока привожу свой вариант (алгоритм тот же): Код:
Цитата:
|
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Цитата:
Цитата:
Но, задача состоит в том чтобы найти первый/последний элемент и для этого не всегда надо делать сортировку. Рассмотрим несколько подробнее то, среди чего нам надо найти первый/последний элемент. 1. Обзовем эту функцию mfind_last, mfind_first - найти последний, найти первый. Это для того, чтобы было однозначно ясно что мы делаем. 2. Передавать этим функциям будем список строк, где каждая строка имеет вид: префикс дефис? (инфикс разделитель)* постфикс Где-то там перед вызовом mfind_last у нас имеется список всех маркеров. Из них надо сделать список маркеров только тех, у которых префикс равен образцу. Тогда mfind_last фильтрацией маркеров заниматься уже не будет. И, теперь префикс в сортировке может и не участвовать. Мы его просто будем игнорировать. 3. Далее идет старший по весу инфикс. Поэтому мы можем отбросить все маркеры, у которых старший по весу инфикс меньше наибольшего в последовательности. Алгоритм простой. Берем первый в последовательности старший инфикс и сравниваем его со следующим маркером. Если следующий больше текущего, то в качестве образца (текущего) берем его, иначе оставляем текущий. Т.о. мы найдем наибольший старший инфикс. После чего создадим новый список маркеров, у которых старший инфикс равен наибольшему. Все остальные маркеры рассматривать не имеет смысла. 4. К новому списку применяем п. 3. 5. До тех пор, пока не дойдем до постфикса и к постфиксу применим опять п.3 и в результате получим маркер с наибольшим весом, или последний в последовательности. В результате мы получим список с одним единственным искомым наибольшим элементом. 6. Для mfind_first делает все так же, только ищем наименьший. Теперь вернемся к первой задаче. Как задавать маску для поиска? Думаю, что это не сложно. Префикс у нас отвечает за тип маркера (элемента) и задается либо явным указанием префикса DD*, BTH*, BTK* и т.д. либо его можно задать *, тогда программа должна сформировать столько списков маркеров, сколько типов префиксов найдет в чертеже. Соответственно и инфиксы - DD1.*, DD1.2* и т.д до того уровня детализации, который мне необходим, вплодь до DD1.2.7 - конкретный маркер. Программа должна находить все, что попадает в шаблон и возвращать упорядоченный по возрастанию список маркеров. Собственно в работе все это не очень-то и нужно. Данная задача возникает из необходимости иметь непрерывные последовательности маркеров. А в работе возникают ситуации, когда в последовательности маркера имеются дыры либо дубликаты. Эти случаи необходимо распознавать и приводить к упорядоченной непрерывной последовательности. Под непрерывной последовательностью я понимаю такую последовательность маркеров, которая пронумерована без дыр и дубликатов с шагом 1. Может возникнуть задача объединить несколько наборов маркеров в одну последовательность. например, DD1.2* DD2.1 в последовательность DD1.0.*. Но сдесь так же можно задать список последовательностей и список содержащий целевой маркер. (src1 src2)(dst). |
|||
![]() |
|
||||
Конструирование в области нефтеразведки Регистрация: 10.02.2006
Гомель
Сообщений: 321
|
Да это все все ясно, не понято что делать в таком случае:
Пусть на чертеже есть маркеры P-1.1 P-1.5 и P-1.1.7 1. Маска поиска - P-1.*# 2. Все три маркера попали в набор 3. С первыми двумя понятно - P-1.5 маркер с наибольшим весом Вопрос - что делать с третьим, ведь это маркер совершенно другого типа??? |
|||
![]() |
|
||||
инженер Регистрация: 18.04.2007
Оренбург
Сообщений: 71
|
Цитата:
1. Обычно с схемах автоматизации, СС, СКС таких ситуаций не встречается. Не встречается потому, что маркировкой управляет инженер-конструктор и он прекрасно соображает, что если устройства будут промаркированы таким образом, то будут весьма плачевные последствия. 2. Если же, все-таки такая ситуация встретилась. Можно делать отсев по количеству инфиксов, т.е. Р-1.2, Р-1.1.2 и Р-1.1.1.2 это будут разные маркеры и они не должны попасть в один набор. А маску для отбора можно будет задавать так Р?1.#+., где Р- это префикс, ? - возможный символ дефиса из набора '-','.',' ','', 1 - значение старшего инфикса, . - разделитель, #+ -инфикс, любое количество непрерывных цифр, . - разделитель. Вот последний разделитель как раз и скажет что надо производить отбор только тех маркеров, у которых только два инфикса. Другой пример. Р-#+.#+. это почти тоже, что и предыдущий маркер, только в наборе будут присутствовать маркеры с любым старшим инфиксом. Если же убрать последнюю точку, то в набор попадут какие попало маркеры Р-1.2, Р-1.2.3.4.100 и все что угодно с любым хвостом. Поэтому и присутствуют в маркере синтаксические конструкции - разделитель и инфикс. Для того, что бы каждый раз знать, что вот здесь закончился инфикс, или, другими словами, это самый младший инфикс, за которым следует постфикс. Это и есть решение данной проблемы. Реализация может быть разной, например, фильтр по количеству инфиксов. Может встретиться маркер типа D1, D2, т.е. в нем отсутствует инфикс. Его шаблон может быть D#+ без точек, это значит префикс за которым непосредственно следует постфикс. В конструкции P-1.2.#+ символы #+ означают тоже постфикс, который есть целое число. Примечание. Везде, где я пишу #+, подразумевается # это цифра (0|1|2|3|4|5|6|7|8|9), + говорит о том что цифр может хотя бы одна и более. * - говорит о том, что в контексте #* цифр может и не быть, либо быть сколько угодно. Хотя сама по себе * означает вообще все что угодно. В доказательсто того, что это будет работать можно было бы вывести несколько теорем о свойствах маркеров такого типа, но я думаю, что приведенных рассуждений достаточно. Хотя, можно подумать и над математикой в смысле вывода свойств маркеров, формулировки и доказательству теорем и т.д. Тем более, если еще вспомнить, что программирование это в первую очередь математика а потом уже кодирование. Последний раз редактировалось Serge_BN, 15.09.2009 в 09:24. |
|||
![]() |
![]() |
|
|
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Как в Акад 2006 программно создать подшивку с заданным набор | kp+ | Программирование | 4 | 16.03.2009 23:23 |
Как создать функцию с необязательным вводом параметра | Krieger | Программирование | 2 | 14.02.2009 11:49 |
SW подскажите как создать радиальное отверстие | Chives | SolidWorks | 23 | 17.12.2008 00:54 |
Как создать виртуальный принтер | Владислав Кулигин | Компьютерная и бытовая техника, электроника и инструмент | 4 | 03.01.2008 17:54 |
Юмор 2007 | Огурец | Разное | 1172 | 29.12.2007 11:16 |