How might I add a third and final condition, where those candidates
with equal scores AND equal counts are all returned together?

A first try was this:

(defn closest-match
  "Searches the haystack vecs for the closest match to the needle vec"
  [#^IPersistentVector needle #^IPersistentVector haystack]
  (letfn [(matching [candidate]
                    (reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
          (closest [v1 v2]
                   (cond
                     (and (= (matching v1) (matching v2))
                          (= (count v1) (count v2))) [v1 v2]
                     (or (> (matching v1) (matching v2))
                         (and (= (matching v1) (matching v2))
                              (< (count v1) (count v2)))) v1
                     :else v2))]
    (reduce #(closest %1 %2) [] haystack)))

(closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1]})
[[1 2 \b] [1 2 \a]]
(closest-match [1 2] #{[1 2] [1 2 \a] [1 2 \b] [2 1]})
[1 2]

It looks good at first, but I quickly noticed that I broke the whole
reduction by introducing a pair where we expend only a vec:

(closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1] [1 2 \c]})
[1 2 \a]

What we should be getting [[1 2 \a] [1 2 \b] [1 2 \c]] since each of
them is equally close to [1 2 3]




On Mon, Dec 28, 2009 at 5:20 PM, Robert Campbell <rrc...@gmail.com> wrote:
> Thanks ajuc.
>
> I updated the implementation to match your algorithm:
>
> (defn closest-match
>  "Searches the haystack vecs for the closest match to the needle vec"
>  [#^IPersistentVector needle #^IPersistentVector haystack]
>  (letfn [(matching [candidate]
>                    (reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
>          (closest [v1 v2]
>                   (if (or (> (matching v1) (matching v2))
>                           (and (= (matching v1) (matching v2))
>                                (< (count v1) (count v2)))) v1 v2))]
>    (reduce #(closest %1 %2) [] haystack)))
>
> It now factors in the second step, taking the shortest candidate.
>
> (closest-match [1 2 3] #{[1 2 3] [9 8 3] [1 2] [1] [1 0 3 4] [1 2 3 4 5]})
>
> now correctly returns [1 2 3] instead of [1 2 3 4 5]
>
>
>
>
> On Mon, Dec 28, 2009 at 4:23 PM, ajuc <aju...@gmail.com> wrote:
>> I don't know if I understan correctly the requirements, but this is my
>> try.
>>
>>
>> (def v #{[1 2 3]   [9 8 3]   [1 2]   [1]   [1 0 3 4]   [1 2 3 4 5]} )
>>
>> (defn matching [p v]
>>  (reduce + (map #(if (= %1 %2) 1 0) p v)))
>>
>> (defn better-match [p v1 v2]
>>  (if
>>    (or
>>      (> (matching p v1) (matching p v2))
>>      (and
>>         (= (matching p v1) (matching p v2)) (< (count v1) (count
>> v2))))
>>    v1
>>    v2))
>>
>> (reduce #(better-match [1 2 4 4 5] %1 %2) [] v)
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to