Multiple For Loop Iterations (Combination) with filter to achieve highest possible value - excel

I have a set of "Points" & it's "Value".
I want to get highest possible "Value" from combination of "Points".
Example:
My Target Point: 100
Point Value
1 111
2 222
3 333
4 444
5 555
6 666
7 777
8 888
9 999
10 1110
11 1221
12 1332
13 1443
14 1554
15 1665
16 1776
17 1887
18 1998
19 2109
20 2220
There can be TRILLIONS of combination but I need only those combinations upto "My Target Point" yielding Highest "Value".
Possible Answers:
1. (Point 16)*2 + (Point 17)*4 = 100
(Value 1776)*2 + (Value 1887)*4 = 11100
2. (Point 1)*100 = 100
(Value 111)*100 = 11100
& so on.....
So finally I need just one (any) combination with highest value.
amt2 = 0
For i20 = 0 To 5 ' (Max multiple -> 100/20 = 5)
For i19 = 0 To 5 ' (Max multiple -> 100/19 = 5)
For i18 = 0 To 5
For i17 = 0 To 5
For i16 = 0 To 6
For i15 = 0 To 6
For i14 = 0 To 7
For i13 = 0 To 7
For i12 = 0 To 8
For i11 = 0 To 9
For i10 = 0 To 10
For i9 = 0 To 11
For i8 = 0 To 12
For i7 = 0 To 14
For i6 = 0 To 16
For i5 = 0 To 20
For i4 = 0 To 25
For i3 = 0 To 33
For i2 = 0 To 50
For i1 = 0 To 100 ' (Max multiple -> 100/1 = 1)
point1 = (1 * i1) + (2 * i2) + (3 * i3) + (4 * i4) + (5 * i5) + (6 * i6) + (7 * i7) + (8 * i8) + (9 * i9) + (10 * i10) + (11 * i11) + (12 * i12) + (13 * i13) + (14 * i14) + (15 * i15) + (16 * i16) + (17 * i17) + (18 * i18) + (19 * i19) + (20 * i20))
If point1 <= 100 Then
amt1 = (111 * i1) + (222 * i2) + (333 * i3) + (444 * i4) + (555 * i5) + (666 * i6) + (777 * i7) + (888 * i8) + (999 * i9) + (1110 * i1 + (1221 * i11) + (1332 * i12) + (1443 * i13) + (1554 * i14) + (1665 * i15) + (1776 * i16) + (1887 * i17) + (1998 * i18) + (2109 * i19) + (2220 * i20)
If amt2 < amt1 Then
amt2 = amt1
<Save Combination Details>
End If
End If
Next i1
Next i2
Next i3
Next i4
Next i5
Next i6
Next i7
Next i8
Next i9
Next i10
Next i11
Next i12
Next i13
Next i14
Next i15
Next i16
Next i17
Next i18
Next i19
Next i20
Problem with my code is that it iterates through ALL possible combinations which takes lots of time & produce little result.

"Trillions" underestimates how much work your code is trying to do. Your code would pass through the innermost loop 1.94*10^21 times, which at the rate of 10 million passes per second (about the most VBA could give) would take over 6 million years. Instead, just use the Solver add-in to solve what is a fairly straightforward integer programming problem.
Set up your spreadsheet something like this:
Your data is in columns A:B, I added a new column of decision variables, a constraint cell in D2, and an objective function in E2.
The formula in D2 is:
=SUMPRODUCT(A2:A21,C2:C21)
and in E2 it is:
=SUMPRODUCT(B2:B21,C2:C21)
Then I simply ask the solver to find the maximum of cell E2 by changing cells C2:C21 subject to the two constraints that D2 <= 100 and that C2:C21 are integers. I keep the default setting that variables are assumed to be nonnegative, and tell the solver to use the Simplex method (which under the hood will use branch-and-bound for solving this ILP). The optimal solution according to the Solver (found in less than a second as opposed to 6 million years) is 10*Point1 + 6*Point15 with a total value of 11100 -- which happens to be a value that you have already found, showing that this problem has multiple optima.
It is possible but not easy to do this all in VBA, since the solver add-in can be invoked in code. See this for a basic introduction.

Related

Creating forumla for sum of products in excel

I need help creating a formula for row 8 that will give me the sum of the products for cost * quantity of that month. The spreadsheet I am working with is 50+ columns and 1100+ rows.
The hand calculation for this is
B8 = (5 * 10) + (1 * 0) + (10 * 0) + (3 * 0) + (6 * 3 ) = 68
C8 = (5 * 0) + (1 * 0) + (10 * 3) + (3 * 8) + (6 * 0) = 54
D8 = (5 * 0) + (1 * 0) + (10 * 0) + (3 * 0) + (6 * 3) = 5
etc
In B8: =$a2*b$2+$a3*b$3+$a4*b$4+$a5*b$5+$a6*b$6
Once entered just drag to right to column F.
Due to order of operations parenthesis are not required but could be included for clarity.
HTH

Algorithm to generate a unique string of a certain format

I would like to generate a sequence of strings in the same format of digits and letters positions
e.g ABC12,DEV45,UED23,...
It's also required a formula to generate the next string from the current one. for example from the string above:
f(ABC12)=DEV45
f(DEV45)=UED23
I would like to use this to generate next "look-random" unique code in a defined format. What algorithm do you suggest? Thanks a lot.
A code of the format "ABC12" is basically a 5-digit number where the first 3 digits are base-26 and the last 2 digits are decimal. There are 26×26×26×10×10 or 1,757,600 of these. Each code is easily converted to the corresponding number and back:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
ABC12 = ((( 0 * 26 + 1) * 26 + 2) * 10 + 1) * 10 + 2 = 2,812
DEV45 = ((( 3 * 26 + 4) * 26 + 21) * 10 + 4) * 10 + 5 = 215,345
UED23 = (((20 * 26 + 4) * 26 + 3) * 10 + 2) * 10 + 3 = 1,362,723
2,812 / 10 = 281 rem: 2
281 / 10 = 28 rem: 1
28 / 26 = 1 rem: 2
1 / 26 = 0 rem: 1
0 / 26 = 0 rem: 0 -> 0 1 2 1 2 -> ABC12
215,345 / 10 = 21,534 rem: 5
21,534 / 10 = 2,153 rem: 4
2,153 / 26 = 82 rem: 21
82 / 26 = 3 rem: 4
3 / 26 = 0 rem: 3 -> 3 4 21 4 5 -> DEV45
1,362,723 / 10 = 136,272 rem: 3
136,272 / 10 = 13,627 rem: 2
13,627 / 26 = 524 rem: 3
524 / 26 = 20 rem: 4
20 / 26 = 0 rem: 20 -> 20 4 3 2 3 -> UED23
To loop through the numbers from 0 to 1,757,599 in a pseudo-random way, choose a step size which only returns to zero after having gone through every number, and then calculate the next value as:
x -> (x + step) % 1,757,600
So step should have no common factors with 1,757,600:
1,757,600 = 2 * 2 * 2 * 2 * 2 * 5 * 5 * 13 * 13 * 13
and preferably be greater than 26*26*10*10 so that every digit changes with every step; so, e.g.:
step = 3^11 = 177,147
which gives this sequence:
2,812 ABC12
( 2,812 + 177,147) % 1,757,600 = 179,959 -> CRF59
(179,959 + 177,147) % 1,757,600 = 357,106 -> FHJ06
...
Here's a code example to demonstrate the method. It's a bit fiddly because JavaScript. In C-like languages where a string is basically an array of integers, the code will be more straightforward.
function nextCode(current) {
var base = [26,26,26,10,10], symbol = [65,65,65,48,48], char = [], number = 0;
for (var i = 0; i < 5; i++) {
var digit = current.charCodeAt(i) - symbol[i];
number = number * base[i] + digit;
}
number = (number + 177147) % 1757600;
for (var i = 4; i >= 0; i--) {
var remainder = number % base[i];
number = (number - remainder) / base[i];
char[i] = String.fromCharCode(symbol[i] + remainder);
}
return char.join('');
}
document.write("ABC12 → " + nextCode("ABC12"));
One of the approaches is to precalculate letter part in an array form and then combine it with the consecutive numbers. For the letter array:
start with AAA, AAB, AAC, ..., ABA, ABB, ..., ZZZ (total 17576 elements) -- all possible unique combinations;
shuffle the array -- now they are in (a) random and (b) predictive order;
from any given value -> use the next element from the array.
For the digit part, use simple counting:
start with 00;
from any given value -> increment by 1;
if the result is 100, use the next letter part -- thus each string is unique.
This provides 1757600 unique strings like ABC12.

Excel: why is the average of divisions different from division of sums?

So lets say I have two variables x and y. I calculate the total sum of each variable.
I calculate y/x for each row and also calculate y/x for the sum of both x and y columns (280/10=28).
I would expect this value (28) to be equal to the average of y/x (230/4=32.5), but it is different.
This might have a simple explanation, but I can't seem to find it.
Thanks in advance
This is really a mathematics question. The two are not equal:
10 200 30 40
─── + ──── + ─── + ───
10 + 200 + 30 + 40 1 2 3 4
────────────────── ≠ ────────────────────────
1 + 2 + 3 + 4 4
There really is no reason why they could be expected to be the same: when the second expression is rewritten with one common denominator, it becomes even more evident there is little it has in common with the first expression.
To get a common denominator, one finds the least common denominator, which in this case is 12, and so the second expression could be written as follows:
120 1200 120 120
──── + ──── + ──── + ────
12 12 12 12
──────────────────────────
4
Which is simplified to:
120 + 1200 + 120 + 120 5 + 50 + 5 + 5 65
────────────────────── = ────────────── = ── = 32.5
48 2 2
There clearly is no relation with the first expression.
What is equal?
10 + 200 + 30 + 40 AVG(10, 200, 30, 40)
────────────────── = ────────────────────
1 + 2 + 3 + 4 AVG(1, 2, 3, 4)
This works because you really divide both numerator and denominator with the same factor (4), which is a null-operation.

Evaluating recursive function in Haskell

I am given this function and asked to manually evaluate g 5. I found the answer to be 25, but this is incorrect. The correct answer is 63. Would anyone help me understand why? Thanks
g :: Int -> Int
g n
| n==0 = 1
| otherwise = 2 * g (n-1) + 1
My answer: (2*4+1) + (2*3+1) + (2*2+1) + (2*1+1) + 1 = 25
You just need to think it out step by step:
(g 5) = 2 * (g 4) + 1
(g 4) = 2 * (g 3) + 1
(g 3) = 2 * (g 2) + 1
(g 2) = 2 * (g 1) + 1
(g 1) = 2 * (g 0) + 1
(g 0) = 1
Then, plug in the values from the bottom-up:
2 * 1 + 1 = 3
2 * 3 + 1 = 7
2 * 7 + 1 = 15
2 * 15 + 1 = 31
2 * 31 + 1 = 63
Your problem is that you were using the raw value of n, instead of what (g n) returned at the end of the recursion.
In your calculation you messed up with the nesting of the terms. They should be nested and not summed up separately.
The way to evaluate such functions is to replace function applications with the body of the function with its parameters replaced by the given arguments. I will do the first few steps and then you can take over:
g 5
if 5 == 0 then 1 else 2 * g (5-1) + 1
2 * g (5-1) + 1
2 * (if (5 - 1) == 0 then 1 else 2 * g ((5-1) - 1) + 1) + 1
2 * (if 4 == 0 then 1 else 2 * g (4-1) + 1) + 1
2 * (2 * g (4-1) + 1) + 1
...
63
#Carcigenicate's answer is of course easier to calculate, but this technique is more universal and more inline with how the code actually works.
Although this isn't your question, it's fairly easy to show by induction that
g n = 2^(n+1)-1
So
g 5 = 2^6 - 1 --> 63
Your parenthesization is wrong. Not doing any reductions (other than expanding g), we get
g 5
= 2 * g 4 + 1
= 2 * (2 * g 3 + 1) + 1
= 2 * (2 * (2 * g 2 + 1) + 1) + 1
= 2 * (2 * (2 * (2 * g 1 + 1) + 1) + 1) + 1
= 2 * (2 * (2 * (2 * (2 * g 0 + 1) + 1) + 1) + 1) + 1
= 2 * (2 * (2 * (2 * (2 * 1 + 1) + 1) + 1) + 1) + 1

Is there a way to do a nested FOR loop in Excel?

If have the following two columns with the values:
A B
1 1
2 2
3 3
4 4
How can I multiply and return the sum:
1* 1 + 1 * 2 + 1* 3 + 1 * 4 + 2 * 1 + 2 * 2 + ... 4 * 4
exactly like a nested FOR loop?
Similarly, how can I multiply and sum only when first column value is bigger than second:
2 * 1 + 3 * 1 + 3 * 2 + 4 * 1 + 4 * 2 + 4 * 3 ?
With formula I think what is required, assuming A1:E1 and A1:A4 as shown, may be:
(1) The sum of B1:E4 where B2 copied across and down is:
=$A2*B$1
Alternatively the array formula with layout as you show:
=SUM(MMULT(A2:A5,TRANSPOSE(B2:B5)))
answer 100, and
(2) in B2 copied across and down and then B2:E4 summed:
=IF($A2>B$1,$A2*B$1,0)
answer 35.

Resources