DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #158 - RGB To Hex Conversion

The rgb() method is incomplete. Complete the method so that passing in RGB decimal values will result in a hexadecimal representation being returned.

The valid decimal values for RGB are 0 - 255. Any (r,g,b) argument values that fall out of that range should be rounded to the closest valid value.

The following are examples of expected output values:

rgb(255, 255, 255) # returns FFFFFF
rgb(255, 255, 300) # returns FFFFFF
rgb(0,0,0) # returns 000000
rgb(148, 0, 211) # returns 9400D3


This challenge comes from jhoffner on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Discussion (20)

Collapse
savagepixie profile image
SavagePixie • Edited

My JavaScript solution, which would look a lot nicer if the TC39 finally added a pipeline operator.

const checkRange = num => Math.min(255, Math.max(num, 0))

const rgb = (...args) => args.slice(0, 3)
    .map(x => checkRange(x)
        .toString(16)
        .toUpperCase()
        .padStart(2, '0'))
    .join('')
Enter fullscreen mode Exit fullscreen mode
Collapse
lffg profile image
Luiz Felipe Gonçalves • Edited

String.prototype.padStart would handle the addZeroes trick for you. ;)

Collapse
quozzo profile image
Quozzo • Edited

I got really confused when the link opened in Portuguese. I had to check my VPN 😆

Thread Thread
lffg profile image
Luiz Felipe Gonçalves

Whoops! Sorry about that. :P Should be fixed now.

Collapse
avalander profile image
Avalander

We have padStart now in strings to add characters to the beginning up to a certain length.

Collapse
savagepixie profile image
SavagePixie • Edited

I've modified it to use padStart instead of my custom function.

Thanks @lffg and @avalander !

Collapse
qm3ster profile image
Mihail Malo • Edited

Nodejs (not web):

const rgb = (...args) => 
  Buffer.from(args).toString('hex') // .toUpperCase() // if you are wasteful xD

Not necessarily actually efficient, but definitely hilarious.

General JS:

const rgb = (...args) =>
  args.reduce((a, x, i) => a + x * 0x100 ** (2 /*or args.length*/ - i), 0)
  .toString(16).toUpperCase().padStart(6, '0')
Collapse
celyes profile image
Ilyes Chouia • Edited

My PHP Solution

// round the number to the closest value (255 or 0)
function roundToClosest($color)
{ 
    if($color > 255){
        return 255;
    }elseif($color < 0){
        return 0;
    }
    return $color; 
}

function rgb($r,$g,$b){

    $r = roundToClosest($r);
    $g = roundToClosest($g);
    $b = roundToClosest($b);

    return sprintf("%02X%02X%02X", $r, $g, $b);
}
Collapse
aminnairi profile image
Amin

Elm

toHexadecimalLetter : Int -> String
toHexadecimalLetter integer =
    case integer of
        10 ->
            "A"

        11 ->
            "B"

        12 ->
            "C"

        13 ->
            "D"

        14 ->
            "E"

        15 ->
            "F"

        _ ->
            String.fromInt integer

toHexadecimal : Int -> String
toHexadecimal integer =
    let
        clampedInteger  = clamp 0 255 integer
        integerDivision = clampedInteger // 16
        decimalDivision = toFloat clampedInteger / 16.0
        rest            = floor ((decimalDivision - toFloat integerDivision) * 16)
    in
        toHexadecimalLetter integerDivision ++ toHexadecimalLetter rest 

rgb : Int -> Int -> Int -> String
rgb red green blue =
    [red, green, blue]
        |> List.map toHexadecimal
        |> String.join ""

Test.

Collapse
craigmc08 profile image
Craig McIlwrath

Haskell, using the word8 type to ensure the inputs are from 0-255.

import Data.Bits
import Data.Word 

hexMap :: (Integral a) => a -> Char
hexMap = ("0123456789ABCDEF"!!) . fromIntegral

toHex :: Word8 -> String
toHex word = let lo = word .&. 15
                 hi = word .&. 240
             in  hexMap lo : hexMap (hi `shift` (-4)) : [] 

rgb :: Word8 -> Word8 -> Word8 -> String
rgb r g b = toHex r ++ toHex g ++ toHex b
Collapse
maymeow profile image
💜May Meow🌼

My solution in PHP

<?php

namespace MayMeow\PHPColor;

class Color
{
    /** int $red */
    public $red;

    /** int $green */
    public $green;

    /** int $blue */
    public $blue;

    public function __construct($red, $green, $blue)
    {
        $this->red = $red;
        $this->green = $green;
        $this->blue = $blue;
    }

    /**
     * Method convertToHex
     * Covert given color to string #RRGGBB
     */
    public static function convertToHex(Color $color)
    {
        $red = dechex($color->red);
        if (strlen($red) < 2) $red = '0' . $red; // check string length and add zero if needed

        $green = dechex($color->green);
        if (strlen($green) < 2) $green = '0' . $green;

        $blue = dechex($color->blue);
        if (strlen($blue) < 2) $blue = '0' . $blue;

        return '#' . $red . $green . $blue;
    }

    /**
     * Method convertToRGB
     * Convert given color string back to RGB color values
     */
    public static function convertToRGB($hex)
    {
        $hex = ltrim($hex, "#");

        $red = hexdec(substr($hex, 0, 2));
        $green = hexdec(substr($hex, 2, 2));
        $blue = hexdec(substr($hex, 4, 2));

        return new Color($red, $green, $blue);
    }
}
Collapse
herobank110 profile image
David Kanekanian

Python solution, supports 1 or 3 arguments like CSS.

rgb = lambda *_: "#"+eval("'%02X'"+(lambda a:a.pop(len(_)>1)+a.pop())(["%_","*3"]))

print(rgb(255)) # => #FFFFFF
print(rgb(126, 28, 29)) # => #7E1C1D
Collapse
nickholmesde profile image
Nick Holmes

In C#, you don't even really need to implement a method for this, as its easily done with string interpolation;

    var rgb  = $"{red:X02}{green:X02}{blue:X02}";

(Useful for unique ad-hoc strings, but usually better factored out to a method anyway)

Collapse
dannemanne profile image
Daniel Viklund

Ruby solution

def valid_num(v)
  [[v, 255].min, 0].max
end

def rgb(*args)
  args[0..2].reduce('') { |str, v|
    str << valid_num(v).to_s(16).rjust(2, '0')
  }
end
Collapse
citizen428 profile image
Michael Kohl • Edited

Note that you can use a format string to do most of the work for you:

# before
valid_num(v).to_s(16).rjust(2, '0')

# after
"%02X" % valid_num(n)

You can also use "%0x" if you want the hex digits to be lowercase.

Collapse
dannemanne profile image
Daniel Viklund

Thanks for the tip! I've mostly used string formating for dealing with point numbers in decimals. Need to explore more use cases because the syntax is indeed preferable.

Collapse
citizen428 profile image
Michael Kohl • Edited

F#:

let rgb (r : uint8) (g : uint8) (b : uint8) = 
    sprintf "%02X%02X%02X" r g b

Example:

> rgb 148uy 0uy 211uy;;
val it : string = "9400D3"
Collapse
vaibhavyadav1998 profile image
Vaibhav Yadav

In Go.

func rgb(r, g, b uint8) string {
    return fmt.Sprintf("#%x%x%x", r, g, b)
}
Collapse
adam_cyclones profile image
Adam Crockett

I'd do this with Uint8Array