import cp.
main =>
% Weights = {1, 2, 3, 4, 5, 7, 8, 9, 10, 11},
Weights = {1,2,3,7,11,13,17,19,23,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113},
print("===========\n"),
time(go_kn(Weights,sum(Weights)//3, 1)),
printf("===========\n"),
time(go(Weights, sum(Weights)//3, 1)),
printf("===========\n"),
time(go_kn(Weights, sum(Weights)//4, 2)),
printf("===========\n"),
time(go(Weights, sum(Weights)//4, 2)),
printf("===========\n").
go(Weights,Target,Q) =>
printf("Constraint Solution Part %w\n",Q),
assign_bin1(Weights,Target,Bins,QE,L1),
solve($[ffd,min(QE),
report(printf("Found %w, %w %w\n", L1, QE, Bins))],
Bins),
Bin1Weights = [BW: I in 1..Weights.length, BW=Bins[I]*Weights[I],BW>0],
printf("Bin 1: %w ",Bin1Weights),
printf("CP Answer Part %d: %w\n",Q,prod(Bin1Weights)).
assign_bin1(Weights,Target,Bins,QE,L1) =>
N = length(Weights),
Bins = new_array(N),
Bins :: 0..1,
scalar_product(Weights, Bins, Target),
L1 #= sum(Bins), % for reporting bin1 size
QE #= prod([max(1,(Bins[I]*Weights[I])) : I in 1..N]). % Minimize QE = product of weights
go_kn(Weights,Target,Q) =>
printf("Knapsack Solution Part %w\n",Q),
knapsack(to_list(Weights),Target,Sack,Val),
printf("Bin 1: %w\n",Sack),
printf("Table Answer Part %d: %w\n",Q,second(Val)).
% Val = (Length of Sack, QE)
% Item is a list of weights
table(+,+,-,min)
knapsack(_,C,Sack,Val), C<=0 =>
Sack = [], Val = (1,1).
knapsack([_|L],C,Sack,Val), C > 0 ?=>
knapsack(L,C,Sack,Val).
knapsack([IWeight|L],C,Sack,Val), C >= IWeight =>
Sack = [IWeight|Sack1],
knapsack(L,C-IWeight,Sack1,Val1),
Val = (first(Val1)+1,second(Val1)*IWeight).