I want to solve a mathematical problem in a fastest possible way.
I have a set of natural numbers between 1 to n, for example {1,2,3,4,n=5} and I want to calculate a formula like this:
s = 1*2*3*4+1*2*3*5+1*2*4*5+1*3*4*5+2*3*4*5
as you can see, each element in the sum is a multiplications of n-1 numbers in the set. For example in (1*2*3*4), 5 is excluded and in (1*2*3*5), 4 is excluded. I know some of the multiplications are repeated, for example (1*2) is repeated in 3 of the multiplications. How can I solve this problem with least number of multiplications.
Sorry for bad English.
Thanks.
Here is a way that does not "cheat" by replacing multiplication with repeated addition or by using division. The idea is to replace your expression with
1*2*3*4 + 5*(1*2*3 + 4*(1*2 + 3*(1 + 2)))
This used 9 multiplications for the numbers 1 through 5. In general I think the multiplication count would be one less than the (n-1)th triangular number, n * (n - 1) / 2 - 1. Here is Python code that stores intermediate factorial values to reduce the number of multiplications to just 6, or in general 2 * n - 4, and the addition count to the same (but half of them are just adding 1):
def f(n):
fact = 1
term = 2
sum = 3
for j in range(2, n):
fact *= j
term = (j + 1) * sum
sum = fact + term
return sum
The only way to find which algorithm is the fastest is to code all of them in one language, and run each using a timer.
The following would be the most straightforward answer.
def f(n):
result = 0
nList = [i+1 for i in range(n)]
for i in range(len(nList)):
result += reduce(lambda x, y: x*y,(nList[:i]+nList[i+1:]))
return result
Walkthrough - use the reduce function to multiply all list's of length n-1 and add to the variable result.
If you just want to minimise the number of multiplications, you can replace all the multiplications by additions, like this:
// Compute 1*2*…*n
mult_all(n):
if n = 1
return 1
res = 0
// by adding 1*2*…*(n-1) an entirety of n times
for i = 1 to n do
res += mult_all(n-1)
return res
// Compute sum of 1*2*…*(i-1)*(i+1)*…*n
sum_of_mult_all_but_one(n):
if n = 1
return 0
// by computing 1*2*…*(n-1) + (sum 1*2*…*(i-1)*(i+1)*…*(n-1))*n
res = mult_all(n-1)
for i = 1 to n do
res += sum_of_mult_all_but_one(n-1)
return res
Here is an answer that would work with javascript. It is not the fastest way because it is not optimized, but it should work if you want to just find the answer.
function combo(n){
var mult = 1;
var sum = 0;
for (var i = 1; i <= n; i++){
mult = 1;
for (var j = 1; j<= n; j++){
if(j != i){
mult = mult*j;
}
}
sum += mult;
}
return (sum);
}
alert(combo(n));
I have a 4x4 grid full of letters. How can I calculate all possible routes from any point to any point that consist of 2 to 10 points?
All points within a route must be connected to another point within the same route vertically, horizontally or diagonally. For example you can go from A to B, A to E and A to F but not A to C.
Each point can be used only once in a route.
Here's an example of 25 possible permutations:
+---+---+---+---+
| A | B | C | D |
+---+---+---+---+
| E | F | G | H |
+---+---+---+---+
| I | J | K | L |
+---+---+---+---+
| M | N | O | P |
+---+---+---+---+
- AB
- ABC
- ABCD
- ABCDH
- ABCDHG
- ABCDHGF
- ABCDHGFE
- ABCDHGFEI
- ABCDHGFEIJ
- AE
- AEI
- AEIM
- AEIMN
- AEIMNJ
- AEIMNJF
- AIEMNJFB
- AIEMNJFBC
- AIEMNJFBCG
- AFKP
- PONM
- FGKL
- NJFB
- MNJGD
Now I should clear the question. I'm not asking HOW to get all the permutations. I'm asking what is the total amount of the possible permutations (i.e. an integer) and how to calculate it.
As mentioned in the comments the question can be answered with basic DFS in java starting at top left at (0,0)
EDIT: I added if(count(visited)>10) return; for the constraint
static int count=0;
static int count(boolean[][] b){
int r = 0;
for(int i=0;i<b.length;i++){
for(int j=0;j<b[0].length;j++){
if(b[i][j]) r++;
}
}
return r;
}
static boolean[][] copy(boolean[][] arr){
boolean [][] r = new boolean[arr.length][];
for(int i = 0; i < arr.length; i++)
r[i] = arr[i].clone();
return r;
}
static void dfs(int i, int j,boolean[][] visited) {
visited[i][j] = true;
if(count(visited)>10) return;
count++;
for (int k=-1;k<2;k++) {
for (int l=-1;l<2;l++) {
int r = i+k;
int c = j+l;
if (r>-1 && r<visited.length && c>-1 && c<visited.length && !visited[r][c]){
dfs(r,c,copy(visited));
}
}
}
}
public static void main(String args[]) {
boolean[][] visited = {
{false, false, false, false},
{false, false, false, false},
{false, false, false, false},
{false, false, false, false}
};
// dfs(row,column,initialize all to false)
dfs(0,0,visited);
System.out.println(count-1);
}
The above script just goes through each permutation and increments count every time since this includes the starting point (for example (0,0)) i have at the bottom count-1
Output: 105837 (edited from my incorrect original 1012519)
for 2x2 starting at same place i get 15. Which you can see from running
static int count=0;
static int count(boolean[][] b){
int r = 0;
for(int i=0;i<b.length;i++){
for(int j=0;j<b[0].length;j++){
if(b[i][j]) r++;
}
}
return r;
}
static boolean[][] copy(boolean[][] arr){
boolean [][] r = new boolean[arr.length][];
for(int i = 0; i < arr.length; i++)
r[i] = arr[i].clone();
return r;
}
static void dfs(int i, int j,boolean[][] visited,String str) {
visited[i][j] = true;
if (count(visited)>10) return;
count++;
str+="("+i+","+j+")";
System.out.println(str+": "+count);
for (int k=-1;k<2;k++) {
for (int l=-1;l<2;l++) {
int r = i+k;
int c = j+l;
if (r>-1 && r<visited.length && c>-1 && c<visited.length && !visited[r][c]){
dfs(r,c,copy(visited),str);
}
}
}
}
public static void main(String args[]) {
boolean[][] visited = {
{false, false},
{false, false}
};
dfs(0,0,visited,"");
// "count-1" to account for the starting position
System.out.println(count-1);
}
Output:
(0,0): 1
(0,0)(0,1): 2
(0,0)(0,1)(1,0): 3
(0,0)(0,1)(1,0)(1,1): 4
(0,0)(0,1)(1,1): 5
(0,0)(0,1)(1,1)(1,0): 6
(0,0)(1,0): 7
(0,0)(1,0)(0,1): 8
(0,0)(1,0)(0,1)(1,1): 9
(0,0)(1,0)(1,1): 10
(0,0)(1,0)(1,1)(0,1): 11
(0,0)(1,1): 12
(0,0)(1,1)(0,1): 13
(0,0)(1,1)(0,1)(1,0): 14
(0,0)(1,1)(1,0): 15
(0,0)(1,1)(1,0)(0,1): 16
15
the same script with 4x4 instead last 6 lines of output are:
(0,0)(1,1)(2,2)(3,3)(3,2)(3,1)(3,0)(2,1)(1,2)(0,3): 105834
(0,0)(1,1)(2,2)(3,3)(3,2)(3,1)(3,0)(2,1)(1,2)(1,3): 105835
(0,0)(1,1)(2,2)(3,3)(3,2)(3,1)(3,0)(2,1)(1,2)(2,3): 105836
(0,0)(1,1)(2,2)(3,3)(3,2)(3,1)(3,0)(2,1)(2,0): 105837
(0,0)(1,1)(2,2)(3,3)(3,2)(3,1)(3,0)(2,1)(2,0)(1,0): 105838
105837
The requirements for your problem are complex enough that I doubt there is a simple mathematical calculation--at least I cannot think of one. Here is recursive Python code to find your path count.
SIDE = 4 # Length of side of grid
MAXLEN = 10 # Maximum path length allowed
SIDE2 = SIDE + 2
DIRS = ( # offsets for directions
-1 * SIDE2 - 1, # up & left
-1 * SIDE2 + 0, # up
-1 * SIDE2 + 1, # up & right
0 * SIDE2 - 1, # left
0 * SIDE2 + 1, # right
1 * SIDE2 - 1, # down & left
1 * SIDE2 + 0, # down
1 * SIDE2 + 1, # down & right
)
def countpaths(loc, pathlen):
"""Return the number of paths starting at the point indicated by
parameter loc of length at most parameter pathlen, not repeating
points or using points marked False in global variable isfree[]."""
global isfree
pathcnt = 1 # count sub-path of just this one point
if pathlen > 1:
isfree[loc] = False
for dir in DIRS:
if isfree[loc + dir]:
pathcnt += countpaths(loc + dir, pathlen - 1)
isfree[loc] = True
return pathcnt
# Init global boolean array variable to flag which points are still available
isfree = [1 <= r <= SIDE and 1 <= c <= SIDE
for r in range(SIDE2) for c in range(SIDE2)]
# Use the symmetries of the square grid to find count of paths in grid
allpathcnt = 0
for r in range(1, (SIDE + 1) // 2 + 1): # do a triangular slice of the grid
for c in range(1, r + 1):
# Find the number of similar (by symmetry) points in the grid
if 2 * r - 1 == SIDE:
if r == c:
sym = 1 # center of entire grid
else:
sym = 4 # center of column
else:
if r == c:
sym = 4 # diagonal
else:
sym = 8 # other
# Add paths starting at this kind of point removing those of length 1
allpathcnt += sym * (countpaths(r * SIDE2 + c, MAXLEN) - 1)
print('Total path count is ' + str(allpathcnt))
This code takes into account the requirement that paths have lengths between 2 and 10 by limiting the path length to 10 and removing the paths of length 1. The requirement that points are not repeated is fulfilled by using array isfree[] to note which points are still free (True) and which are already used or should not be used (False).
Python is a somewhat slow language, so I increased speed by moving some calculations out of the inner recursions. I used a surrounding border of always-False points around your 4x4 grid, removing the need for explicit bounds checking. I used a one-dimensional list rather than two-dimensional and pre-coded the offsets from each cell to neighboring cells in constant DIRS (for "directions"). I used a final optimization by not using all 16 starting points. There are 4 corner points like A, 8 side points like B, and 4 center points like F, so I just found the numbers of paths from A, B, and F and calculated what the total would be for starting at all points.
This version of my code can handle any size square grid and maximum path length. I checked my code by varying SIDE and MAXLEN separately to 1, 2, and 3, and checking the results for each point by hand.
The final answer I get is
1626144
I was interested to note that the section of code taking the most space is the part that determines the symmetries of a point in the grid. I have found other, more concise ways to do this, but they are all much less readable.
I'm trying to write a function of the type:
pascal : int * int -> int
where the pair of ints represent the row and column, respectively, of Pascal's triangle.
Here's my attempt:
fun pascal(i : int, j : int) : int =
if (i = 0 andalso j = 0) orelse i = j orelse i = 0
then 1
else
pascal(i - 1, j - 1) + pascal(i - 1, j);
It works for my base cases but gives me strange output otherwise. For instance:
pascal(4, 2) gives me 11 and pascal(4, 1) gives me 15
It's a bit strange because, as long as the if clause fails and the else gets evaluated, I do want to return the sum of the element one row above and the element one row above and one element to the left.
What am I doing wrong?
Consider pascal 1 0. If you're using zero-based indexing for the table then this should be equal to 1. But:
pascal 1 0 = pascal 0 -1 + pascal 0 0 = 2
You should put some guards to deal with negative indices and indices where j is greater than i.
the problem is about coin change - "how many ways you can change 3,5,10 dollars
if you have 5c,10c ......
"http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=83
the problem is solved many times on various blogs( solution here )
In dp, the hardest thing is to understand the relation between subproblems and get the formula(optimal substructure)
I only give the actual for loop that stores the ways into 2d table like the solution:
for (int i = 2; i <= NCHANGES; ++i){
for (int m = 1; m <= MAX_AMOUNT; ++m){
if (m >= coins[i])
n[i][m] = n[i-1][m] + n[i][m - coins[i]];
else
n[i][m] = n[i-1][m];
}
}
=================================
The actual important code:
if (m >= coins[i])
n[i][m] = n[i-1][m] + n[i][m - coins[i]];
else
n[i][m] = n[i-1][m];
My thinking.
for example:
(else case)
I have the amount 5 cents and 1 coin to use : 5c. there is only 1 way : 5c = 1 * 5c
(store n[5][coin(5)])
I have the amount 5c and 2 coins to use : 5c and 10c i can't use BOTH 5C and 10c => i go back to 1 WAY of doing it ( store 1 in the table for n[5][coin(5,10)])
for this case
that's why n[i][m] = n[i-1][m]
can you explain the first if case? n[i][m] = n[i-1][m] + n[i][m - coins[i]]?
Ok, i found it on a website - same problem.
The coin change recurrence:
a[i][j] = a[i-1][j] (d[i] > j)
(If the coin can't be used, then don't use it)
a[i][j] = a[i-1][j] + a[i][j-d[i]] (d[i] <= j)
(If the coin can be used: don't use OR use it)
I have been trying to get my head around this perticular complexity computation but everything i read about this type of complexity says to me that it is of type big O(2^n) but if i add a counter to the code and check how many times it iterates per given n it seems to follow the curve of 4^n instead. Maybe i just misunderstood as i placed an count++; inside the scope.
Is this not of type big O(2^n)?
public int test(int n)
{
if (n == 0)
return 0;
else
return test(n-1) + test(n-1);
}
I would appreciate any hints or explanation on this! I completely new to this complexity calculation and this one has thrown me off the track.
//Regards
int test(int n)
{
printf("%d\n", n);
if (n == 0) {
return 0;
}
else {
return test(n - 1) + test(n - 1);
}
}
With a printout at the top of the function, running test(8) and counting the number of times each n is printed yields this output, which clearly shows 2n growth.
$ ./test | sort | uniq -c
256 0
128 1
64 2
32 3
16 4
8 5
4 6
2 7
1 8
(uniq -c counts the number of times each line occurs. 0 is printed 256 times, 1 128 times, etc.)
Perhaps you mean you got a result of O(2n+1), rather than O(4n)? If you add up all of these numbers you'll get 511, which for n=8 is 2n+1-1.
If that's what you meant, then that's fine. O(2n+1) = O(2⋅2n) = O(2n)
First off: the 'else' statement is obsolete since the if already returns if it evaluates to true.
On topic: every iteration forks 2 different iterations, which fork 2 iterations themselves, etc. etc. As such, for n=1 the function is called 2 times, plus the originating call. For n=2 it is called 4+1 times, then 8+1, then 16+1 etc. The complexity is therefore clearly 2^n, since the constant is cancelled out by the exponential.
I suspect your counter wasn't properly reset between calls.
Let x(n) be a number of total calls of test.
x(0) = 1
x(n) = 2 * x(n - 1) = 2 * 2 * x(n-2) = 2 * 2 * ... * 2
There is total of n twos - hence 2^n calls.
The complexity T(n) of this function can be easily shown to equal c + 2*T(n-1). The recurrence given by
T(0) = 0
T(n) = c + 2*T(n-1)
Has as its solution c*(2^n - 1), or something like that. It's O(2^n).
Now, if you take the input size of your function to be m = lg n, as might be acceptable in this scenario (the number of bits to represent n, the true input size) then this is, in fact, an O(m^4) algorithm... since O(n^2) = O(m^4).