Java 按条目乘积递减的顺序生成列表的笛卡尔乘积(条目为正数,列表已排序)

Java 按条目乘积递减的顺序生成列表的笛卡尔乘积(条目为正数,列表已排序),java,algorithm,iteration,cartesian-product,Java,Algorithm,Iteration,Cartesian Product,假设我有几个正数排序列表,例如: double[]a1=新的double[]{0.70,0.20,0.10}; double[]a2=新的double[]{0.80,0.10,0.05,0.05}; double[]a3=新的double[]{0.60,0.15,0.14,0.10,0.01}; 我想按条目乘积递减的顺序迭代这些数组的笛卡尔积,如下所示: 0000: Combo[product=3.36e-01, vals=[0.70, 0.80, 0.60], indexes=[0, 0,

假设我有几个正数排序列表,例如:

double[]a1=新的double[]{0.70,0.20,0.10};
double[]a2=新的double[]{0.80,0.10,0.05,0.05};
double[]a3=新的double[]{0.60,0.15,0.14,0.10,0.01};
我想按条目乘积递减的顺序迭代这些数组的笛卡尔积,如下所示:

0000: Combo[product=3.36e-01, vals=[0.70, 0.80, 0.60], indexes=[0, 0, 0]]
0001: Combo[product=9.60e-02, vals=[0.20, 0.80, 0.60], indexes=[1, 0, 0]]
0002: Combo[product=8.40e-02, vals=[0.70, 0.80, 0.15], indexes=[0, 0, 1]]
0003: Combo[product=7.84e-02, vals=[0.70, 0.80, 0.14], indexes=[0, 0, 2]]
0004: Combo[product=5.60e-02, vals=[0.70, 0.80, 0.10], indexes=[0, 0, 3]]
0005: Combo[product=4.80e-02, vals=[0.10, 0.80, 0.60], indexes=[2, 0, 0]]
...
在上面的示例中,第一个条目是显而易见的(当数组被排序时),它是第一个值的组合:
[0.70,0.80,0.60]
与产品
0.70*0.80*0.60=3.36e-01
,数组
a1、a2、a3
中的对应值索引是
[0,0,0]
。现在第二个条目不那么明显了,我们是否应该将
0.70
更改为
0.20
?或者
0.60
0.15
?或者
0.80
0.10
?第二个应该是
[0.20,0.80,0.60]
产品
9.60e-02
,索引
[1,0,0]

这里有一个Java程序来生成/打印它们:(所有的逻辑都在
printwolecartesianproduct()
method中)
这个程序按字典顺序生成它们,然后按乘积对整个集合进行排序

问题:有没有一种简单的方法可以首先按照正确的顺序生成组合

原因是:我首先没有列表,只有一些已排序的数字集合上的迭代器。可能很长,长度事先不知道,但已知每个迭代器中的数字都已排序

要使用的MVCE(与上面的链接相同):

导入java.text.DecimalFormat;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入java.util.StringJoiner;
导入java.util.function.Consumer;
导入java.util.stream.collector;
公共班机{
公共静态void main(字符串[]args){
列表数据=createData();
打印整个产品(数据);
}
公共静态列表createData(){
double[]a1=新的double[]{0.70,0.20,0.10};
double[]a2=新的double[]{0.80,0.10,0.05,0.05};
double[]a3=新的double[]{0.60,0.15,0.14,0.10,0.01};
返回createData(a1、a2、a3);
}
公共静态void printWholecartsianProduct(列表数据){
最终十进制df=新十进制(“0.00”);
//打印输入数据
字符串矩阵=data.stream()
.map(l->l.stream().map(df::format).collect(collector.joining(“,”))
.map(行->“[”+行+“]”)
.collect(收集器.加入(“\n”));
System.out.println(“输入数据:\n”+矩阵);
//在生成组合时收集它们
最终列表组合=新的ArrayList();
消费者回调=索引->{
double[]v=新的double[index.length];
双针=1;
for(int i=0;i=0){
接受(c);
c[ptr]++;//增量
如果(c[ptr]==data.get(ptr.size()){//carry
做{
ptr--;
}while(ptr>=0&&c[ptr]==data.get(ptr.size()-1);
如果(ptr<0){
打破
}
c[ptr]++;
//归零
而(++ptr-Double.compare(o2.product,o1.product));
StringBuilder sb=新的StringBuilder();
双总P=0;
对于(int i=0;ivals.add(asList(a)));
返回VAL;
}
静态类组合{
最终双产品;
最终双[]VAL;
最终int[]索引;
组合(双乘积、双[]VAL、整数[]索引){
本产品=产品;
this.vals=vals;
this.index=索引;
}
@凌驾
公共字符串toString(){
返回新的StringJoiner(“,”,Combo.class.getSimpleName()+“[”,“]”)
.add(“product=“+String.format”(%.2e”,product))
.add(“vals=[”+Arrays.stream(vals.boxed().map(v->String.format(“%.2f”,v)).collect(
收集器。连接(“,”)+“]”)
.add(“index=“+Arrays.toString(index))
.toString();
}
}
}

我不熟悉Java,但由于它主要只是一种算法,伪代码应该足够了:

Input:
Non-empty lists A, B, C: containing positive number(s).

Pseudo-code:
type-define tuple3 = (iterator, iterator, iterator);
function double value(tuple3 x) {
  return x.elm[0].value() * x.elm[1].value() * x.elm[2].value();
}
function boolean greater_than (tuple3 x, tuple3 y) {
  return (value(x) > value(y));
}
function void main() {
  iterator a = A.first();
  iterator b = B.first();
  iterator c = C.first();
  set<tuple3> Visit;
  PriorityQueue<tuple3, greater_than>  Q;
  Q.add((a,b,c));
  Visit.add((a,b,c));
  while (!Q.empty()) {
     tuple x = Q.pop_top();
     output(x);
     (a, b, c) = x;
     if (a.next() != null && !Visit.contains((a.next(), b, c))) {
         Q.add((a.next(), b, c));
         Visit.add((a.next(), b, c));
     }
     if (b.next() != null && !Visit.contains((a, b.next(), c))) {
         Q.add((a, b.next(), c));
         Visit.add((a, b.next(), c));
     }
     if (c.next() != null && !Visit.contains((a, b, c.next()))) {
         Q.add((a, b, c.next()));
         Visit.add((a, b, c.next()));
     }
  }
}
每个
o
*
表示一个乘法结果。
表示“大于”

左上角的
o
表示
A[0]*B[0]
。每向右一步意味着对
A[]
使用+1索引,每向下一步意味着对
B[]
使用+1索引。对于同一列,
A
的索引相同。对于同一行,
B
的索引相同

考虑一下
*
:我们只知道
A[]
B[]
是后代
o > o > o > *
v   v   v   v
o > o > * > o
v   v   v   v
o > * > o > o
v   v   v   v
* > o > o > o
o > o > o > *
v   v   v   v
o > o > P > N
v   v   v   v
o > * > N > o
v   v   v   v
* > o > o > o