Sorted collections (with

`subseq`

and

`rsubseq`

) can help when working with a partition of disjoint intervals, eg when you need to interpolate.

(defn interpolator

"Takes a coll of 2D points (vectors) and returns

their linear interpolation function."

[points]

(let [m (into (sorted-map) points)]

(fn [x]

(let [[[x1 y1]] (rsubseq m <= x)

[[x2 y2]] (subseq m > x)]

(if x2

(+ y1 (* (- x x1) (/ (- y2 y1) (- x2 x1))))

y1)))))

;; => (map (interpolator [[0 0] [1 1] [3 2] [4 3]]) (range 0 9/2 1/2))

;; (0 1/2 1 5/4 3/2 7/4 2 5/2 3)

## 2 comments:

Nice.

The function does something sensible for inputs that outside the range of points.

(map (interpolator points) (range 0 19/2 1/2))

; (0 1/2 1 5/4 3/2 7/4 2 5/2 3 3 3 3 3 3 3 3 3 3 3)

But only on one side

(map (interpolator points) (range -1 19/2 1/2)) ; java.lang.NullPointerException

@john, true, here is an amended version:

(defn interpolator

"Takes a coll of 2D points (vectors) and returns

their linear interpolation function."

[points]

(let [m (into (sorted-map) points)]

(fn [x]

(let [[[x1 y1]] (rsubseq m <= x)

[[x2 y2]] (subseq m > x)]

(cond

(not x2) y1

(not x1) y2

:else (+ y1 (* (- x x1) (/ (- y2 y1) (- x2 x1)))))))))

;; => (map (interpolator [[0 0] [1 1] [3 2] [4 3]]) (range -1 11/2 1/2))

;; (0 0 0 1/2 1 5/4 3/2 7/4 2 5/2 3 3 3)

Post a Comment