2011-07-06 11 views
5

ベクトルのベクトルとして格納されたx、y点のリストがあり、境界を見つけたいと思います。この与えられた例x、y点のリストの境界を取得する

、:

[[0 0] [20 30] [-50 -70] [200 300]] 

結果は次のようになります。

{:x -50, :y -70, :x2 200, :y2 300} 

は、ここで私がこれまで持っているものです。それは望みの結果を与えますが、冗長であり、私には非常に魅力的ではありません。

(defn get-stroke-bounds [vector-of-points] 
    (reduce (fn [m [x y]] 
     {:x (min (:x m Integer/MAX_VALUE) x) 
     :y (min (:y m Integer/MAX_VALUE) y) 
     :x2 (max (:x2 m Integer/MIN_VALUE) x) 
     :y2 (max (:y2 m Integer/MIN_VALUE) y)}) 
     {} 
     (vector-of-points))) 

改善方法についてのご意見はありますか?ありがとう!

答えて

3

すでに入力ポイントにベクトルを使用している場合は、戻り値を同じ形式にすることをお勧めします。それを念頭に置いて、私はこれが良い慣用的な解決策だと思う:

(defn bounds 
    [points] 
    (let [xs (sort (map first points)) 
     ys (sort (map second points))] 
    (list [(first xs) (first ys)] 
      [(last xs) (last ys)]))) 
+0

'first'と' second'をリストにマッピングして何かをソート可能にする!もちろん!ありがとう! – jhickner

4

あなたのソリューションはすでにかなり良いです!それはかなり慣用的であり、アルゴリズム的に最適な点の数ではO(n)である(実際にはソートを行う方法よりも良い)。

しかし、ここでそれを行うための別の方法は、あなたが興味を持つかもしれないです....私は

(defn get-stroke-bounds [stroke] 
    (zipmap 
     [:x :y :x2 :y2] 
     (map 
     (fn [[getter reducer]] 
      (reduce 
      reducer 
      (map getter stroke))) 
     [ 
      [first min] 
      [second min] 
      [first max] 
      [second max]]))) 
+0

間違いなく面白い!どのように動作するか私にしばらく時間がかかりました。とてもかっこいい! – jhickner

1

:-)高階関数の大ファンだから、私はあなたの解決策を考えていない、主に作成クロージャーもそうではありません。しかし、少ないコードが好きなら、ソートされたセットを試すことができます。

(let [v [[0 0] [20 30] [-50 -70] [200 300]] 
     v-sorted (apply sorted-set v)] 
    [(first v-sorted) (last v-sorted)]) 

更新:私は上記のコードは正しくありませんごめんなさい。 separetely xとyをソートして、最大点または最小点ではない境界を見つける必要があります。セットが好まれる場合を除き、ジョンのsolutionが良いです。

関連する問題