I am working on a project in which I have three box (as of now) and each box will have some color of balls, so I am storing the input in a Map
of String
and List
of String
as shown below:
Map<String, List<String>> boxBallMap = new LinkedHashMap<String, List<String>>();
Data in the above map can be like this. Below is one possible input combination and each box won't have same color balls, so two blues is not possible in box1
as an input:
{box1=[blue, red, orange]}
{box2=[blue, red, orange]}
{box3=[blue, red, orange]}
Basis on the above input, I need to return a mapping which will be List<Map<String, String>>
, so for above input below mapping would be returned as an output (this is one possible output combination which follows the below rules):
[{box1=blue, box2=red, box3=orange},
{box1=red, box2=orange, box3=blue},
{box1=orange, box2=blue, box3=red}]
Some rules:
In each row, boxes should have an alternate colors of ball. If you see above, each row has an alternate color of balls for each box - meaning
blue
forbox1
,red
forbox2
,orange
forbox3
in the first row.I cannot have same color of balls in each row, so the below combination is not possible as it has same color of balls for two boxes in one row:
{box1=blue, box2=blue, box3=orange}
In the next row, I won't use those balls for the box which have been used in the earlier rows, so the second row cannot have
blue
forbox1
as it was already used in the first row bybox1
.
Below is the code I have so far which works fine on some input combinations but somehow doesn't work on some of the input combinations:
public static List<Map<String, String>> generateMappings(Map<String, List<String>> input) {
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
// find all boxes
List<String> boxes = new ArrayList<String>(input.keySet());
// find all colors
Set<String> distinctColors = new LinkedHashSet<String>();
for(List<String> e : input.values()) {
for(String color : e) {
if(! distinctColors.contains(color)) {
distinctColors.add(color);
}
}
}
List<String> colors = new ArrayList<String>(distinctColors);
int colorIndex = 0;
for(int i = 0; i < colors.size(); i++) {
Map<String, String> row = new LinkedHashMap<String, String>();
output.add(row);
colorIndex = i;
for(int j = 0; j < colors.size(); j++) {
int boxIndex = j;
if(boxIndex >= boxes.size()) {
boxIndex = 0;
}
String box = boxes.get(boxIndex);
List<String> boxColors = input.get(box);
if(colorIndex >= colors.size()) {
colorIndex = 0;
}
String color = colors.get(colorIndex++);
// a combination is generated only if the actual
// colors does exist in the actual box
if(boxColors.contains(color)) {
row.put(box, color);
}
}
}
return output;
}
Sample Unit Test
Map<String, List<String>> input = new LinkedHashMap<>();
input.put("box1", Arrays.asList("blue", "red", "orange"));
input.put("box2", Arrays.asList("blue", "red", "orange"));
input.put("box3", Arrays.asList("blue", "red", "orange"));
List<Map<String, String>> output = create(input);
for(Map<String, String> e : output) {
System.out.println(e);
}
And
Map<String, List<String>> input = new LinkedHashMap<>();
input.put("box1", Arrays.asList("blue", "red", "orange"));
input.put("box2", Arrays.asList("blue", "red", "orange"));
input.put("box3", Collections.<String>emptyList());
List<Map<String, String>> output = create(input);
for(Map<String, String> e : output) {
System.out.println(e);
}
And
Map<String, List<String>> input = new LinkedHashMap<>();
input.put("box1", Arrays.asList("blue", "red", "orange"));
input.put("box2", Arrays.asList("blue", "red"));
input.put("box3", Arrays.asList("blue", "red", "orange"));
List<Map<String, String>> output = create(input);
for(Map<String, String> e : output) {
System.out.println(e);
}
Is there any better way of solving this algorithm?
{box4=[blue,blue]}
what would the expected output be? It would be nice if you also added some unit tests. \$\endgroup\$