Minimum value in a vector

272 views
Skip to first unread message

Don

unread,
Dec 2, 2009, 5:43:27 PM12/2/09
to Clojure
I am having difficulty approaching this problem. I'm not sure if it
can be done in one swoop, or requires a few steps.

I have 5 vectors as such:

a [2 4 6 7]
b [1 3 9 2]
c [2 4 5 6]
d [6 1 3 8]
e [4 8 2 1]

And I want to take the minimum value at a given index between the
vectors. Therefore, minimum value at index 0 would yield the value 1
from vector b.

Thank You.

Stefan Kamphausen

unread,
Dec 2, 2009, 5:53:22 PM12/2/09
to Clojure
Hi,
a quick shot would be

(reduce min (map #(get % 0) (list a b c d e)))

It would be nicer to have a vector of vectors or a list of vectors at
the beginning, probably.

Cheers,
Stefan

Kevin Downey

unread,
Dec 2, 2009, 5:55:26 PM12/2/09
to clo...@googlegroups.com
user=> (vec (map min [2 4 6 7] [1 3 9 2] [2 4 5 6] [6 1 3 8] [4 8 2 1]))
[1 1 2 1]
user=>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en



--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

Don

unread,
Dec 2, 2009, 6:22:32 PM12/2/09
to Clojure
Thank you Stefan and Kevin. Awesome solutions that answer my
question. However I actually made a mistake in posing my question.
Let me attempt to ask my question again.

I have 5 vectors as such:
a [2 4 6 7]
b [1 3 9 2]
c [2 4 5 6]
d [6 1 3 8]
e [4 8 2 1]

and the output i want is this

a1 [0 0 0 0]
b1 [1 0 0 0]
c1 [0 0 0 0]
d1 [0 1 0 0]
e1 [0 0 1 1]

Now I'm not sure if it can be done in one swoop, or should be done in
a loop. I was thinking a loop, but I'm having trouble thinking about
it.

I initially thought of creating a function that takes in 5 vectors and
returns a single vector. So the first time its called it would
return a1 [0 0 0 0] then call it again and return b1 [1 0 0 0] etc...
I know it will repeat calculations however I couldn't come up with
anything else.

Thank you.

Don

unread,
Dec 2, 2009, 6:29:11 PM12/2/09
to Clojure
Forgot to mention that i'm still calculating the minimum distance
between the vectors, but my output isn't actually the minimum value.
The output is the minimum value in terms of the vectors, if that makes
sense.

Wilson MacGyver

unread,
Dec 2, 2009, 6:40:17 PM12/2/09
to clo...@googlegroups.com
assuming, vector a b c d e are already defined.

I'd do

user=> (map vector a b c d e)
([2 1 2 6 4] [4 3 4 1 8] [6 9 5 3 2] [7 2 6 8 1])

you can then use the solutions provided from previous messages
to find the min value of each vector.

so you then end up with

[0 1 0 0 0] [0 0 0 1 0] [0 0 0 0 1] [0 0 0 0 1]

at that point, you repeat the same trick

(map vector [0 1 0 0 0] [0 0 0 1 0] [0 0 0 0 1] [0 0 0 0 1])

and that will give you

[0 0 0 0] [1 0 0 0] [0 0 0 0] [0 1 0 0] [0 0 1 1]
Omnem crede diem tibi diluxisse supremum.

Don

unread,
Dec 2, 2009, 7:59:50 PM12/2/09
to Clojure
I still can't figure it out. If have this set.

a [2 4 6 7]
b [1 3 9 2]
c [2 4 5 6]
d [6 1 3 8]
e [4 8 2 1]

If I do (reduce min (map #(get % 0) (list a b c d e)))

It grabs the min value from index 0 of the five vectors and returns 1
corresponding to 'b'. But I'm not sure how I would determine it's
coming from 'b'. I need to know that it comes from 'b' in order to
build the new vector.

If I do (vec (map min a b c d e))

It grabs the min value from index (0, 1, 2, 3) and puts it in a vector

[1 1 2 1]

And I don't know from what vector the minimum value is coming from.

The solution is probably already here but I can't think of it. Sorry.

John Harrop

unread,
Dec 2, 2009, 5:55:17 PM12/2/09
to clo...@googlegroups.com
(defn min-col [col vecs]
  (apply min (map #(nth % col) vecs)))

user=> (min-col 0 [[2 4 6 7] [1 3 9 2] [2 4 5 6] [6 1 3 8] [4 8 2 1]])
1

John Harrop

unread,
Dec 2, 2009, 9:20:23 PM12/2/09
to clo...@googlegroups.com
On Wed, Dec 2, 2009 at 7:59 PM, Don <josere...@gmail.com> wrote:
I still can't figure it out.  If have this set.

 a [2 4 6 7]
 b [1 3 9 2]
 c [2 4 5 6]
 d [6 1 3 8]
 e [4 8 2 1]

If I do (reduce min (map #(get % 0) (list a b c d e)))

It grabs the min value from index 0 of the five vectors and returns 1
corresponding to 'b'. But I'm not sure how I would determine it's
coming from 'b'.  I need to know that it comes from 'b' in order to
build the new vector.

If I do (vec (map min a b c d e))

It grabs the min value from index (0, 1, 2, 3) and puts it in a vector

[1 1 2 1]

And I don't know from what vector the minimum value is coming from.

The solution is probably already here but I can't think of it.  Sorry.
 
(defn min-col [col vecs]
  (apply min (map #(nth % col) vecs)))

(defn min-pos [col vecs]
  (let [m (min-col col vecs)]
    (map #(if (= m %) 1 0) (map #(nth % col) vecs))))

(defn min-pos-vecs [vecs]
  (apply map vector
    (map #(min-pos % vecs)
      (range (count (first vecs))))))

user=> (min-pos-vecs [[2 4 6 7] [1 3 9 2] [2 4 5 6] [6 1 3 8] [4 8 2 1]])
([0 0 0 0] [1 0 0 0] [0 0 0 0] [0 1 0 0] [0 0 1 1])

Wilson MacGyver

unread,
Dec 2, 2009, 10:01:56 PM12/2/09
to clo...@googlegroups.com
(defn min-dist [coll]
(let [minval (reduce min coll)]
(map #(if (= minval %) 1 0) coll)))

this function, if you pass
user=> (min-dist [2 1 2 6 4])
(0 1 0 0 0)

assume the 5 vectors are stored in a b c d e.

user=> (apply map vector (map min-dist (map vector a b c d e)))
([0 0 0 0] [1 0 0 0] [0 0 0 0] [0 1 0 0] [0 0 1 1])


On Wed, Dec 2, 2009 at 7:59 PM, Don <josere...@gmail.com> wrote:

Chouser

unread,
Dec 2, 2009, 10:43:51 PM12/2/09
to clo...@googlegroups.com
>> On Wed, Dec 2, 2009 at 6:22 PM, Don <josereyno...@gmail.com> wrote:
>> > Thank you Stefan and Kevin.  Awesome solutions that answer my
>> > question.  However I actually made a mistake in posing my question.
>> > Let me attempt to ask my question again.
>>
>> >  I have 5 vectors as such:
>> >  a [2 4 6 7]
>> >  b [1 3 9 2]
>> >  c [2 4 5 6]
>> >  d [6 1 3 8]
>> >  e [4 8 2 1]
>>
>> > and the output i want is this
>>
>> > a1 [0 0 0 0]
>> > b1 [1 0 0 0]
>> > c1 [0 0 0 0]
>> > d1 [0 1 0 0]
>> > e1 [0 0 1 1]

(defn min-cols [v]
(map #(apply min-key % (range (count v)))
(apply map vector v)))

(defn mark-cols [v m]
(map (fn [i] (map #(if % 1 0) (map = m (repeat (count m) i))))
(range (count v))))

(def v [[2 4 6 7] [1 3 9 2] [2 4 5 6] [6 1 3 8] [4 8 2 1]])

user=> (mark-cols v (min-cols v))
((0 0 0 0) (1 0 0 0) (0 0 0 0) (0 1 0 0) (0 0 1 1))

--Chouser

Don

unread,
Dec 2, 2009, 11:36:00 PM12/2/09
to Clojure
Thanks to everyone for the solutions. I actually wrote this terribly
ugly function. Terrible. This should go in the "don't write code like
this section" in clojure book.

(defn md2 [d1 d2 d3 d4 d5]
(let [cnt (count d1)]
(loop [i 0 v []]
(if (= i cnt)
v
(do
(if (= (get d1 i) (reduce min (map #(get % i) (list d1 d2 d3
d4 d5))))
(recur (inc i) (conj v 1))
(recur (inc i) (conj v 0))))))))
Reply all
Reply to author
Forward
0 new messages