I’m working on rde_npr_permutation, the final set of tool for my combinatorics library. Now, there seem to be a bug, I simply cannot grasp, ever. I do have some ideas, but not much. This is the code:
Current Code
#@cli rep_rde_npr_permutations: selected_count,item_0_count>=1,item_1_count,...,_axis={x,y,z}
#@cli : Generates all possible permutations of repeated distinct elements of different counts, and the total number of elements is equal to the selected_count.
#@cli :
#@cli : Default values: '_axis=x'
+rep_rde_npr_permutations:
check "isint($1,1)&&$#>1"
if isnum($-1)
items_counts=${2--1}
axis=0
else
check "inrange(_'$-1',_'x',_'z',1,1)"
items_counts=${2--2}
axis={_'$-1'-_'x'}
fi
check "items_counts=["$items_counts"];
( sum( isint(items_counts,1) ) == size(items_counts) ) && ($1 <= sum(items_counts) );"
number_of_possible_permutations=${_rep_rde_npr_permutations_length\ $1,$items_counts}
if $number_of_possible_permutations>(1<<24) error exc_combin_size:$number_of_possible_permutations fi
out_dim={v=vector(#3,1);v[$axis]=$number_of_possible_permutations;v}
$out_dim,$1,>"begin(
quantity_of_items_in_group=vmin(["$items_counts"],$1);
const cardinality_of_groups=size(quantity_of_items_in_group);
const last_group_id=cardinality_of_groups-1;
final_modify_pos=0;
result=vector(#$1);
final_perm=result;
const result_size=size(result);
const last_r_ind=result_size-1;
const start_modify_pos=last_r_ind-1;
p=q=0;
remaining_counts=quantity_of_items_in_group;
while(p<result_size,
current_size=quantity_of_items_in_group[q];
counts=min(current_size,result_size-p);
copy(result[p],1,counts,1,0,-q);
p+=current_size;
remaining_counts[q]-=counts;
++q;
);
p=0;
q=last_group_id;
while(p<result_size,
current_size=quantity_of_items_in_group[q];
counts=min(current_size,result_size-p);
copy(final_perm[p],1,counts,1,0,-q);
p+=counts;
--q;
);
print(final_perm);
started=0;
);
started?(
last_p=p;
while(p<=final_perm[final_modify_pos],
++p;
if(p<=final_perm[final_modify_pos]?remaining_counts[p],
++remaining_counts[last_p];
--remaining_counts[p];
result[last_r_ind]=p;
break();
);
);
if(p>final_perm[final_modify_pos],
++remaining_counts[result[last_r_ind]];
for(q=start_modify_pos,q>final_modify_pos,--q,
if(result[q]<final_perm[final_modify_pos],
break();
);
++remaining_counts[result[q]];
);
last_p=p=result[q];
while(++p<=final_perm[final_modify_pos],
if(p<=final_perm[final_modify_pos]?remaining_counts[p],
++remaining_counts[last_p];
result[q]=p;
break();
);
);
--remaining_counts[result[q]];
p=0;++q;counts=0;
while(q<result_size,
while(p<final_perm[final_modify_pos],
if(counts=remaining_counts[p],break(););
++p;
);
counts=min(counts,result_size-q);
remaining_counts[p]-=counts;
copy(result[q],[p],counts,1,0);
q+=counts;
++p;
);
if(final_modify_pos<start_modify_pos,
if(result[final_modify_pos]==final_perm[final_modify_pos],
++final_modify_pos;
);
);
);
):(
started=1;
);
p=result[last_r_ind];
[result,remaining_counts];"
_rep_rde_npr_permutations_length:
(${2--1})
eval. <"begin(
const sec_size=$1+1;
dp=vector(#sec_size);
dp[0]=1;
);
new_dp=vector(#sec_size,0);
repeat(sec_size,t,
if(!dp[0],continue(););
maxj=min(i,$1-t);
repeat(maxj+1,j,
comb=perm(j,t+j,0);
new_dp[t+j]+=comb*dp[t];
);
);
dp=new_dp;
end(
set('{}',dp[$1]);
);
"
rm.
What’s the algorithm is about?
It’s about generating size-n permutations of multiset.
When the last indice reach the limit, it scan the other indices, and modify the array. There’s tracks of remaining colors. Right now, this part is bugged, and I have no idea why, nor I can explain the algorithm too well.
Results Test
C:\Windows\System32>gmic +rep_rde_npr_permutations 3,3,2,1 repeat whd { e {I[#-1,"$>"]} }
[gmic]./ Start G'MIC interpreter (v.3.6.0).
[gmic_math_parser] final_perm = (uninitialized) (mem[48]: vector3)
[gmic_math_parser] final_perm = [ 2,1,1 ] (size: 3)
0,0,0
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
1,0,0
1,0,1
1,0,2
1,1,0
1,1,2
1,2,0
1,2,1
2,0,0
2,0,1
2,1,0
2,1,1
[gmic]./ Display image [0] = '[>begin( quantity_of_items_in...'.
[0] = '[>begin( quantity_of_items_in_group=vmin([3,2,1],3); const ca...':
size = (19,1,1,3) [228 b of float32].
data = (0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2^0,0,0,1,1,1,2,2,0,0,0,1,1,2,2,0,0,1,1^0,1,2,0,1,2,0,1,0,1,2,0,2,0,1,0,1,0,1).
min = 0, max = 2, mean = 0.789474, std = 0.773139, coords_min = (0,0,0,0), coords_max = (15,0,0,0).
[gmic]./ End G'MIC interpreter.
C:\Windows\System32>gmic +rep_rde_npr_permutations 5,5,1,3,2 repeat whd { e {I[#-1,"$>"]} }
[gmic]./ Start G'MIC interpreter (v.3.6.0).
[gmic_math_parser] final_perm = (uninitialized) (mem[52]: vector5)
[gmic_math_parser] final_perm = [ 3,3,2,2,2 ] (size: 5)
0,0,0,0,0
0,0,0,0,1
0,0,0,0,2
0,0,0,0,3
0,0,0,1,0
0,0,0,1,2
0,0,0,1,3
0,0,0,2,0
0,0,0,2,1
0,0,0,2,2
0,0,0,2,3
0,0,0,3,0
0,0,0,3,1
0,0,0,3,2
0,0,0,3,3
0,0,1,0,0
0,0,1,0,2
0,0,1,0,3
0,0,1,2,0
0,0,1,2,2
0,0,1,2,3
0,0,1,3,0
0,0,1,3,2
0,0,1,3,3
0,0,2,0,0
0,0,2,0,1
0,0,2,0,2
0,0,2,0,3
0,0,2,1,0
0,0,2,1,2
0,0,2,1,3
0,0,2,2,0
0,0,2,2,1
0,0,2,2,2
0,0,2,2,3
0,0,2,3,0
0,0,2,3,1
0,0,2,3,2
0,0,2,3,3
0,0,3,0,0
0,0,3,0,1
0,0,3,0,2
0,0,3,0,3
0,0,3,1,0
0,0,3,1,2
0,0,3,1,3
0,0,3,2,0
0,0,3,2,1
0,0,3,2,2
0,0,3,2,3
0,0,3,3,0
0,0,3,3,1
0,0,3,3,2
0,1,0,0,0
0,1,0,0,2
0,1,0,0,3
0,1,0,2,0
0,1,0,2,2
0,1,0,2,3
0,1,0,3,0
0,1,0,3,2
0,1,0,3,3
0,1,2,0,0
0,1,2,0,2
0,1,2,0,3
0,1,2,2,0
0,1,2,2,2
0,1,2,2,3
0,1,2,3,0
0,1,2,3,2
0,1,2,3,3
0,1,3,0,0
0,1,3,0,2
0,1,3,0,3
0,1,3,2,0
0,1,3,2,2
0,1,3,2,3
0,1,3,3,0
0,1,3,3,2
0,2,0,0,0
0,2,0,0,1
0,2,0,0,2
0,2,0,0,3
0,2,0,1,0
0,2,0,1,2
0,2,0,1,3
0,2,0,2,0
0,2,0,2,1
0,2,0,2,2
0,2,0,2,3
0,2,0,3,0
0,2,0,3,1
0,2,0,3,2
0,2,0,3,3
0,2,1,0,0
0,2,1,0,2
0,2,1,0,3
0,2,1,2,0
0,2,1,2,2
0,2,1,2,3
0,2,1,3,0
0,2,1,3,2
0,2,1,3,3
0,2,2,0,0
0,2,2,0,1
0,2,2,0,2
0,2,2,0,3
0,2,2,1,0
0,2,2,1,2
0,2,2,1,3
0,2,2,2,0
0,2,2,2,1
0,2,2,2,3
0,2,2,3,0
0,2,2,3,1
0,2,2,3,2
0,2,2,3,3
0,2,3,0,0
0,2,3,0,1
0,2,3,0,2
0,2,3,0,3
0,2,3,1,0
0,2,3,1,2
0,2,3,1,3
0,2,3,2,0
0,2,3,2,1
0,2,3,2,2
0,2,3,2,3
0,2,3,3,0
0,2,3,3,1
0,2,3,3,2
0,3,0,0,0
0,3,0,0,1
0,3,0,0,2
0,3,0,0,3
0,3,0,1,0
0,3,0,1,2
0,3,0,1,3
0,3,0,2,0
0,3,0,2,1
0,3,0,2,2
0,3,0,2,3
0,3,0,3,0
0,3,0,3,1
0,3,0,3,2
0,3,1,0,0
0,3,1,0,2
0,3,1,0,3
0,3,1,2,0
0,3,1,2,2
0,3,1,2,3
0,3,1,3,0
0,3,1,3,2
0,3,2,0,0
0,3,2,0,1
0,3,2,0,2
0,3,2,0,3
0,3,2,1,0
0,3,2,1,2
0,3,2,1,3
0,3,2,2,0
0,3,2,2,1
0,3,2,2,2
0,3,2,2,3
0,3,2,3,0
0,3,2,3,1
0,3,2,3,2
0,3,3,0,0
0,3,3,0,1
0,3,3,0,2
0,3,3,1,0
0,3,3,1,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
0,3,3,2,1
0,3,3,2,2
0,3,3,2,0
[gmic]./ Display image [0] = '[>begin( quantity_of_items_in...'.
[0] = '[>begin( quantity_of_items_in_group=vmin([5,1,3,2],5); const ...':
size = (536,1,1,5) [10.5 Kio of float32].
data = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ... ,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0).
min = 0, max = 3, mean = 1.60299, std = 1.24845, coords_min = (0,0,0,0), coords_max = (131,0,0,1).
[gmic]./ End G'MIC interpreter.
See, it start breaking with second input. So, I have no idea why. I will probably try to generate it by hand and see why. It works well on first input.