假设我有一个看起来像这样的数组声明
array[1..5] of int: temp = [1,0,5,0,3];
有没有办法启动一个看起来与 temp 相同但没有 0 的新数组?结果如下所示
[1,5,3]
或以这样的方式对数组进行排序,使 0 位于数组的开头或结尾,这将是
[0,0,1,5,3]
或者
[1,5,3,0,0]
谢谢
尽管 Axel 已经回答了这个问题,但我将展示另一种方法——在我的书中更简洁一些。
情况 1:数组(“temp”)是一个常量数组。然后可以简单地写
int 的数组 [int]:temp2 = [temp[i] | i in index_set(temp) where temp[i] != 0];
MiniZinc 2(与版本 1.* 相比)如果可以计算,则不需要尺寸声明;只需使用“array [int]”就足够了。此外,“index_set”用于更通用一点,例如处理索引从 0..4 开始的情况(参见注释行)。
如果要处理的数组是决策变量,我们不知道(根据定义)有多少个 0,并且必须依赖替代变体,即对数组进行排序。然后可以使用“排序”功能,如模型所示。
include "globals.mzn";
% constant
array[1..5] of int: temp = [1,0,5,0,3];
% array[0..4] of int: temp = array1d(0..4, [1,0,5,0,3]);
array[int] of int: temp2 = [temp[i] | i in index_set(temp) where temp[i] != 0];
% decision variables
array[1..5] of var int: s;
array[1..5] of var int: s2 = sort(s); % NOT CORRECT, see model below
solve satisfy;
constraint
s = [1,0,5,0,3]
;
% show our variables
output
[
"temp: \(temp)\n",
"temp2: \(temp2)\n",
"s: \(s)\n",
"s2: \(s2)\n",
];
更新
对于决策变量的稳定版本,这适用于我所看到的。它根据“s [i]”是否为0来计算放置此数字的位置。虽然不是很漂亮。
int: n = 5;
array[1..n] of var 0..5: s;
array[1..n] of var lb_array(s)..ub_array(s): s2;
solve satisfy;
constraint
s = [1,0,5,0,3] /\
forall(i in 1..n) (
if s[i] != 0 then
s2[sum([s[j]!=0 | j in 1..i-1])+1] = s[i]
else
s2[sum([s[j]!=0 | j in 1..n]) + sum([s[j]=0 | j in 1..i-1])+1 ] = 0
endif
)
;
output
[
"s: \(s)\n",
"s2: \(s2)\n",
]
;
输出是
s: [1, 0, 5, 0, 3]
s2: [1, 5, 3, 0, 0]
使用MiniZinc 2
,可以按如下方式完成:
array[1..5] of int: temp = [1,0,5,0,3];
% calculate upper bound of temp index
int: i_max = max(index_set(temp));
% use array comprehension to count non-zero elements
int: temp_non_zero = sum([1 | i in 1..i_max where temp[i] != 0]);
% copy non-zero elements to new array
array[1..temp_non_zero] of int: temp2 = [temp[i] | i in 1..i_max where temp[i] != 0];
% calculate upper bound for temp2 index
int: i2_max = max(index_set(temp2));
solve satisfy;
% show our variables
output
["\ni_max=" ++ show(i_max)]
++ ["\ni2_max=" ++ show(i2_max)]
++ ["\n" ++ show(temp2[i]) | i in 1..i2_max]
;
另一种选择:
两个数组之间的 1:1 映射建立为唯一索引值数组(= 数组位置)。然后对这些索引进行排序。如果元素指向零,则比较权重更高的元素。因此,零值向后移动,同时保持非零元素的顺序不变。
int: n = 5;
int: INF = 99999; % infinity
array[1..n] of var 0..5: s;
array[1..n] of var 1..n: map;
array[1..n] of var 0..5: s2;
solve satisfy;
% set s[]
constraint
s = [1,0,5,0,3]
;
% 1:1 mapping between s[] and s2[]
constraint
forall (i in 1..n) (
exists(j in 1..n) (
map[j] = i
)
)
;
constraint
forall(i in 1..n) (
s2[i] = s[map[i]]
)
;
% sort the map and move zero values to the back
constraint
forall(i in 1..n-1) (
(if s2[i] != 0 then map[i] else INF endif) <=
(if s2[i+1] != 0 then map[i+1] else INF endif)
)
;
output
[
"s: \(s)\n",
"map: \(map)\n",
"s2: \(s2)\n",
]
;
输出:
s: [1, 0, 5, 0, 3]
map: [1, 3, 5, 4, 2]
s2: [1, 5, 3, 0, 0]