Author Topic: Averaging  (Read 3238 times)

0 Members and 1 Guest are viewing this topic.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Averaging
« on: March 28, 2012, 01:20:32 PM »
Hi folks. Long time no see/talk. Been sick, but not wishing to dwell on that. Hope everyone is well.

Anyway ... had need to write a simple average function that could take a list of numbers, or a list of coordinates, and average the result.

Thought it might make a fun simple challenge for the cumpulsive lisp authors that hang their hats here.

Given: (1 2 3 4 5) or ((1 2) (3 4) (5 6)) or ((1) (2 3) (4 5 6))

Return: 3.0 or (3.0 4.0) or (2.33333 2.66667 2.0) respectively.

Code: [Select]
(defun _Avg ( lst )

    (cond
        ((vl-some 'vl-consp lst) (cons (_Avg (mapcar 'car lst)) (_Avg (mapcar 'cdr lst))))
        ((vl-some 'numberp lst) (/ (apply '+ (subst 0 nil lst)) (float (length lst))))
    )

)

Cheers.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Averaging
« Reply #1 on: March 28, 2012, 01:34:09 PM »
Quick hack, but I fail for the last one:

Code - Auto/Visual Lisp: [Select]
  1. (defun _avg ( l / n )
  2.     (setq n (float (length l)))
  3.     (if (vl-some 'listp l)
  4.         (mapcar '(lambda ( x ) (/ x n)) (apply 'mapcar (cons '+ l)))
  5.         (/ (apply '+ l) n)
  6.     )
  7. )

Nice to see you again MP  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Averaging
« Reply #2 on: March 28, 2012, 02:12:02 PM »
Another, but not too different to yours:

Code - Auto/Visual Lisp: [Select]
  1. (defun _avg ( l / r n )
  2.     (setq n (float (length l)))
  3.     (cond
  4.         (   (listp (car l))
  5.             (repeat (apply 'max (mapcar 'length l))
  6.                 (setq r (cons (/ (apply '+ (subst 0 nil (mapcar 'car l))) n) r)
  7.                       l (mapcar 'cdr l)
  8.                 )
  9.             )
  10.             (reverse r)
  11.         )
  12.         (   (/ (apply '+ l) n))
  13.     )
  14. )

This method of transposition would also work if we excluded the last example:

Code - Auto/Visual Lisp: [Select]
  1. (defun _avg ( l )
  2.     (if (listp (car l))
  3.         (mapcar '_avg (apply 'mapcar (cons 'list l)))
  4.         (/ (apply '+ l) (float (length l)))
  5.     )
  6. )

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Averaging
« Reply #3 on: March 28, 2012, 02:51:25 PM »
Nicely done Lee (like the brevity of the 6 liner) and thanks for the greets. :)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

adalea03

  • Guest
Re: Averaging
« Reply #4 on: March 28, 2012, 09:50:14 PM »
MP
Your humility is admirable.

LM
You continue to raise the bar so high (as MP has done so often)
that I can still walk under it without stooping.

I can only imagine what auto/visual Lisp might have been if minds like yours (and others here)
were a part of the developing teams.

Tony

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Averaging
« Reply #5 on: March 28, 2012, 10:30:18 PM »
Hi folks. Long time no see/talk. < ....>

Great to see you posting again Michael.
Best wishes,
Regards,
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Averaging
« Reply #6 on: March 29, 2012, 05:39:11 AM »
Nicely done Lee (like the brevity of the 6 liner) and thanks for the greets. :)

Thanks Michael  :-)

LM
You continue to raise the bar so high (as MP has done so often)
that I can still walk under it without stooping.

I can only imagine what auto/visual Lisp might have been if minds like yours (and others here)
were a part of the developing teams.

Tony

That's very kind of you to say Tony, thanks  :-)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Averaging
« Reply #7 on: March 29, 2012, 07:14:18 AM »
Hope you're feeling well again MP.

Great idea! And great work MP & Lee! I love how novel, brief, succinct, elegant and robust code can be made in Lisp. I'm trying to imagine how many bible sheets I'd have typed to get the same function in C  :ugly:

Here's another to "extend" on the idea. What about obtaining the median instead of the average? Say something like this:
Code: [Select]
(defun _Median (lst / avg closest diff %compare%)
  (setq avg     (_Avg lst)
        closest (car lst)
  )
  (cond
    ((numberp avg)
     (setq diff (abs (- avg closest))
           lstp 0
     )
     (defun %compare% (num / diff1)
       (if (<= (setq diff1 (abs (- num avg))) diff)
         diff1
       )
     )
    )
    ((vl-consp avg)
     (setq diff (distance avg closest)
           lstp 1
     )
     (defun %compare% (pt / diff1)
       (if (<= (setq diff1 (distance num avg)) diff)
         diff1
       )
     )
    )
    (t (defun %compare% (num) nil))
  )
  (car
    (reverse (vl-remove-if-not
               '(lambda (n / d)
                  (if (setq d (%compare% n))
                    (setq closest n
                          diff d
                    )
                  )
                )
               (cdr lst)
             )
    )
  )
)
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Averaging
« Reply #8 on: March 30, 2012, 02:30:43 PM »
Good to see you back Michael.  8-)

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Averaging
« Reply #9 on: March 30, 2012, 03:16:18 PM »
Good to see you back Michael.  8-)

Thank you Charles, good to see your hat still hangs here prominantly. :)

Hope you're feeling well again MP ... Here's another to "extend" on the idea ...

Thank you sir. I love when code snips spawn other ideas, the very essence of the swamp. :)

Great to see you posting again Michael.
Best wishes,
Regards

Thank you Kerry, and to you and yours the best. :)

MP
Your humility is admirable.

I think you have me confused with someone else but I'll steal the kind words from you anyway. :)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Averaging
« Reply #10 on: March 31, 2012, 04:36:34 AM »
I love when code snips spawn other ideas, the very essence of the swamp. :)
:lmao: ... So that's what the swamp is all about! At last I get it: It's a spawning pond!
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Averaging
« Reply #11 on: March 31, 2012, 04:56:40 AM »
Actually to take my "spawned" idea  ;) and make it a bit "better" ... seeing as it's not truly the correct definition of "Median":
Code - Auto/Visual Lisp: [Select]
  1.  
  2. ;;; By MP: http://www.theswamp.org/index.php?topic=41352.0
  3. (defun _Avg  (lst)
  4.   (cond ((vl-some 'vl-consp lst) (cons (_Avg (mapcar 'car lst)) (_Avg (mapcar 'cdr lst))))
  5.         ((vl-some 'numberp lst) (/ (apply '+ (subst 0 nil lst)) (float (length lst))))))
  6.  
  7. ;;; Get closest point or number to another point or number
  8. (defun _Closest  (lst val / diff)
  9.   (cond ((listp val)
  10.          (setq diff (distance (car lst) val))
  11.          (last (vl-remove-if-not
  12.                  (function (lambda (pt / d)
  13.                              (if (<= (setq d (distance pt val)) diff)
  14.                                (setq diff d))))
  15.                  lst)))
  16.         ((numberp val)
  17.          (setq diff (abs (- (car lst) val)))
  18.          (last (vl-remove-if-not
  19.                  (function (lambda (num / d)
  20.                              (if (<= (setq d (abs (- num val))) diff)
  21.                                (setq diff d))))
  22.                  lst)))))
  23.  
  24. ;;; Get most average point or number
  25. (defun _ClosestToAvg (lst /) (_Closest lst (_Avg lst)))
Not to mention ... it's a bit more succinct, and gives the core as a separate usable function _Closest.

Edit: Code altered to reduce the stupid (car (reverse ... )) into (last ... )  :ugly: :lmao:
And trying out another formatting alternative - more like python format.
« Last Edit: March 31, 2012, 11:19:40 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Averaging
« Reply #12 on: March 31, 2012, 05:05:33 AM »
And of cource the "true" definition of Median (if you have a sorted list):
Code - Auto/Visual Lisp: [Select]
  1. (defun _Median (lst / n)
  2.   (setq n (/ (length lst) 2))
  3.   (cond
  4.     ((vl-consp (car lst))
  5.      (if (= (rem n 2) 0)
  6.        (mapcar (function (lambda (a b) (/ (+ a b) 2.))) (nth n lst) (nth (1+ n) lst))
  7.        (nth n lst)
  8.      )
  9.     )
  10.     ((numberp (car lst))
  11.      (if (= (rem n 2) 0)
  12.        (/ (+ (nth n lst) (nth (1+ n) lst)) 2.)
  13.        (nth n lst)
  14.      )
  15.     )
  16.   )
  17. )
Though with a point list there may be several ways to sort it, e.g. X then Y then Z, or distance from origin, or distance from another point, or clockwise, or ccw, etc.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.