Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active March 19, 2021 04:26
Show Gist options
  • Save ericnormand/24704c0e4804580c991b68aab29b1c30 to your computer and use it in GitHub Desktop.
Save ericnormand/24704c0e4804580c991b68aab29b1c30 to your computer and use it in GitHub Desktop.

RGB Color Mixing

Here's an algorithm for mixing multiple RGB colors to create a single color.

  1. Separate the colors into Red, Green, and Blue components.
  2. Average all the Reds together, average all the Greens together, average all the Blues together.
  3. Put the average values back together into a resulting RGB.

Is this the right way to do it? I don't know! But it's the way we're going to implement in this problem. Your task is to take a collection of RGB strings of the form "#FF021A", mix them like the algorithm above, and return the resulting RGB string.

Note that each RGB string contains two hexadecimal digits for each component. You can round the averages to integers however you want.

Examples

(mix ["#FFFFFF" "#000000"]) ;=> "#7F7F7F" or "#808080" depending on how you round
(mix ["#FF0000" "#00FF00" "#0000FF"]) ;=> "#555555"

Thanks to this site for the challenge idea where it is considered Very Hard level in JavaScript.

Please submit your solutions as comments on this gist.

@Sinha-Ujjawal
Copy link

My solution to the problem-

(defn hex->num [s]
    (Integer/parseInt s 16))

(defn filter-index [pred coll]
    (map second (filter (fn [[i x]] (pred i)) (map-indexed vector coll))))

(defn pick-even [coll]
    (filter-index (fn [i] (= 0 (bit-and i 1))) coll))

(defn pick-odd [coll]
    (filter-index (fn [i] (= 1 (bit-and i 1))) coll))

(defn hex->rgb [s]
    (let [s (rest s)] (map hex->num (map str (pick-even s) (pick-odd s)))))

(defn rgb->hex [[r g b]]
    (str "#" (clojure.string/join #"" (map (fn [x] (format "%x" x)) [r g b]))))

(defn mix [colors]
    (rgb->hex (let [n (count colors)] (reduce (fn [[x y z] [a b c]] (map (fn [[x y]] (+ x (int (/ y n)))) [[x a] [y b] [z c]])) [0 0 0] (map hex->rgb colors)))))

@Sinha-Ujjawal
Copy link

Sinha-Ujjawal commented Mar 19, 2021

Another solution (thx @andyfry01)-

(defn average [& ns]
    (reduce + (map (fn [n] (/ n (count ns))) ns)))

(defn hex->num [s]
    (Integer/parseInt s 16))

(defn hex->rgb [s]
    (map hex->num (map (fn [[x y]] (str x y)) (partition 2 (rest s)))))

(defn rgb->hex [[r g b]]
    (str "#" (clojure.string/join #"" (map (fn [x] (format "%x" x)) [r g b]))))

(defn mix [colors]
    (rgb->hex (apply map (fn int-average [& ns] (int (Math/floor (apply average ns)))) (map hex->rgb colors))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment