LISP: функция Nth наоборот
| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > LISP: функция Nth наоборот

LISP: функция Nth наоборот

Ответ
Поиск в этой теме
Непрочитано 18.03.2013, 19:02 #1
LISP: функция Nth наоборот
WhiteShark
 
Регистрация: 30.03.2012
Сообщений: 101

Есть ли красивая реализация у кого нибудь функции которая возвращает весь список только без элемента за номером N?
Просмотров: 6311
 
Непрочитано 18.03.2013, 19:19
#2
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


А самому подумать?
gomer вне форума  
 
Автор темы   Непрочитано 18.03.2013, 19:25
#3
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Да я то сделал вот такую... но мне не нравится
Код:
[Выделить все]
 (defun invNth (lst N / k newlst)
  (setq k 0)
  (if lst
    (progn
      (while lst
	(if (/= k N)
	  (setq newlst (append newlst (car lst)))
	  )
	(setq k (1+ k))
	(setq lst (cdr lst))
      )
    newlst
    )
  )
)
WhiteShark вне форума  
 
Непрочитано 18.03.2013, 19:35
#4
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


забыли list
Код:
[Выделить все]
 (setq newlst (append newlst (list (car lst))))
вообще рекурсивно это гораздо проще решается
gomer вне форума  
 
Автор темы   Непрочитано 18.03.2013, 19:43
#5
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Ну я вот и чувствую что можно лучше.. но не могу сложить в кучу. Не подскажите как рекурсивно?
WhiteShark вне форума  
 
Непрочитано 18.03.2013, 19:48
#6
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Код:
[Выделить все]
 (defun butnth (i lst)
  (if (zerop i)
    (cdr lst)
    (cons (car lst)
	  (butnth
	    (1- i)
	    (cdr lst)
	  )
    )
  )
)
Настоятельно рекомендую начать изучать рекурсию
ну и еще вопрос: нафига это надо?
gomer вне форума  
 
Автор темы   Непрочитано 18.03.2013, 22:31
#7
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Спрашивали? Отвечаем :-)

Стоит задача по списку вида ((x1 y1 z1) (x2 y2 z2) ... ... ), содержащему наборы координат концов линий, определить образуют ли они замкнутый контур.
Ну и вообще, в принципе, как же получать список без какого то элемента? (vl-remove-if не подходит из за того что элемент не уникальный)
WhiteShark вне форума  
 
Непрочитано 18.03.2013, 23:03
#8
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,996


Looking for a faster version of delete_nth, insert_nth and switch_nth
Парочка функций из этой темы (там требутся регистрация)
http://forum.dwg.ru/showthread.php?p=676403#post676403
http://forum.dwg.ru/showthread.php?t=80369
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Непрочитано 19.03.2013, 00:14
#9
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от WhiteShark Посмотреть сообщение
Стоит задача по списку вида ((x1 y1 z1) (x2 y2 z2) ... ... )
Это список точек, а не отрезков
gomer вне форума  
 
Автор темы   Непрочитано 19.03.2013, 01:50
#10
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Уважаемый gomer, я именно так ((x1 y1 z1) (x2 y2 z2) ... ... ) написал, чтоб было понятно, что каждый отрезок задан координатой начала и конца, идущими подряд. Задача проверить контур на незамкнутость весьма проста: список не будет содержать по два раза одни и те же координаты или будет нечетное количество элементов. Я пытаюсь решить задачу сложнее: попытаться составить из такого списка замкнутый контур (то есть еще и упорядочить его). Для чего нужно попробовать выстроить из данного набора координат цепочку, где каждая конечная координата одного отрезка соседствует с такой же начальной координатой следующего (ну а голова равна хвосту). Если цепочка выстроится, то контур замкнутый.

VVA, как всегда спасибо!

Последний раз редактировалось WhiteShark, 19.03.2013 в 01:57. Причина: поправил
WhiteShark вне форума  
 
Непрочитано 20.03.2013, 17:50
#11
Sleekka

-
 
Регистрация: 24.07.2005
Москва
Сообщений: 1,335


Цитата:
Есть ли красивая реализация у кого нибудь функции которая возвращает весь список только без элемента за номером N?
Красивая говоришь...
Может и не супер красивая, но зато быстрая.

Код:
[Выделить все]
 (defun remove-i (i lst)
      (setq i (1+ i))
      (vl-remove-if '(lambda (x) (zerop (setq i (1- i)))) lst)
    )
считается что первый список в листе - номер 0.
Sleekka вне форума  
 
Непрочитано 20.03.2013, 18:31
#12
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Рекурсивненько тоже можно
Код:
[Выделить все]
;;fixo () 2013 * all rights released
(defun remove-by-index	 (lst idx)
  (if (car lst)
    (cons (vl-remove-if
	    '(lambda (a) (= (vl-position a (car lst)) idx))
	    (car lst))
	  (remove-by-index (cdr lst) idx))))
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 20.03.2013, 22:51
#13
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Спасибо спасибо! С Nth уже понятно )
Намного более нетривиальная задачка - исходная (та, что в 10-ом посте). Если у кого мысли есть - скрывайте!

Если прям на пальцах то так: есть список

( (18 7 0) (23 59 0) (34 14 0) (18 7 0) (95 13 0) (34 14 0) (23 59 0) (95 13 0) )

надо получить из него

( (23 59 0) (95 13 0) (95 13 0) (34 14 0) (34 14 0) (18 7 0) (18 7 0) (23 59 0) )

Последний раз редактировалось WhiteShark, 20.03.2013 в 23:12.
WhiteShark вне форума  
 
Непрочитано 21.03.2013, 01:17
#14
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Цитата:
Сообщение от WhiteShark Посмотреть сообщение
Если у кого мысли есть - скрывайте!
Поищи chain selection не помню где, склерозьм
Олег (jr.) вне форума  
 
Непрочитано 21.03.2013, 02:17
#15
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


см. #2
gomer вне форума  
 
Непрочитано 21.03.2013, 13:00
#16
CB

Конструирование в области нефтеразведки
 
Регистрация: 10.02.2006
Гомель
Сообщений: 321


Цитата:
Если прям на пальцах то так: есть список
( (18 7 0) (23 59 0) (34 14 0) (18 7 0) (95 13 0) (34 14 0) (23 59 0) (95 13 0) )
надо получить из него
( (23 59 0) (95 13 0) (95 13 0) (34 14 0) (34 14 0) (18 7 0) (18 7 0) (23 59 0) )
А почему не так?
Код:
[Выделить все]
 '( (23 59 0) (34 14 0) (34 14 0) (18 7 0) (18 7 0) (95 13 0) (95 13 0) (23 59 0)  ))
 '( (34 14 0) (18 7 0) (18 7 0) (95 13 0) (95 13 0) (23 59 0) (23 59 0) (34 14 0)))
 '( (18 7 0) (95 13 0) (95 13 0) (34 14 0) (34 14 0) (23 59 0) (23 59 0) (18 7 0) ))
 '( (18 7 0) (34 14 0) (34 14 0) (95 13 0) (95 13 0) (23 59 0) (23 59 0) (18 7 0) ))
__________________
Никогда не спорьте с дураками - они опустят Вас до своего уровня и победят за счет опыта
CB вне форума  
 
Автор темы   Непрочитано 21.03.2013, 14:07
#17
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Олег (jr.), спасибо, попробую найти!
gomer, спасибо, я уже почти придумал ) просто есть непреодолимая тяга сделать всё так же красиво как вы
CB, первый, третий и четвертый списки неправильные потому, что в исходном списке элементы (подсписки) 1и2, 3и4 и т.д. образуют неразрывные пары, т.к. описывают начало и конец одного отрезка
WhiteShark вне форума  
 
Непрочитано 21.03.2013, 17:32
#18
Sleekka

-
 
Регистрация: 24.07.2005
Москва
Сообщений: 1,335


WhiteShark, ничего не понятно какой тебе алгоритм нужен?

http://algolist.manual.ru/maths/geom...ull/graham.php
этот что-ли?
Sleekka вне форума  
 
Непрочитано 21.03.2013, 18:22
#19
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,996


Цитата:
Сообщение от Олег (jr.) Посмотреть сообщение
Поищи chain selection не помню где, склерозьм
Пробы пера были здесь
http://forum.dwg.ru/showthread.php?p=134515#post134515
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Автор темы   Непрочитано 22.03.2013, 00:47
#20
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Чтоб не заругали модераторы, спрошу прямо тут. Почему моя функция как то странно работает? Это сдвиг списка влево до тех пор пока не встретится передаваемый аргумент. (ну случай что он не встретится вообще пока не знаю как учесть получше)
Код:
[Выделить все]
 
(defun lshift (elem lst  /)
       (cond ((= (car lst) elem) lst)
               (T (lshift (append  (cdr lst) (list (car lst)) )  elem))
       )
)
(lshift 3 '(1 2 3 4)) возвращает как и задумывалось (3 4 1 2), но

(lshift '(3) '((1) (2) (3) (4))) делает stack overflow
Подскажите в чем дело?
WhiteShark вне форума  
 
Непрочитано 22.03.2013, 02:32
#21
Vov.Ka


 
Регистрация: 21.07.2008
Луцьк
Сообщений: 179


..
Цитата:
Сообщение от WhiteShark Посмотреть сообщение
Подскажите в чем дело?
=
Vov.Ka вне форума  
 
Непрочитано 22.03.2013, 03:19
#22
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


потому что #2!!!!!!!!! WhiteShark, включи уже мозг, мало того что у тебя же аргументы гуляют как по тверской, так еще и и сравниваешь атом со списком и циклишь по заведомо ложному условию! Nil тебе вместо якоря
gomer вне форума  
 
Непрочитано 22.03.2013, 09:04
#23
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,426


Пошагово попробуй выполнить код.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 22.03.2013, 10:56
#24
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Так в том то и дело, что я трейсил код. И своими глазами видел, что почему то (3) не равно (3).
Спасибо, с "equal" вместо "=" работает как задумывалось
А аргументы загуляли по тверской когда красоту наводил и местами переставил

Ну вот собстно руки и дошли... до пилотного варианта. Если кому то интересно, функция проверяет по координатам отрезков можно ли из них составить замкнутый контур (вспомогательная функция делает такой список координат из выбранного набора). Пока всё работает с допущением о том, что отрезки рисовались последовательно (т.е. грубо говоря все или по часовой стрелке или против).

Код:
[Выделить все]
 
(defun WS-SSetToPolygon (sset / lst head tail)
  (if sset
    (progn
      (setq lst (WS-GetLinesEnds sset))
      (if (not (vl-remove-if (function (lambda (e) (vl-position e (cdr (member e lst))))) lst))
        (progn
          (setq head (list (car lst) (cadr lst)))
          (setq tail (cddr lst))
          (repeat (- (/ (length lst) 2) 1)
            (setq tail (WS-lshift (car (reverse head)) tail))
            (setq head (append head (list (car tail)) (list (cadr tail)) ))
            (setq tail (cddr tail))        
          )
          head
        )
      )
    )
  )
)

;------------------------------------------------------------------

(defun WS-GetLinesEnds (sset / k XYZ1 XYZ2 XYZlist)
  (cond (sset
  (setq k 0)
  (setq XYZlist nil)
  (repeat (sslength sset)
    (setq ent (ssname sset k))
    (setq k (1+ k))
    (if (= "LINE" (cdr (assoc 0 (entget ent))))
      (progn
        (setq XYZ1 (cdr (assoc 10 (entget ent))))
        (setq XYZ2 (cdr (assoc 11 (entget ent))))
        (setq XYZlist (append (list XYZ1 XYZ2) XYZlist))
      )
      nil
    )
  )
  XYZlist)
  (T nil)
  )
)

;----------------------------------------------------------------

(defun WS-lshift (elem lst /)
       (cond ((equal (car lst) elem) lst)
         (T (WS-lshift  elem (append (cdr lst) (list (car lst))) ))
       )
)

Последний раз редактировалось WhiteShark, 23.03.2013 в 01:25.
WhiteShark вне форума  
 
Непрочитано 23.03.2013, 21:42
#25
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Не работает если линии расположены не по одному направлению
Посмотри хороший пример от VVA:

Код:
[Выделить все]
;;* Author VVA
;;* Утилита объединения набора линий в полилинию*
;;* Должно выбирать все (сначала и с конца) найденные примитивы в цепочку)
;;------------------------------------------------
;;Алгоритм взят у ChainSelect Fatty
;;http://www.cadforyou.spb.ru/index.php?current_section=section_programs_page
;;Доработан до понимания ARC,PLINE,LINE
;;Для выполнения необходимо указать только точку
;; pt - Список точек для выбранных примитивов в МСК !!!
;; fuzz - точность
;;Возвращает список vla объектов
(defun ChainSelectFromAny1 ( pt obj fuzz / chain_list couple line_lst ln ss cycl line_list )
(vl-load-com)
(if (setq ss (ssget "_I")
          ss nil
          ss (ssget "_X" '((0 . "ARC,LINE,*POLYLINE")))
    ) ;_ end of setq
  (progn
    (setq line_lst  (mapcar 'vlax-ename->vla-object
                             (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
                     ) ;_ end of mapcar
          chain_list nil
          chain_list (list obj)
    ) ;_ end of setq
    (setq line_lst (vl-remove-if
                      '(lambda (x)
                         (eq "AcDb3dPolyline" (vla-get-objectname x))
                       ) ;_ end of lambda
                      line_lst
                    ) ;_ end of vl-remove-if
    ) ;_ end of setq
     (setq line_lst (vl-remove obj line_lst))
    (setq cycl 0 line_list line_lst)
    (foreach pt_Pattern pt
     (while
        (setq couple
               (vl-remove-if-not
                 (function (lambda (x)
                             ;; значение допуска 0.01 можно изменить по ситуации
                             ;; в зависимости от единиц черчения : 
                             (or (equal (vlax-curve-getStartPoint x)
                                        pt_Pattern
                                        fuzz      ;<--- допуск 
                                 ) ;_ end of equal
                                 (equal (vlax-curve-getEndPoint x)
                                        pt_Pattern
                                        fuzz     ;<--- допуск 
                                 ) ;_ end of equal
                             ) ;_ end of or
                           ) ;_ end of lambda
                 ) ;_ end of function
                 line_list
               ) ;_ end of vl-remove-if-not
        ) ;_ end of setq
       (grtext -1 (strcat "Обработка. Цикл - " (itoa (setq cycl (1+ cycl)))))
       (if couple
           (progn
             (setq chain_list (cons (car couple) chain_list))
             (setq ln (car chain_list))
             (setq line_list (vl-remove ln line_list))
             (setq pt_Pattern (if (equal pt_Pattern (vlax-curve-getStartPoint ln) 1e-6)
                                (vlax-curve-getEndPoint ln)
                                (vlax-curve-getStartPoint ln)
                                )
                   )
           ) ;_ end of progn
         ) ;_ end of if
      )
   )
  ) ;_ end of progn
) ;_ end of if
chain_list
)
;;;Ф-ция переводит градусы в радианы
;;;( pl:DTR a)
(defun pl:DTR (a)(* pi (/ a 180.0)))
;;;---------------------------------------------
;;;Ф-ция переводит радианы в градусы
;;;( R2D a)
(defun pl:RTD (a)(/ (* a 180.0) pi))
(defun mip_grdraw ( ptdraw ang color / pt1 pt2 )
  (setq pt1 (polar ptdraw (+ ang (pl:DTR 135)) (* 0.05 (getvar "VIEWSIZE"))))
  (setq pt2 (polar ptdraw (+ ang (pl:DTR 225)) (* 0.05 (getvar "VIEWSIZE"))))
  (grvecs (list color pt1 ptdraw ptdraw pt2))
  )
(defun _vxgrdraw ( ptdraw color / ang pt11 pt12 pt21 pt22 len )
  (setq len (* 0.03 (getvar "VIEWSIZE"))
       ang 0
       pt11 (polar ptdraw (+ ang (pl:DTR 225)) len)
       pt12 (polar ptdraw (+ ang (pl:DTR 45)) len)
       pt21 (polar ptdraw (+ ang (pl:DTR 315)) len)
       pt22 (polar ptdraw (+ ang (pl:DTR 135)) len))
  (grvecs (list color pt11 pt12 pt21 pt22))
  )
;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
 
(defun C:ChainSelect ( / ss en fuzz obj pt pt1 len dst ptother what lst *error*)
 (vl-load-com)
 (defun *error* (msg)(princ msg)
   (vla-EndUndoMark(vla-get-ActiveDocument (vlax-get-acad-object)))(princ))
 (vla-StartUndoMark(vla-get-ActiveDocument (vlax-get-acad-object))) 
 (setvar "cmdecho" 0) 
 (if (and (setq en (entsel "\nВыбрать линию в цепи :"))
          (wcmatch (cdr(assoc 0 (entget (car en)))) "ARC,LINE,*POLYLINE,SPLINE")
          (setq obj (vlax-ename->vla-object (car en)))
          (cond ((=(vla-get-ObjectName obj) "AcDb3dPolyline")
                 (princ "\n3d Полилиния. ") nil)
                ((and (=(vla-get-ObjectName obj) "AcDbLine")
                      (not(equal (last(cdr(assoc 10 (entget(car en)))))
                             (last(cdr(assoc 11 (entget(car en)))))
                             1e-9
                             )
                          )
                      )
                 (princ "\nОтрезок. Разные координаты Z. ") nil)
                ((and (=(vla-get-ObjectName obj) "AcDb2dPolyline")
                     (member (vla-get-Type obj) '(1 2 3)))
                 (princ "\n2d сглаженная полилиния. ") nil)
                (t t)
                )
          )
 (progn
 (setq pt1 (trans (cadr en) 1 0))  
 (setq pt1 (vlax-curve-getclosestpointto obj pt1))
 (setq len (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)))
 (setq dst (vlax-curve-getDistAtPoint obj pt1))
 (if (<= dst (- len dst))
   (setq pt (vlax-curve-getStartPoint obj) ptother (vlax-curve-getEndPoint obj))
   (setq pt (vlax-curve-getEndPoint obj) ptother (vlax-curve-getStartPoint obj))
   )
  (_vxgrdraw (trans pt 0 1) -1)
(mip_grdraw (trans pt1 0 1)
  (angle (trans pt1 0 1)(trans pt 0 1)) 1)
 (initget "Ближайшая Противоположная Обе Nearest Opposite Both _Nearest Opposite Both Nearest Opposite Both")
 (princ "\nСтроить цепочку от ближайшей точки [Ближайшая/Противоположная/Обе] <Обе>:")
 (setq what (getkword))
 (cond ((= what "Opposite")
        (setq pt (list ptother))
        (vl-cmdf "_.redrawall")
        (_vxgrdraw (trans ptother 0 1) -1)
        (mip_grdraw (trans pt1 0 1)
  (angle (trans pt1 0 1)(trans ptother 0 1)) 1)
        )
       ((= what "Nearest") (setq pt (list pt)))
       (t (setq pt (list pt ptother)))
       )
 
 (if (null *FUZZ*)(setq *FUZZ* 0.0))
 (princ "\nЗначение допуска < ")(princ *FUZZ*)(princ " >: ")
 (if (null (setq fuzz  (getdist)))
   (setq fuzz *FUZZ*))
 (setq *FUZZ* fuzz)
 (vl-cmdf "_.redrawall")
 (setq ss nil ss (ssadd (car en)))
       
 (setq lst (ChainSelectFromAny1 pt obj (+ fuzz 1e-6)))
 (foreach item lst
      (ssadd (vlax-vla-object->ename item) ss)
    )
 (sssetfirst nil ss)
  )
   (princ " Нужно указать LINE, POLYLINE, ARC или SPLINE")
   )
 (vla-EndUndoMark(vla-get-ActiveDocument(vlax-get-acad-object)))
  (princ)
  )
(princ "\nНаберите ChainSelect  в командной строке")
(princ)

;;(C:ChainSelect)
Олег (jr.) вне форума  
 
Непрочитано 24.03.2013, 11:11
#26
Sleekka

-
 
Регистрация: 24.07.2005
Москва
Сообщений: 1,335


Значит WhiteShark как тебе что-то надо, помогите! научите! как тебя попросил в личке - хрен тебе! Давай досвиданья!
Sleekka вне форума  
 
Автор темы   Непрочитано 24.03.2013, 13:22
#27
WhiteShark


 
Регистрация: 30.03.2012
Сообщений: 101


Offtop: Sleekka, пардон муа, но в личке меня никто ни о чем не просил
WhiteShark вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > LISP: функция Nth наоборот

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
AUTOCAD 2010 перестал переключаться в многооконный режим. Проблемы с переменными Андрей Х. AutoCAD 24 27.05.2015 10:17
Подправте старый лисп evg76 LISP 10 25.10.2012 10:23
Двутавр Born AutoCAD 14 26.03.2009 16:45
3D Konstruktor для проектировщиков КМ. Дима_ Готовые программы 17 10.07.2008 10:03
Помогите с автолиспом MaloI LISP 12 26.12.2006 08:05