interpolate hex color vectors in one line of ruby

Posted by crux on June 27, 2007

which color lies halfway inbetween #ff00ff and #00ff00 you ask?

One line of ruby code can interolate two color vectors like they are usually found inside css files, like: body{background: #ff00ff; color: #00ff00}.

%w{ff00ff 00ff00}.map{|a|a.scan(/../).map{|b|b.hex}}.inject{|c,d|(0...c.size).each{|i|c[i]+=d[i]};c}.map{|e|"%02x"%(e>>1)}.join

@UPDATE:
#121 character solution by schmidt(http://www.nach-vorne.de)
%w{ff00ff 00ff00}.map{|a|a.scan(/../).map{|b|b.hex}}.inject{|c,d|c.size.times{|i|c[i]+=d[i]};c}.map{|e|"%0x"%(e>>1)}.join


Answer -> 0x7f7f7f. sure, there must be a shorter version. Can you show it to me?

next step: color animations and gradients and HSR colorspace conversions mayby.

have fun



Technorati Tags: , , , , , ,

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. schmidt Wed, 27 Jun 2007 11:22:06 UTC

    I could eliminate 5 chars by swapping “(0…c.size).each” with “c.size.times”. One is redundant: “%02x” and “%0x” should be the same in this context. (e>>1) should never be larger than 255.

    %w{ff00ff 00ff00}.map{|a|a.scan(/../).map{|b|b.hex}}.inject{|c,d|c.size.times{|i|c[i]+=d[i]};c}.map{|e|”%0x”%(e>>1)}.join

    With the help of active support you could substitute “.map{|b|b.hex}” with “.map(&:hex)” and save again 3 characters.

    And the final question is, wheter this algorithm is sufficient to calculate the colour “in the middle”. I guess transforming it to HSV (the colour schema not the football club) and computing there would deliver better results. But this won’t be shorter.

  2. joe.sixpack Wed, 27 Jun 2007 12:31:44 UTC

    @it would not work for HSV, i knew that, but found colorspace to complicated for one line.

    about active_support, that’s also right, but would go against the ‘fully self contained’ character of this oneliner.

    keep on going: 127121 == ‘%w{ff00ff 00ff00}.map{|a|a.scan(/../).map{|b|b.hex}}.inject{|c,d|c.size.times{|i|c[i]+=d[i]};c}.map{|e|”%0x”%(e>>1)}.join’.size

    are to beat!

  3. mono Wed, 27 Jun 2007 17:55:27 UTC

    132 Zeichen im ersten Versuch. Einzeilig wäre etwas länger. Und Ruby ist es auch nicht. Aber mindestens so cryptisch.

    h[]=[]::[Int] h l=read(“0x”++(take 2 l)):h(drop 2 l) m a b=(a+b)div2 foldl(++)”".map(printf”%x”)$zipWith m(h”ff00ff”)(h”00ff00″)

  4. bob Thu, 10 Jul 2008 16:21:10 UTC

    >>Sure, there must be a shorter version. Can you show it to me?

    If short obfuscated code is your aim then I think your writing in the wrong language. Have you thought of perl

    http://www.perlmonks.org/?node=Obfuscated%20Code

    try not to bring this kind of crap to ruby

  5. crux Thu, 10 Jul 2008 16:51:56 UTC

    @bob, what harsh words you spell on me? No, don’t worry, nothing could be farther away from me than bringing awefull perl style to the ruby world. the interpol code just serves as the exception to the rule,

    nichts fuer ungut

Comments