The challenge
In this challenge, you parse RGB colors represented by strings. The formats are primarily used in HTML and CSS. Your task is to implement a function that takes a color as a string and returns the parsed color as a map (see Examples).
Inputs:
The input string represents one of the following:
- 6-digit hexadecimal – “#RRGGBB”
e.g. “#012345”, “#789abc”, “#FFA077”
Each pair of digits represents a value of the channel in hexadecimal: 00 to FF - 3-digit hexadecimal – “#RGB”
e.g. “#012”, “#aaa”, “#F5A”
Each digit represents a value 0 to F which translates to 2-digit hexadecimal: 0->00, 1->11, 2->22, and so on. - Preset color name
e.g. “red”, “BLUE”, “LimeGreen”
You have to use the predefined mapPRESET_COLORS
(JavaScript, Python, Ruby),presetColors
(Java, C#, Haskell), orpreset-colors
(Clojure). The keys are the names of preset colors in lower-case and the values are the corresponding colors in 6-digit hexadecimal (same as 1. “#RRGGBB”).
Examples:
parse("#80FFA0") === new RGB(128, 255, 160))
parse("#3B7") === new RGB( 51, 187, 119))
parse("LimeGreen") === new RGB( 50, 205, 50))
// RGB class is defined as follows:
final class RGB {
public int r, g, b;
public RGB();
public RGB(int r, int g, int b);
}
The solution in Java code
Option 1:
import java.util.Map;
import java.awt.Color;
public class HtmlColorParser {
private final Map<String, String> presetColors;
public HtmlColorParser(Map<String, String> presetColors) {
this.presetColors = presetColors;
}
public RGB parse(String color) {
if (color.charAt(0) != '#') color = nameFixer(color);
if (color.length() < 7) color = stringFixer(color);
Color decoded = (Color.decode(color));
return new RGB(decoded.getRed(), decoded.getGreen(), decoded.getBlue());
}
public String stringFixer(String s) {
return "#" + s.charAt(1) + s.charAt(1) + s.charAt(2) + s.charAt(2) + s.charAt(3) + s.charAt(3);
}
public String nameFixer(String s) {
return presetColors.get(s.toLowerCase());
}
}
Option 2:
import java.util.Map;
class HtmlColorParser {
private final Map<String, String> presetColors;
HtmlColorParser(Map<String, String> presetColors) {
this.presetColors = presetColors;
}
RGB parse(String color) {
if ((color = presetColors.getOrDefault(color.toLowerCase(), color)).length() < 7)
color = color.replaceAll("((?i)[\\da-f])", "$1$1");
return new RGB(Integer.valueOf(color.substring(1, 3), 16), Integer.valueOf(color.substring(3, 5), 16), Integer.valueOf(color.substring(5), 16));
}
}
Option 3:
import java.util.Map;
public class HtmlColorParser {
private final Map<String, String> presetColors;
public HtmlColorParser(Map<String, String> presetColors) {
this.presetColors = presetColors;
}
public RGB parse(String color) {
String lc = color.toLowerCase();
String rgb = presetColors.getOrDefault(lc, lc);
if(rgb.length() == 4)
rgb = rgb.replaceAll("([0-9a-f])", "$1$1");
return new RGB(Integer.valueOf(rgb.substring(1, 3), 16),
Integer.valueOf(rgb.substring(3, 5), 16),
Integer.valueOf(rgb.substring(5), 16));
}
}
Test cases to validate our solution
import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ExampleTests {
private HtmlColorParser parser;
@Before
public void setup() {
parser = new HtmlColorParser(PresetColors.getMap());
}
@Test
public void testExamples() {
shouldParse("#80FFA0", new RGB(128, 255, 160));
shouldParse("#3B7", new RGB( 51, 187, 119));
shouldParse("LimeGreen", new RGB( 50, 205, 50));
}
private void shouldParse(String color, RGB expected) {
assertRgbEquals(color, expected, parser.parse(color));
}
private static void assertRgbEquals(String input, RGB expected, RGB actual) throws AssertionError {
try {
System.out.printf("input: \"%s\"", input);
assertEquals(expected, actual);
System.out.println(" => pass!");
} catch (AssertionError e) {
String message = String.format(Locale.ENGLISH,
"expected: %s\nactual : %s", expected, actual);
throw new AssertionError(message, e);
}
}
}