1 module nxt.products;
2 
3 import std.range.primitives : isInputRange, ElementType;
4 
5 auto cartesianProductDynamic(R)(R x)
6 	if (isInputRange!R &&
7 		isInputRange!(ElementType!R))
8 {
9 	import std.algorithm : map;
10 	import std.algorithm.setops : cartesianProduct;
11 	import std.array : array;
12 	import std.algorithm : count;
13 	import nxt.traits_ex : asDynamicArray;
14 
15 	alias E = ElementType!(ElementType!R);
16 	alias C = E[]; // combination
17 	const n = x.count;
18 
19 	final switch (n)
20 	{
21 	case 0: return R.init;
22 	case 1: return [x[0]];
23 	case 2: return cartesianProduct(x[0], x[1]).map!(a => a.asDynamicArray).array;
24 	case 3: return cartesianProduct(x[0], x[1], x[2]).map!(a => a.asDynamicArray).array;
25 	case 4: return cartesianProduct(x[0], x[1], x[2], x[3]).map!(a => a.asDynamicArray).array;
26 	case 5: return cartesianProduct(x[0], x[1], x[2], x[3], x[4]).map!(a => a.asDynamicArray).array;
27 	case 6: return cartesianProduct(x[0], x[1], x[2], x[3], x[4], x[5]).map!(a => a.asDynamicArray).array;
28 	case 7: return cartesianProduct(x[0], x[1], x[2], x[3], x[4], x[5], x[6]).map!(a => a.asDynamicArray).array;
29 	case 8: return cartesianProduct(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]).map!(a => a.asDynamicArray).array;
30 	case 9: return cartesianProduct(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]).map!(a => a.asDynamicArray).array;
31 	// default:
32 	//	 foreach (const i; 0 .. n)
33 	//	 {
34 	//		 foreach (const j; x[i])
35 	//		 {
36 	//			 y[i] ~= j;
37 	//		 }
38 	//	 }
39 	//	 auto y = new C[n];
40 	//	 return y;
41 	}
42 
43 }
44 
45 unittest {
46 	import std.algorithm.comparison : equal;
47 	auto x = cartesianProductDynamic([["2", "3"],
48 									  ["green", "red"],
49 									  ["apples", "pears"]]);
50 	assert(equal(x,
51 				 [["2", "green", "apples"],
52 				 ["2", "green", "pears"],
53 				  ["2", "red", "apples"],
54 				  ["2", "red", "pears"],
55 				  ["3", "green", "apples"],
56 				  ["3", "green", "pears"],
57 				  ["3", "red", "apples"],
58 				  ["3", "red", "pears"]]));
59 }