Author Topic: Parse a list of integers  (Read 4799 times)

0 Members and 1 Guest are viewing this topic.

David Bethel

  • Swamp Rat
  • Posts: 656
Parse a list of integers
« on: September 10, 2015, 02:33:14 PM »
Greetings

Using vanilla Autolisp :

Given a sorted list of integers that always starts with 1
Code: [Select]
(setq lst '(1 12 16 21 26 32 40 42 56 66 74))

A function to parse the list with a  maximum difference between values of a specified number of units ie 24
Code: [Select]
(parsel lst 24)

And return a list of lists with the start and end positions:
Code: [Select]
'((1 21) (21 42) (42 66) (66 74))

(1 25) would be valid
Code: [Select]
(<= (- 25 1) 24) ->  T

Any ideas ?  Thanks  -David

PS I haven't figured out what to do if the difference is greater than 24 for 2 adjacent atoms.

Here's where I'm at and it aint working !

Code: [Select]
(defun parsel (lst q / s ) ;i  rl)
  (setq s (car lst))
  (while (< s (last lst))
     (setq i 0)
     (repeat (length lst)
        (if (> (+ s q) (- (nth i lst) s))
            (setq i (1+ i))))
     (setq rl (cons (list s (nth (1- i) lst)) rl)
            s (nth (1- i) lst)))
  (setq rl (cons (list s (last lst)) rl))
  (prin1 (reverse rl)))

Any ideas ?  Thanks  -David
R12 Dos - A2K

ronjonp

  • Needs a day job
  • Posts: 7531
Re: Parse a list of integers
« Reply #1 on: September 10, 2015, 03:01:04 PM »
Not pretty but seems to work with your example  :) 
Guess I should have read a bit closer :oops:   .. does not account for adjacent atoms.
Code - Auto/Visual Lisp: [Select]
  1. (setq l '(1 12 16 21 26 32 40 42 56 66 74))
  2. (defun _foo (l / i i2 out)
  3.   (while (setq i (car l)
  4.           l (cdr l)
  5.     )
  6.     (while (and l (<= (- (car l) i) 24))
  7.       (setq i2 (car l)
  8.        l  (cdr l)
  9.       )
  10.     )
  11.     (setq l   (cons i2 l)
  12.      out (cons (cons i i2) out)
  13.     )
  14.   )
  15.   (reverse out)
  16. )
  17. (_foo l)
  18.  
  19.  
  20. ;;;_$
  21. ;;;
  22. ;;;(1 12 16 21 26 32 40 42 56 66 74)
  23. ;;;_FOO
  24. ;;;((1 . 21) (21 . 42) (42 . 66) (66 . 74))
  25. ;;;; 3 forms loaded from #<editor "<Untitled-1> loading...">
  26. ;;;_$
« Last Edit: September 10, 2015, 03:20:32 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

jvillarreal

  • Bull Frog
  • Posts: 332
Re: Parse a list of integers
« Reply #2 on: September 10, 2015, 03:26:28 PM »
Greetings

Using vanilla Autolisp :

Given a sorted list of integers that always starts with 1
Code: [Select]
(setq lst '(1 12 16 21 26 32 40 42 56 66 74))

A function to parse the list with a  maximum difference between values of a specified number of units ie 24
Code: [Select]
(parsel lst 24)

And return a list of lists with the start and end positions:
Code: [Select]
'((1 21) (21 42) (42 66) (66 74))

(1 25) would be valid
Code: [Select]
(<= (- 25 1) 24) ->  T

Any ideas ?  Thanks  -David

PS I haven't figured out what to do if the difference is greater than 24 for 2 adjacent atoms.

Here's where I'm at and it aint working !

Code: [Select]
(defun parsel (lst q / s ) ;i  rl)
  (setq s (car lst))
  (while (< s (last lst))
     (setq i 0)
     (repeat (length lst)
        (if (> (+ s q) (- (nth i lst) s))
            (setq i (1+ i))))
     (setq rl (cons (list s (nth (1- i) lst)) rl)
            s (nth (1- i) lst)))
  (setq rl (cons (list s (last lst)) rl))
  (prin1 (reverse rl)))

Any ideas ?  Thanks  -David

Using your code:
Code: [Select]
(defun parsel (lst q / s i  rl)
  (setq s (car lst))
  (while (< s (last lst))
     (setq i 0)
     (repeat (length lst)
        (if (>= q (- (nth i lst) s));include equal to and adding s is not needed
            (setq i (1+ i))))
    (if (not (zerop (- (nth (1- i) lst) s)))
     (setq rl (cons (list s (nth (1- i) lst)) rl)
            s (nth (1- i) lst))
     (setq s (nth i lst))
    )
)
 ;(setq rl (cons (list s (last lst)) rl));Not sure why this is being done
  (reverse rl));Removed prin1, assuming it was placed for your testing

*Edit* - Added additional if statement in case difference between current and next number exceed maximum diff
« Last Edit: September 10, 2015, 03:52:03 PM by jvillarreal »

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Parse a list of integers
« Reply #3 on: September 10, 2015, 03:51:32 PM »

So far so good !

I figured it was something fairly simple that I was overlooking

 Thanks!  -David
R12 Dos - A2K

jvillarreal

  • Bull Frog
  • Posts: 332
Re: Parse a list of integers
« Reply #4 on: September 10, 2015, 03:52:34 PM »
Edited previous post for a case such as (parsel lst 12)

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Parse a list of integers
« Reply #5 on: September 10, 2015, 04:42:34 PM »

Thanks.  I'm still contemplating a few different scenarios that I know will crash ( or at least give my poor brain and headache.  -David
R12 Dos - A2K

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Parse a list of integers
« Reply #6 on: September 10, 2015, 04:44:27 PM »
Not pretty but seems to work with your example  :) 


I'll have to give this some thought on how it works !  Thanks  -David
R12 Dos - A2K

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Parse a list of integers
« Reply #7 on: September 10, 2015, 06:35:31 PM »
Another, not likely to be fast:
Code - Auto/Visual Lisp: [Select]
  1. (defun foo ( l n )
  2.     (if l (bar (car l) (+ (car l) n) n (cdr l)))
  3. )
  4. (defun bar ( a b n l )
  5.     (if (cadr l)
  6.         (if (< b (cadr l))
  7.             (cons (list a (car l)) (foo l n))
  8.             (bar a b n (cdr l))
  9.         )
  10.         (list (list a (car l)))
  11.     )
  12. )
Code - Auto/Visual Lisp: [Select]
  1. _$ (foo lst 24)
  2. ((1 21) (21 42) (42 66) (66 74))

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Parse a list of integers
« Reply #8 on: September 10, 2015, 06:52:23 PM »
Another:
Code - Auto/Visual Lisp: [Select]
  1. (defun foo ( l n / x y r )
  2.     (setq x (car  l)
  3.           y (cadr l)
  4.     )
  5.     (foreach z (cddr l)
  6.         (if (< (+ x n) z) (setq r (cons (list x y) r) x y))
  7.         (setq y z)
  8.     )
  9.     (reverse (cons (list x y) r))
  10. )

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Parse a list of integers
« Reply #9 on: September 10, 2015, 07:15:45 PM »
Another:
Code - Auto/Visual Lisp: [Select]
  1. (defun foo ( l n )
  2.     (if (caddr l)
  3.         (if (< (+ (car l) n) (caddr l))
  4.             (cons (list (car l) (cadr l)) (foo (cdr l) n))
  5.             (foo  (cons (car l) (cddr l)) n)
  6.         )
  7.         (list l)
  8.     )
  9. )

AIberto

  • Guest
Re: Parse a list of integers
« Reply #10 on: September 10, 2015, 08:55:42 PM »
 :-(
I can't understand.
(setq lst '(1 12 16 21 26 32 40 42 56 66 74))

(parsel lst 24)
why returns '((1 21) (21 42) (42 66) (66 74))

why not '((1 12) (12 16) (16 21) (21 26)..............)

(<= (- 12 1) 24) ->  T , (<= (- 16 12) 24) ->  T........

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Parse a list of integers
« Reply #11 on: September 11, 2015, 03:33:45 AM »
why not '((1 12) (12 16) (16 21) (21 26)..............)
Because
A function to parse the list with a  maximum difference between values of a specified number of units ie 24
Code: [Select]
(parsel lst 24)

A bit unclearly stated, but it seems to mean: Get pairs of values, where their difference is the maximum less than (or equal to) a specified quantizer (in this case 24).

Your scenario (i.e. simply pair consecutive items) would be very easy:
Code - Auto/Visual Lisp: [Select]
  1. (mapcar 'list lst (cdr lst))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Parse a list of integers
« Reply #12 on: September 11, 2015, 05:44:15 AM »
What should be the result of the function in this case?:
Code: [Select]
(setq lst '(1 12 16 21 26 32 40 42 56 66 74))
(setq dif 2)

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Parse a list of integers
« Reply #13 on: September 11, 2015, 05:57:35 AM »
My offer:
Code - Auto/Visual Lisp: [Select]
  1. ; (Roy_Test_01 '(1 12 16 21 26 32 40 42 56 66 74)  2)
  2. ;   => ((40 . 42))
  3. ; (Roy_Test_01 '(1 12 16 21 26 32 40 42 56 66 74) 10)
  4. ;   => ((12 . 21) (21 . 26) (26 . 32) (32 . 42) (56 . 66) (66 . 74))
  5. ; (Roy_Test_01 '(1 12 16 21 26 32 40 42 56 66 74) 24)
  6. ;   => ((1 . 21) (21 . 42) (42 . 66) (66 . 74))
  7. (defun Roy_Test_01 (lst dif / itm)
  8.   (setq itm (car lst))
  9.     nil
  10.     (mapcar
  11.       '(lambda (cur nxt)
  12.         (if (or (not nxt) (< dif (- nxt itm)))
  13.           (if (< dif (- cur itm))
  14.             (not (setq itm cur))
  15.             (cons itm (setq itm cur))
  16.           )
  17.         )
  18.       )
  19.       (cdr lst)
  20.       (append (cddr lst) '(nil))
  21.     )
  22.   )
  23. )

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Parse a list of integers
« Reply #14 on: September 11, 2015, 06:10:09 AM »
What should be the result of the function in this case?:
Code: [Select]
(setq lst '(1 12 16 21 26 32 40 42 56 66 74))
(setq dif 2)
Agreed - most of the codes here would at worst cause an infinite loop, or need to make some assumption.


@David: Could you please specify what should happen if the quantile is smaller than the difference between some 2 consecutive items in the list?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.