How to do grouped MAX in ArrayFire? - max

Is there such a thing like
af::array groupedMax= af::Max(myValues, fromIndices, toIndices);
For example,
myValues= {random values}
fromIndices = {2, 7, 5}
toIndices = {10, 9, 12}
The result should be
groupedMax[0] will be max between myValues[2] and myValues[10]
groupedMax[1] will be max between myValues[7] and myValues[9]
groupedMax[2] will be max between myValues[5] and myValues[12]
Is this achievable? If not, any idea how to do this super fast on ArrayFire?
Edit: Here is a rough single threaded code I want to achieve.
vector<double> groupedMaxValues(fromIndices.size());
for(int g=0; g<fromIndices.size(); g++)
{
double maxVal = 0;
for(int i=fromIndices[g]; i<=toIndices[g]; i++)
{
if(maxVal < myValues[i])
{
maxVal = myValues[i];
}
}
groupedMaxValues[g] = maxVal;
}

I am not aware of what is a grouped max, but the operation of max between two af::arrays can be performed using the following
af::array a = myValues(fromIndices);
af::array b = myValues(toIndices);
af::array cond = a > b;
af::array mxd = cond * a + (1 - cond) * b;
In the above example, the two inputs a & b are just indexed arrays of myValues.
Update: (6th Sep, 2019)
After BoBoDev latest comment on this answer, here is the code I came up with following code snippet based on your explanation and it gives the correct output(shown after the code)
float v[] = {10.0f, 30.0f, 20.0f};
af::array myValues(3, 1, v);
int f4m[] = {10};
int to[] = {12};
af::array fromIndices(1, f4m);
af::array toIndices(1, to);
af_print(myValues);
af_print(fromIndices);
af_print(toIndices);
af::array a = myValues(fromIndices);
af::array b = myValues(toIndices);
af::array cond = a > b;
af::array mxd = cond * a + (1 - cond) * b;
af_print(mxd);
Output of sample
myValues
[3 1 1 1]
10.0000
30.0000
20.0000
fromIndices
[1 1 1 1]
10
toIndices
[1 1 1 1]
12
mxd
[1 1 1 1]
30.0000

Sorry,I was confused by the original description. Your serial code explains the Q in much better way.
I think what you are looking for is af::scanByKey - http://arrayfire.org/docs/group__scan__func__scanbykey.htm - although I am not yet sure on how to generate keys for your use case as the indices range (from-to) seem to overlap. The length of the ranges also doesn't seem to be same.

Related

Dynamic Programming: max sum through a a 2 column list, left column skips a row

To preface, my English is not quite perfect so apologies for any mistakes.
The problem goes as follows:
Given a list of two choices in each column, determine the maximum sum possible from choosing only one of the two options in the column. The twist is: if the bottom of the two values is chosen, the next column is entirely skipped.
Example:
5
9 3 5 7 3
5 8 1 4 5
If you were to choose 5 initially from [9, 5], the column [3, 8] would be skipped. Whereas, if 9 was chosen, the next column would NOT be skipped and you could choose from [3, 8] (if 8 was chosen, the next column would be skipped and if 3 was chosen, it would not be, etc).
When you attempt to solve this using DP, the most important aspect of the problem is to define the right states of the DP.
Define D[i][j] = maximum sum until index i, if u choose element j || j in [0,1]
L = [
[9, 3, 5, 7, 3],
[5, 8, 1, 4, 5]
]
def find_max_sum(L):
D = [[0, 0] for _ in range(len(L[0]))]
D[0][0] = max(L[0][0], 0)
D[0][1] = max(L[1][0], 0)
for i in range(1, len(D)):
D[i][0] = L[0][i] + max(D[i-1])
if i > 1:
D[i][1] = max(L[1][i] + max(D[i-2]), max(D[i-1]))
else:
D[i][1] = max(L[1][i], max(D[i-1]))
return max(D[-1])
print(find_max_sum(L))
Let N be the number of columns, then we can store our choices in an array a(2 X N).
And lets define a function f(i,j) which gives the maximum possible sum from the first j+1 columns(0,1...j) where in j-th column we either pick the first option(i=0) or we pick the second option(i=1).
So the answer to this problem will be max(f(i,j)) for each i=[0,1] and j=[0,1,...N-1].
For each column j we need to handle 2 cases:
1- choosing the first option ---> f(0,j)
2- choosing the second option ---> f(1,j)
To calculate the values of column j ( f(0,j) , f(1,j) ) we need to consider these cases for column j-1:
1- we picked the first option from column j-1
2- we did not pick any option from column j-1(means we picked the second option from column j-2)
note: we can not pick the second option from column j-1 because we are picking an option from column j according to our function definition.
Here is the code written in C++
int OO = 1e6;// a big value
//reading the input
int a[2][100];
int N; cin >> N;
for (int i = 0; i < N; i++) cin >> a[0][i];
for (int i = 0; i < N; i++) cin >> a[1][i];
//initialization
int f[2][100];
f[0][0] = a[0][0];
f[1][0] = a[1][0];
int result = max(f[0][0],f[1][0]);
for (int i = 1; i < N; i++) {
int val1 = f[0][i - 1];
int val2 = -OO;
if (i - 2 >= 0)
val2 = f[1][i - 2];
f[0][i] = max(val1, val2) + a[0][i];
f[1][i] = max(val1,val2) + a[1][i];
result = max(result, max(f[0][i], f[1][i]));
}
cout << result << endl;

Using a vector as column-indices into rows of a matrix, in Octave

Let's say I have a matrix A and a vector B. Is it possible to use the values in vector B as indices to select one value from each row in matrix A? Example:
A = [1, 2, 3;
4, 5, 6;
7, 8, 9;]
B = [1;3;1]
C = A(B) or C = A(:,B)
giving:
C = [1; 6; 7]
Of course I could do this with a for loop but with bigger matrices it will take a while. I would also like to use this to make a logical matrix in the following fashion:
A = zeros(3,3)
B = [1;3;1]
A(B) = 1
A = [1, 0, 0;
0, 0, 1;
1, 0, 0]
Thanks for any advice you are able to give me.
You need to create linear indices for that. Following your example:
octave-3.8.2> a = [1 2 3
4 5 6
7 8 9];
octave-3.8.2> b = [1 3 1];
octave-3.8.2> ind = sub2ind (size (a), 1:rows (a), b);
octave-3.8.2> c = a(ind)
c =
1 6 7
As per my understanding, the way to go about creating a logical matrix is below:
>A = eye(3,3)
>B = [1;3;1]
>A(B,:) =
>
>[ 1 0 0;
> 0 0 1;
> 1 0 0; ]

Mathematica: Thread::tdlen: Objects of unequal length in {Null} {} cannot be combined. >>

I have aproblem:
Thread::tdlen: Objects of unequal length in {Null} {} cannot be combined. >>
It seems to occur in the while test which makes no sense at all since I am onlu comparing numbers...?
The program is a program to solve the 0-1 knapsack dynamic programming problem though I use loops, not recursion.
I have put some printouts and i can only think that the problem is in the while loop and it doesnt make sense.
(* 0-1 Knapsack problem
item = {value, weight}
Constraint is maxweight. Objective is to max value.
Input on the form:
Matrix[{value,weight},
{value,weight},
...
]
*)
lookup[x_, y_, m_] := m[[x, y]];
generateTable[items_, maxweight_] := {
nbrofitems = Dimensions[items][[1]];
keep = values = Table[0, {j, 0, nbrofitems}, {i, 1, maxweight}];
For[j = 2, j <= nbrofitems + 1, j++,
itemweight = items[[j - 1, 2]];
itemvalue = items[[j - 1, 1]];
For[i = 1, i <= maxweight, i++,
{
x = lookup[j - 1, i, values];
diff = i - itemweight;
If[diff > 0, y = lookup[j - 1, diff, values], y = 0];
If[itemweight <= i ,
{If[x < itemvalue + y,
{values[[j, i]] = itemvalue + y; keep[[j, i]] = 1;},
{values[[j, i]] = x; keep[[j, i]] = 0;}]
},
y(*y eller x?*)]
}
]
];
{values, keep}
}
pickItems[keep_, items_, maxweight_] :=
{
(*w=remaining weight in knapsack*)
(*i=current item*)
w = maxweight;
knapsack = {};
nbrofitems = Dimensions[items][[1]];
i = nbrofitems + 1;
x = 0;
While[i > 0 && x < 10,
{
Print["lopp round starting"];
x++;
Print["i"];
Print[i];
Print["w"];
Print[w];
Print["keep[i,w]"];
Print[keep[[i, w]]];
If[keep[[i, w]] == 1,
{Append[knapsack, i];
Print["tjolahej"];
w -= items[[i - 1, 2]];
i -= 1;
Print["tjolahopp"];
},
i -= 1;
];
Print[i];
Print["loop round done"];
}
knapsack;
]
}
Clear[keep, v, a, b, c]
maxweight = 5;
nbrofitems = 3;
a = {5, 3};
b = {3, 2};
c = {4, 1};
items = {a, b, c};
MatrixForm[items]
results = generateTable[items, 5];
keep = results[[1]][[2]];
Print["keep:"];
MatrixForm[keep]
Print["------"];
results2 = pickItems[keep, items, 5];
MatrixForm[results2]
This is not really an answer to the specific question being asked, but some hints on general situations when this error occurs. The short answer is that this is a sign of passing lists of unequal lengths to some Listable function, user-defined or built-in.
Many of Mathematica's built-in functions are Listable(have Listable attribute). This basically means that, given lists in place of some or all arguments, Mathematica automatically threads the function over them. What really happens is that Thread is called internally (or, at least, so it appears). This can be illustrated by
In[15]:=
ClearAll[f];
SetAttributes[f,Listable];
f[{1,2},{3,4,5}]
During evaluation of In[15]:= Thread::tdlen: Objects of unequal length in
f[{1,2},{3,4,5}] cannot be combined. >>
Out[17]= f[{1,2},{3,4,5}]
You can get the same behavior by using Thread explicitly:
In[19]:=
ClearAll[ff];
Thread[ff[{1,2},{3,4,5}]]
During evaluation of In[19]:= Thread::tdlen: Objects of unequal length in
ff[{1,2},{3,4,5}] cannot be combined. >>
Out[20]= ff[{1,2},{3,4,5}]
In case of Listable functions, this is a bit more hidden though. Some typical examples would include things like {1, 2} + {3, 4, 5} or {1, 2}^{3, 4, 5} etc. I discussed this issue in a bit more detail here.
Try this version:
pickItems[keep_, items_, maxweight_] := Module[{},
{(*w=remaining weight in knapsack*)(*i=current item*)w = maxweight;
knapsack = {};
nbrofitems = Dimensions[items][[1]];
i = nbrofitems + 1;
x = 0;
While[i > 0 && x < 10,
{
Print["lopp round starting"];
x++;
Print["i"];
Print[i];
Print["w"];
Print[w];
Print["keep[i,w]"];
Print[keep[[i, w]]];
If[keep[[i, w]] == 1,
{
Append[knapsack, i];
Print["tjolahej"];
w -= items[[i - 1, 2]];
i -= 1;
Print["tjolahopp"];
},
i -= 1;
];
Print[i];
Print["loop round done"]
};
knapsack
]
}
]
no errors now, but I do not know what it does really :)

How to calculate the index (lexicographical order) when the combination is given

I know that there is an algorithm that permits, given a combination of number (no repetitions, no order), calculates the index of the lexicographic order.
It would be very useful for my application to speedup things...
For example:
combination(10, 5)
1 - 1 2 3 4 5
2 - 1 2 3 4 6
3 - 1 2 3 4 7
....
251 - 5 7 8 9 10
252 - 6 7 8 9 10
I need that the algorithm returns the index of the given combination.
es: index( 2, 5, 7, 8, 10 ) --> index
EDIT: actually I'm using a java application that generates all combinations C(53, 5) and inserts them into a TreeMap.
My idea is to create an array that contains all combinations (and related data) that I can index with this algorithm.
Everything is to speedup combination searching.
However I tried some (not all) of your solutions and the algorithms that you proposed are slower that a get() from TreeMap.
If it helps: my needs are for a combination of 5 from 53 starting from 0 to 52.
Thank you again to all :-)
Here is a snippet that will do the work.
#include <iostream>
int main()
{
const int n = 10;
const int k = 5;
int combination[k] = {2, 5, 7, 8, 10};
int index = 0;
int j = 0;
for (int i = 0; i != k; ++i)
{
for (++j; j != combination[i]; ++j)
{
index += c(n - j, k - i - 1);
}
}
std::cout << index + 1 << std::endl;
return 0;
}
It assumes you have a function
int c(int n, int k);
that will return the number of combinations of choosing k elements out of n elements.
The loop calculates the number of combinations preceding the given combination.
By adding one at the end we get the actual index.
For the given combination there are
c(9, 4) = 126 combinations containing 1 and hence preceding it in lexicographic order.
Of the combinations containing 2 as the smallest number there are
c(7, 3) = 35 combinations having 3 as the second smallest number
c(6, 3) = 20 combinations having 4 as the second smallest number
All of these are preceding the given combination.
Of the combinations containing 2 and 5 as the two smallest numbers there are
c(4, 2) = 6 combinations having 6 as the third smallest number.
All of these are preceding the given combination.
Etc.
If you put a print statement in the inner loop you will get the numbers
126, 35, 20, 6, 1.
Hope that explains the code.
Convert your number selections to a factorial base number. This number will be the index you want. Technically this calculates the lexicographical index of all permutations, but if you only give it combinations, the indexes will still be well ordered, just with some large gaps for all the permutations that come in between each combination.
Edit: pseudocode removed, it was incorrect, but the method above should work. Too tired to come up with correct pseudocode at the moment.
Edit 2: Here's an example. Say we were choosing a combination of 5 elements from a set of 10 elements, like in your example above. If the combination was 2 3 4 6 8, you would get the related factorial base number like so:
Take the unselected elements and count how many you have to pass by to get to the one you are selecting.
1 2 3 4 5 6 7 8 9 10
2 -> 1
1 3 4 5 6 7 8 9 10
3 -> 1
1 4 5 6 7 8 9 10
4 -> 1
1 5 6 7 8 9 10
6 -> 2
1 5 7 8 9 10
8 -> 3
So the index in factorial base is 1112300000
In decimal base, it's
1*9! + 1*8! + 1*7! + 2*6! + 3*5! = 410040
This is Algorithm 2.7 kSubsetLexRank on page 44 of Combinatorial Algorithms by Kreher and Stinson.
r = 0
t[0] = 0
for i from 1 to k
if t[i - 1] + 1 <= t[i] - 1
for j from t[i - 1] to t[i] - 1
r = r + choose(n - j, k - i)
return r
The array t holds your values, for example [5 7 8 9 10]. The function choose(n, k) calculates the number "n choose k". The result value r will be the index, 251 for the example. Other inputs are n and k, for the example they would be 10 and 5.
zero-base,
# v: array of length k consisting of numbers between 0 and n-1 (ascending)
def index_of_combination(n,k,v):
idx = 0
for p in range(k-1):
if p == 0: arrg = range(1,v[p]+1)
else: arrg = range(v[p-1]+2, v[p]+1)
for a in arrg:
idx += combi[n-a, k-1-p]
idx += v[k-1] - v[k-2] - 1
return idx
Null Set has the right approach. The index corresponds to the factorial-base number of the sequence. You build a factorial-base number just like any other base number, except that the base decreases for each digit.
Now, the value of each digit in the factorial-base number is the number of elements less than it that have not yet been used. So, for combination(10, 5):
(1 2 3 4 5) == 0*9!/5! + 0*8!/5! + 0*7!/5! + 0*6!/5! + 0*5!/5!
== 0*3024 + 0*336 + 0*42 + 0*6 + 0*1
== 0
(10 9 8 7 6) == 9*3024 + 8*336 + 7*42 + 6*6 + 5*1
== 30239
It should be pretty easy to calculate the index incrementally.
If you have a set of positive integers 0<=x_1 < x_2< ... < x_k , then you could use something called the squashed order:
I = sum(j=1..k) Choose(x_j,j)
The beauty of the squashed order is that it works independent of the largest value in the parent set.
The squashed order is not the order you are looking for, but it is related.
To use the squashed order to get the lexicographic order in the set of k-subsets of {1,...,n) is by taking
1 <= x1 < ... < x_k <=n
compute
0 <= n-x_k < n-x_(k-1) ... < n-x_1
Then compute the squashed order index of (n-x_k,...,n-k_1)
Then subtract the squashed order index from Choose(n,k) to get your result, which is the lexicographic index.
If you have relatively small values of n and k, you can cache all the values Choose(a,b) with a
See Anderson, Combinatorics on Finite Sets, pp 112-119
I needed also the same for a project of mine and the fastest solution I found was (Python):
import math
def nCr(n,r):
f = math.factorial
return f(n) / f(r) / f(n-r)
def index(comb,n,k):
r=nCr(n,k)
for i in range(k):
if n-comb[i]<k-i:continue
r=r-nCr(n-comb[i],k-i)
return r
My input "comb" contained elements in increasing order You can test the code with for example:
import itertools
k=3
t=[1,2,3,4,5]
for x in itertools.combinations(t, k):
print x,index(x,len(t),k)
It is not hard to prove that if comb=(a1,a2,a3...,ak) (in increasing order) then:
index=[nCk-(n-a1+1)Ck] + [(n-a1)C(k-1)-(n-a2+1)C(k-1)] + ... =
nCk -(n-a1)Ck -(n-a2)C(k-1) - .... -(n-ak)C1
There's another way to do all this. You could generate all possible combinations and write them into a binary file where each comb is represented by it's index starting from zero. Then, when you need to find an index, and the combination is given, you apply a binary search on the file. Here's the function. It's written in VB.NET 2010 for my lotto program, it works with Israel lottery system so there's a bonus (7th) number; just ignore it.
Public Function Comb2Index( _
ByVal gAr() As Byte) As UInt32
Dim mxPntr As UInt32 = WHL.AMT.WHL_SYS_00 '(16.273.488)
Dim mdPntr As UInt32 = mxPntr \ 2
Dim eqCntr As Byte
Dim rdAr() As Byte
modBinary.OpenFile(WHL.WHL_SYS_00, _
FileMode.Open, FileAccess.Read)
Do
modBinary.ReadBlock(mdPntr, rdAr)
RP: If eqCntr = 7 Then GoTo EX
If gAr(eqCntr) = rdAr(eqCntr) Then
eqCntr += 1
GoTo RP
ElseIf gAr(eqCntr) < rdAr(eqCntr) Then
If eqCntr > 0 Then eqCntr = 0
mxPntr = mdPntr
mdPntr \= 2
ElseIf gAr(eqCntr) > rdAr(eqCntr) Then
If eqCntr > 0 Then eqCntr = 0
mdPntr += (mxPntr - mdPntr) \ 2
End If
Loop Until eqCntr = 7
EX: modBinary.CloseFile()
Return mdPntr
End Function
P.S. It takes 5 to 10 mins to generate 16 million combs on a Core 2 Duo. To find the index using binary search on file takes 397 milliseconds on a SATA drive.
Assuming the maximum setSize is not too large, you can simply generate a lookup table, where the inputs are encoded this way:
int index(a,b,c,...)
{
int key = 0;
key |= 1<<a;
key |= 1<<b;
key |= 1<<c;
//repeat for all arguments
return Lookup[key];
}
To generate the lookup table, look at this "banker's order" algorithm. Generate all the combinations, and also store the base index for each nItems. (For the example on p6, this would be [0,1,5,11,15]). Note that by you storing the answers in the opposite order from the example (LSBs set first) you will only need one table, sized for the largest possible set.
Populate the lookup table by walking through the combinations doing Lookup[combination[i]]=i-baseIdx[nItems]
EDIT: Never mind. This is completely wrong.
Let your combination be (a1, a2, ..., ak-1, ak) where a1 < a2 < ... < ak. Let choose(a,b) = a!/(b!*(a-b)!) if a >= b and 0 otherwise. Then, the index you are looking for is
choose(ak-1, k) + choose(ak-1-1, k-1) + choose(ak-2-1, k-2) + ... + choose (a2-1, 2) + choose (a1-1, 1) + 1
The first term counts the number of k-element combinations such that the largest element is less than ak. The second term counts the number of (k-1)-element combinations such that the largest element is less than ak-1. And, so on.
Notice that the size of the universe of elements to be chosen from (10 in your example) does not play a role in the computation of the index. Can you see why?
Sample solution:
class Program
{
static void Main(string[] args)
{
// The input
var n = 5;
var t = new[] { 2, 4, 5 };
// Helping transformations
ComputeDistances(t);
CorrectDistances(t);
// The algorithm
var r = CalculateRank(t, n);
Console.WriteLine("n = 5");
Console.WriteLine("t = {2, 4, 5}");
Console.WriteLine("r = {0}", r);
Console.ReadKey();
}
static void ComputeDistances(int[] t)
{
var k = t.Length;
while (--k >= 0)
t[k] -= (k + 1);
}
static void CorrectDistances(int[] t)
{
var k = t.Length;
while (--k > 0)
t[k] -= t[k - 1];
}
static int CalculateRank(int[] t, int n)
{
int k = t.Length - 1, r = 0;
for (var i = 0; i < t.Length; i++)
{
if (t[i] == 0)
{
n--;
k--;
continue;
}
for (var j = 0; j < t[i]; j++)
{
n--;
r += CalculateBinomialCoefficient(n, k);
}
n--;
k--;
}
return r;
}
static int CalculateBinomialCoefficient(int n, int k)
{
int i, l = 1, m, x, y;
if (n - k < k)
{
x = k;
y = n - k;
}
else
{
x = n - k;
y = k;
}
for (i = x + 1; i <= n; i++)
l *= i;
m = CalculateFactorial(y);
return l/m;
}
static int CalculateFactorial(int n)
{
int i, w = 1;
for (i = 1; i <= n; i++)
w *= i;
return w;
}
}
The idea behind the scenes is to associate a k-subset with an operation of drawing k-elements from the n-size set. It is a combination, so the overall count of possible items will be (n k). It is a clue that we could seek the solution in Pascal Triangle. After a while of comparing manually written examples with the appropriate numbers from the Pascal Triangle, we will find the pattern and hence the algorithm.
I used user515430's answer and converted to python3. Also this supports non-continuous values so you could pass in [1,3,5,7,9] as your pool instead of range(1,11)
from itertools import combinations
from scipy.special import comb
from pandas import Index
debugcombinations = False
class IndexedCombination:
def __init__(self, _setsize, _poolvalues):
self.setsize = _setsize
self.poolvals = Index(_poolvalues)
self.poolsize = len(self.poolvals)
self.totalcombinations = 1
fast_k = min(self.setsize, self.poolsize - self.setsize)
for i in range(1, fast_k + 1):
self.totalcombinations = self.totalcombinations * (self.poolsize - fast_k + i) // i
#fill the nCr cache
self.choose_cache = {}
n = self.poolsize
k = self.setsize
for i in range(k + 1):
for j in range(n + 1):
if n - j >= k - i:
self.choose_cache[n - j,k - i] = comb(n - j,k - i, exact=True)
if debugcombinations:
print('testnth = ' + str(self.testnth()))
def get_nth_combination(self,index):
n = self.poolsize
r = self.setsize
c = self.totalcombinations
#if index < 0 or index >= c:
# raise IndexError
result = []
while r:
c, n, r = c*r//n, n-1, r-1
while index >= c:
index -= c
c, n = c*(n-r)//n, n-1
result.append(self.poolvals[-1 - n])
return tuple(result)
def get_n_from_combination(self,someset):
n = self.poolsize
k = self.setsize
index = 0
j = 0
for i in range(k):
setidx = self.poolvals.get_loc(someset[i])
for j in range(j + 1, setidx + 1):
index += self.choose_cache[n - j, k - i - 1]
j += 1
return index
#just used to test whether nth_combination from the internet actually works
def testnth(self):
n = 0
_setsize = self.setsize
mainset = self.poolvals
for someset in combinations(mainset, _setsize):
nthset = self.get_nth_combination(n)
n2 = self.get_n_from_combination(nthset)
if debugcombinations:
print(str(n) + ': ' + str(someset) + ' vs ' + str(n2) + ': ' + str(nthset))
if n != n2:
return False
for x in range(_setsize):
if someset[x] != nthset[x]:
return False
n += 1
return True
setcombination = IndexedCombination(5, list(range(1,10+1)))
print( str(setcombination.get_n_from_combination([2,5,7,8,10])))
returns 188

What is the output of this pseudocode?

procedure DoSomething(a_1, ... a_n)
p = a_1
for i = 2 to n
temp = p
for j = 1 to a_i
p = p * temp
DoSomething(10,2,2,2)
We are getting mixed results. One of us got 10^7, the other 10^27.
I Think I found my error... I keep substituting 10 for p every time, instead of the new value for temp.
EDIT: here's my work:
{10, 2, 2, 2}
p = 10
i = 2 to 4
temp = p = 10
j = 1 to 2
p = 10 * 10 = 10^2
p = 10^2 * 10 = 10^3
i = 3 to 4
temp = 10^3
j = 1 to 2
p = 10^3 * 10 = 10^4
p = 10^4 * 10 = 10^5
i = 4 to 4
temp = 10^5
j = 1 to 2
p = 10^5 * 10 = 10^6
p = 10^6 * 10 = 10^7
10^7
It's 10^27 as shown by this bit of python code:
a = [10,2,2,2]
p = a[0]
for i in range(1,len(a)):
temp = p
for j in range(a[i]):
p *= temp
print p
1,000,000,000,000,000,000,000,000,000
The problems with your code as posted are:
in your 10^7 solution, you're always multiplying by 10, not temp (which is increased to the final value of p after the j loop).
You're setting temp to arr[i], not p, in your PHP code (which I'll include here so my answer still makes sense after you edited it out of your question :-).
$arr = array(10, 2, 2, 2);
$p = $arr[0];
$temp = 0;
for($i = 1; $i <= 3; $i++)
{
$temp = $arr[$i];
for($j = 0; $j <= $arr[$i]; $j++)
{
$p = $p * $temp;
}
}
echo $p;
I entered the program into my TI-89 and got an answer of 1e27 for the value of p.
t(a)
Func
Local i,j,p,tmp
a[1]->p
For i,2,dim(a)
p->tmp
For j,1,a[i]
p*tmp->p
EndFor
EndFor
Return p
EndFunc
t({10,2,2,2}) 1.E27
Isn't it ((10^3)^4)^5 = 10 ^ 60 ?
Seems to be a function to calculate
(((a_1^(a_2+1))^(a_3+1))^(a_4+1)...
Thus we get ((10^3)^3)^3 = 10^(3^3) = 10^27
There is an error in your computation for 10^7, See below. The correct answer is 10^27
{10, 2, 2, 2}
p = 10
i = 2 to 4
temp = p = 10
j = 1 to 2
p = 10 * 10 = 10^2
p = 10^2 * 10 = 10^3
i = 3 to 4
temp = 10^3
j = 1 to 2
p = 10^3 * 10 = 10^4 -- p=p*temp, p=10^3 and temp=10^3, hence p=10^3 * 10^3.
p = 10^4 * 10 = 10^5 -- Similarly for other steps.
i = 4 to 4
temp = 10^5
j = 1 to 2
p = 10^5 * 10 = 10^6
p = 10^6 * 10 = 10^7
There's a reason folks have called Python "executable pseudocode":
>>> def doSomething(*args):
... args = list(args);
... p = args.pop(0)
... for i in range(len(args)):
... temp = p
... for j in range(args[i]):
... p *= temp
... return p
...
>>> print doSomething(10,2,2,2)
1000000000000000000000000000
In C:
#include <stdio.h>
double DoSomething(double array[], int count)
{
double p, temp;
int i, j;
p = array[0];
for(i=1;i<count;i++)
{
temp = p;
for(j=0; j<array[i];j++)
{
printf("p=%g, temp=%g\n", p, temp); /* useful to see what's going on */
p = p * temp;
}
}
return p; /* this isn't specified, but I assume it's the procedure output */
}
double array[4] = {10.0,2.0,2.0,2.0};
int main(void)
{
printf("%g\n", DoSomething(array, 4));
return 0;
}
And, as others have indicated, 10e27. Note that the above is very verbose from your pseudo code - it could be simplified in many ways.
I used the Tiny C Compiler - very small, lightweight, and easy to use for simple stuff like this.
-Adam

Resources