Author Topic: Snap Number  (Read 947 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Swamp Rat
  • Posts: 812
Snap Number
« on: March 09, 2017, 02:43:44 PM »
Hi guys,
The following idea hit me  :idea: :
Code: [Select]
_$ (SnapNumber 88.92 '(0.0 90.0 180.0 270.0 360.0)) -> 90.0My intention was to "fix" some inaccurate values, by snapping to a value from a numerical list.
Decided that the most approriate name for this subfunction would be "SnapNumber" (my other thoughts were "FixNumber" "getClosestNumberTo").

So I started simple:
Code - Auto/Visual Lisp: [Select]
  1. ; Snaps a number to the closest one in the list (if the num is equally between 2 vals, then it returns the lower value)
  2. ; _$ (SnapNumber 3.2 '(0 2 4 6)) -> 4
  3. ; _$ (SnapNumber 3 '(0 2 4 6)) -> 2
  4. ; _$ (SnapNumber 45 '(0.0 90.0 180.0 270.0 360.0)) -> 0.0
  5. (defun SnapNumber ( n Ln / Ld )
  6.   (cond
  7.     ( (or (not (numberp n)) (not (vl-every 'numberp Ln))) (princ "\nInvalid inputs.") nil )
  8.     ( (setq Ld (mapcar '(lambda (x) (abs (- n x))) Ln))
  9.       (nth (vl-position (apply 'min Ld) Ld) Ln)
  10.     )
  11.   ); cond
  12. ); defun SnapNumber

But then I thought, what if the number is in the middle between two values in the list.. soo:
Code - Auto/Visual Lisp: [Select]
  1. ; Snaps a number to the closest ones in the list (if the num is equally between 2 vals, then it returns list of both values)
  2. ; _$ (SnapNumber2 5 '(0 2 4 6)) -> (4 6)
  3. ; _$ (SnapNumber2 5.2 '(0 2 4 6)) -> 6
  4. ; _$ (SnapNumber2 45 '(0.0 90.0 180.0 270.0 360.0)) -> (0.0 90.0)
  5. (defun SnapNumber2 ( n Ln / _Positions Ld rtn )
  6.  
  7.   (defun _Positions ( x lst / p ) ; MP ;;  find all the positions of x in lst ;;  (_Positions 1 '(0 0 1 0 0 1)) >> (2 5)
  8.     (if (setq p (vl-position x lst))
  9.       ( (lambda ( lst result )
  10.         (while (setq p (vl-position x lst)) (setq result (cons (+ 1 p (car result)) result) lst (cdr (member x lst)) ) )
  11.         (reverse result)
  12.       )
  13.       (cdr (member x lst)) (list p)
  14.       )
  15.     )    
  16.   ); defun _Positions
  17.   (cond
  18.     ( (or (not (numberp n)) (not (vl-every 'numberp Ln))) (princ "\nInvalid inputs.") nil )
  19.     ( (setq Ld (mapcar '(lambda (x) (abs (- n x))) Ln))
  20.       (setq rtn (mapcar '(lambda (x) (nth x Ln)) (_Positions (apply 'min Ld) Ld)))
  21.     )
  22.   ); cond
  23.   (cond ( (not rtn) nil) ( (= 1 (length rtn)) (car rtn) ) (rtn) )
  24. ); defun SnapNumber2
Which means:
Code: [Select]
_$ (SnapNumber2 45 '(0.0 90.0 180.0 270.0 360.0)) -> (0.0 90.0)
But my last intention was to add some tolerance/fuzz, where if the snap number is not within range, return the original number:
If we have (defun SnapNumber2 (n fuzz Ln / ...) ... )
Then:
Code: [Select]
_$ (SnapNumber2 89.1 1.0 '(0.0 90.0 180.0 270.0 360.0)) -> 90
_$ (SnapNumber2 89.1 0.5 '(0.0 90.0 180.0 270.0 360.0)) -> 89.1
_$ (SnapNumber2 5 5 '(0.0 90.0 180.0 270.0 360.0)) -> 0
_$ (SnapNumber2 5 4.9 '(0.0 90.0 180.0 270.0 360.0)) -> 5

Unfortunately right now I don't have enough time to figure this out, so decided to leave it here (instead of burrowing this with my other unfinished subfunctions).
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg