On Mon, Nov 8, 2010 at 8:34 PM, Greg <[email protected]> wrote:
> On Nov 8, 2010, at 3:11 PM, Ken Wesson wrote:
>
>> (defn new-gen [a]
>>  (distinct #(= (:val %1) (:val %2))
>>    (for [f a
>>          n [(transform-left f) (transform-right f)]
>>          :when (not (contains? #(= (:val n) %) (map :val (parents n))))]
>>      n)))
>>
>> is more functional but possibly slower.
>
> This is nice, and it's actually very similar to one of my first attempts, as 
> I used 'for' too, but I couldn't figure out how to use just a single 'for'. I 
> didn't know that you could do that secondary assignment for 'n' like that. 
> This is one of my favorite solutions I think.

Thanks.

It can be done without the double-barreled "for", though, if you
really want it that way:

(defn new-gen [a]
  (distinct #(= (:val %1) (:val %2))
    (mapcat
      (fn [f]
        (for [n [(transform-left f) (transform-right f)]
              :when (not (contains? #(= (:val n) %) (map :val (parents n))))]
          n))
      a))))

:-)

>
>> If you really just want the first one in traversal order with each
>> distinct value, though, you could just use
>>
>> (defn new-gen [a]
>>  (distinct #(= (:val %1) (:val %2))
>>    (apply concat
>>      (for [f a]
>>          [(transform-left f) (transform-right f)]))))
>>
>> which makes distinct do all the heavy lifting (the whole rest of it is
>> just the traversal).
>
> This seems to be missing the check for the rule #1 (making sure the parents 
> don't have the same value) though...

True. That would only work if the parents were in the output somewhere.

As you formulated it, if a child of one node had value foo and a child
of a different node had value foo, one would be omitted; the way you
originally worded the problem it sounded like only when both children
of a single node had the same value should one be omitted. If you want
that behavior instead you need

(defn new-gen [a]
  (mapcat
    (fn [f]
      (let [g (transform-left f)
            h (transform-right f)]
        (if (= (:val g) (:val f))
          (if-not (= (:val h) (:val f)) [h])
          (if (or (= (:val h) (:val f)) (= (:val h) (:val g)))
            [g]
            [g h]))))))

or maybe this version suits you better:

(defn new-gen [a]
  (let [test #(= (:val %1) (:val %2))]
    (mapcat
      (fn [f]
        (let [s (distinct test
                  [f (transform-left f) (transform-right f)])]
          (remove #(test % f) s))))))

> Thanks for your solutions! It's very helpful for learning Clojure.

You're welcome.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to