0

If I wanted to build a table in Clojure of vector duplicates, I'd write:

(take 2 (repeat [1 2 3]))

But how would I expand this notion of a table function to build something like:

Input 1: [a^2 2 6 2] where a^2 is some input function, 2 is min value, 6 is max value, and 2 is step size.

Output 1: [4,16,36]

Input 2: [b^2 10 -5 -2]

Output 2: [100 64 36 16 4 0 4 16]

This outputs a 4x3 matrix

Input 3: [(+ (* 10 i) j) [1 4] [1 3]]

where (+ (* 10 i) j) is 10i+j (some given input function), [1 4] is the min and max of i, and [1 3] is the min and max of j.

Output 3: [[11 12 13] [21 22 23] [31 32 33] [41 42 43]]

sunspots
  • 1,047
  • 13
  • 29

3 Answers3

1

You want to use for in a nested fashion:

(for [i (range 1 (inc 4))]
  (for [j (range 1 (inc 3))]
    (+ (* 10 i) j)))
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))

EDIT: expanded with an example implementation

For example:

(defn build-seq [f lower upper step]
  (for [i (range lower (+ upper step) step)]
    (f i)))

(build-seq #(* % %) 2 6 2)
;; '(4 16 36)

(defn build-table [f [ilower iupper] [jlower jupper]]
  (for [i (range ilower (inc iupper))]
    (for [j (range jlower (inc jupper))]
      (f i j))))

(build-table #(+ (* 10 %) %2) [1 4] [1 3])
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))

Your three input/output samples do not display a consistent signature for one variable and two ; furthermore, the step argument seems to be optional. I'm skeptical about the existence of a nice API that would retain the samples' syntax, but I can try something different (even if I do believe the simple embedded for forms are a better solution):

(defn flexible-range [{:keys [lower upper step] :or {lower 0}}]
  (let [[upper step] (cond
                       (and upper step) [(+ upper step) step]
                       step  (if (pos? step)
                               [Double/POSITIVE_INFINITY step]
                               [Double/NEGATIVE-INFINITY step])
                       upper (if (< lower upper)
                               [(inc upper)  1]
                               [(dec upper) -1])
                       :else   [Double/POSITIVE_INFINITY 1])]
    (range lower upper step)))

(defn build-table
  ([f [& params]]
    (for [i (flexible-range params)]
      (f i)))
  ([f [& iparams] [& jparams]]
    (for [i (flexible-range iparams)]
      (for [j (flexible-range jparams)]
        (f i j)))))

(build-table #(* % %) [:lower 2 :upper 6 :step  2])
;; '(4 16 36)

(build-table #(+ (* 10 %) %2) [:lower 1 :upper 4]
                              [:lower 1 :upper 3])
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))
omiel
  • 1,573
  • 13
  • 16
0

I think you can easily solve it with map and range

(defn applier
  [f ini max step]
  (map f (range ini (+ max step) step)))

(applier #(* % %) 2 6 2)
=> (4 16 36)
guilespi
  • 4,672
  • 1
  • 15
  • 24
0

This fn can resolve your third example

(defn your-fn [[ra1 ra2] [rb1 rb2] the-fn]
   (vec (map (fn [i] (vec (map (fn [j] (the-fn i j)) (range rb1 (inc rb2))))) (range ra1 (inc ra2))))
   )
(your-fn [1 4] [1 3] (fn [i j] (+ (* 10 i) j)))

=> [[11 12 13] [21 22 23] [31 32 33] [41 42 43]]

But i'd need a few more specification details (or more use cases) to make this behavior generic, maybe you can explain a little more your problem. I think the 1st-2nd and the 3rd examples don't take the same type of parameters and meaning, (step vs seq ). So the @Guillermo-Winkler solves part the problem and my-fn will cover the last example

tangrammer
  • 3,041
  • 17
  • 24