Can someone help me figure out the running time of this loop? I believe it is O(5nlogn).
for(int f = 0; f < Array.length; f++) {
F = Array[f];
for(int e = 0; e <= f; e++) {
E = Array[e];
for(int d = 0; d <= e; d++) {
D = Array[d];
for(int c = 0; c <= d; c++) {
C = Array[c];
for(int b = 0; b <= c; b++) {
B = Array[b];
for(int a = 0; a <= b; a++) {
A = Array[a];
}
}
}
}
}
}
Thanks
The answer is Θ(n6). I wrote a program to simulate the inner loop and record how many times a series of n executions occurs:
static void Main(string[] args)
{
int arrLength = 20;
int[] arr = new int[arrLength];
for (int f = 0; f < arrLength; f++)
{
for (int e = 0; e <= f; e++)
{
for (int d = 0; d <= e; d++)
{
for (int c = 0; c <= d; c++)
{
for (int b = 0; b <= c; b++)
{
//for (int a = 0; a <= b; a++)
arr[b] = arr[b] + 1;
}
}
}
}
}
for (int i = 0; i < arr.Length; i++)
{
Debug.WriteLine(string.Format("{0} execution: {1} time(s).", i + 1, arr[i]));
Console.WriteLine(string.Format("{0} execution: {1} time(s).", i + 1, arr[i]));
}
Console.ReadLine();
}
Running this with an arrLength of 1 gives:
1 execution: 1 time(s).
Running this with an arrLength of 2 gives:
1 execution: 5 time(s).
2 execution: 1 time(s).
Running this with an arrLength of 3 gives:
1 execution: 15 time(s).
2 execution: 5 time(s).
3 execution: 1 time(s).
As it turns out, the execution times always follow the same equation. At arrLength of 20, we get:
1 execution: 8855 time(s).
2 execution: 7315 time(s).
3 execution: 5985 time(s).
4 execution: 4845 time(s).
5 execution: 3876 time(s).
6 execution: 3060 time(s).
7 execution: 2380 time(s).
8 execution: 1820 time(s).
9 execution: 1365 time(s).
10 execution: 1001 time(s).
11 execution: 715 time(s).
12 execution: 495 time(s).
13 execution: 330 time(s).
14 execution: 210 time(s).
15 execution: 126 time(s).
16 execution: 70 time(s).
17 execution: 35 time(s).
18 execution: 15 time(s).
19 execution: 5 time(s).
20 execution: 1 time(s).
Plugging this into the awesome Online Encyclopedia of Integer Sequences, we get the Binomial coefficient binomial(n,4), which is this (the sequence starts at an offset of 4):
binomial(n,4)
n*(n-1)*(n-2)*(n-3)/24
0 = 0
1 = 0
2 = 0
3 = 0
4 = 1
5 = 5
6 = 15
7 = 35
...
If we look at the execution patterns output by my program above, we can rewrite it using a summation and this binomial sequence. For each integer i between 1 and n inclusive, we have the (n - i + 4)th number in the binomial(n,4) sequence, then multiplied by i, as the total number of executions. This is expressed as the following:
Substituting j = n - i + 1, and realizing that j goes from n downto 1, we can rewrite this equation as:
Relying on Wolfram Alpha to figure out this equation, I plugged in sum (n-j+1)(j+3)(j+2)(j+1)*j/24, j = 1 to n, and it came up with:
This is very obviously Θ(n6), so that is our answer.
The final equation is actually binomial(n,6), so for m loops, the number of executions of the innermost loop is probably binomial(n,m). For a given number of m loops, we have:
A good way to do this is to think about the space you're iterating over. If you think about it, the loops will iterate over nonnegative integral valuesof (a, b, c, d, e, f) where
n > f ≥ e ≥ d ≥ c ≥ b ≥ a
Each of these iterations does O(1) work (all loops just assign a variable, which takes O(1) work), so the question is how many possible values there are that satisfy the above formula. I'm going to claim it's Θ(n6), and will try to justify this with the rest of my answer.
First, note that the value certainly isn't any more than O(n6). All of a, b, c, d, e, and f range between 0 and n-1, so there's at most n different values for each. Therefore, the maximum possible number of values they can have is n6. This is not a tight bound, but it's certainly an upper bound. That gives us that the runtime is at most O(n6).
If we want to get a tighter bound, we have to work harder. To do this, I'm going to use the following fact:
1k + 2k + 3k + ... + nk = Θ(nk)
This is the sum of a geometric series, which is where it comes from.
This means that
sum(f from 0 to n-1)
sum (e from 0 to f)
sum (d from 0 to e)
sum (c from 0 to d)
sum (b from 0 to c)
sum (a from 0 to b)
1
= sum(f from 0 to n-1)
sum (e from 0 to f)
sum (d from 0 to e)
sum (c from 0 to d)
sum (b from 0 to c)
Theta(b)
= sum(f from 0 to n-1)
sum (e from 0 to f)
sum (d from 0 to e)
sum (c from 0 to d)
Theta(c^2)
= sum(f from 0 to n-1)
sum (e from 0 to f)
sum (d from 0 to e)
Theta(d^3)
= sum(f from 0 to n-1)
sum (e from 0 to f)
Theta(e^4)
= sum(f from 0 to n-1)
Theta(f^5)
= Theta(n^6)
Hope this helps!
Related
I have been trying to do Gauss jordan method in matrices in octave, and I have found diferent ways to call the function, but none works. How can I do that?
A=[1 -2 -1; -1 1 1; 1 1 5]
B=[1; 4; -3]
#format rat
#Transposta = transpose(A) #Transposta
#Inversa = inv(A) #Inversa
#Adjunta = det(A)*inv(A) #Adjunta se A tiver inversa
determinante = det(A) #Determinante.
Resultado = Gaussian(A)
Use the rref function...
A = [1 -2 -1; -1 1 1; 1 1 5]
B = [1; 4; -3]
C = [A, B]
[a, b] = rref(C)
Result
a = 1.0000 0 0 -7.1667
0 1.0000 0 -5.0000
0 0 1.0000 1.8333
More Info: https://docs.octave.org/v7.3.0/Basic-Matrix-Functions.html
I am created a double for loop in Rcpp to move up one cell all 1's in a column that has 5 in the next available cell. When I compile the code I don't get any error but the code does move 1's in the matrix, it just returns the same matrix. Let's take an original matrix, say named t:
5 1 1 1 1
1 5 5 5 1
5 5 1 5 5
5 0 0 5 1
5 5 0 1 1
after running the code up_rcpp(t,5,5), I should get the following results
1 5 1 1 1
5 5 1 5 1
5 5 5 5 1
5 0 0 5 5
5 1 0 1 1
Below is my rcpp code:
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
Rcpp::NumericMatrix up_rcpp(Rcpp::NumericMatrix main, int r, int c) {
Rcpp::NumericMatrix t = clone(main);
for (int j=0; j <= c-1; ++j) {
for (int i=0; i <= r-2; ++i){
if ((t(i,j) == 5) & (t(i+1, j) == 1))
{
main(i, j) = 1;
main(i + 1, j) = 5;
}
}
for (int i= r-1; i == r-1; ++i){
if ((t(i, j) == 5) & (t(1, j) == 1))
{
main(i, j) = 1;
main(1, j) = 5;
}
}
}
return main;
}
Maybe I'm a bit paranoid when I pass values to Rcpp, but I never allow my function to change what I pass either. But the clone(main) is necessary here to avoid changes to main changing t.
The last piece was to change the 1 indicies to 0 for the top row.
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
Rcpp::NumericMatrix up_rcpp(Rcpp::NumericMatrix main, int r, int c) {
Rcpp::NumericMatrix ans = clone(main);
Rcpp::NumericMatrix t = clone(main);
for (int j=0; j <= c-1; ++j) {
for (int i=0; i <= r-2; ++i){
if ((t(i,j) == 5) && (t(i+1, j) == 1))
{
ans(i, j) = 1;
ans(i + 1, j) = 5;
}
}
for (int i= r-1; i <= r-1; ++i){
if ((t(i, j) == 5) && (t(0, j) == 1))
{
ans(i, j) = 1;
ans(0, j) = 5;
}
}
}
return ans;
}
Which gives:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 1 1 1
[2,] 5 5 1 5 1
[3,] 5 5 5 5 1
[4,] 5 0 0 1 5
[5,] 5 1 0 5 1
This is different than your solution in column 4, but the way I understand the logic, this is correct.
I am just starting the R program. I have couple of questions.
I want to create for loop. For example; I created like this. But I want to, loop created every x value,
result = result + 2*n+1
for x = -1 result = 0
for x = 0 result = 0
for x = 1 result = 3
for x = 2 result = 6
# etc, until
x = 9 result = 27
result = 0
vector<-c(-1:9)
for (x in vector){
print(x)
x = x+1
n = as.integer(1)
if (x<=0){
result= 1
} else{
result = result + 2*n+1
}
}
print(result)
Is this it? The special cases for x <= 0 force the code to predict the special case when x already is above 0, meaning, x == 1.
n <- 1
vector <- -1:9
for (x in vector){
cat("x:", x, "\t")
if (x <= 0){
result <- 1
} else{
if(x == 1) result <- 0
result <- result + 2*n + 1
}
cat("result:", result, "\n")
}
#x: -1 result: 1
#x: 0 result: 1
#x: 1 result: 3
#x: 2 result: 6
#x: 3 result: 9
#x: 4 result: 12
#x: 5 result: 15
#x: 6 result: 18
#x: 7 result: 21
#x: 8 result: 24
#x: 9 result: 27
I'm trying to implement the floyd warshall algorithm but it won't work correctly.
What I want is the shortest path distances from one vertex to another written in a matrix d and the predecessors in a matrix pred. The input is an adjacency matrix which contains all of the edge weights.
function FloWa(C)
N = size(C)
n = min(C[1],C[2])
pred = -1*ones(C[1],C[2])
d = C
for k in 1:n
for i in 1:n
for j in 1:n
if d[i,j] > d[i,k] + d[k,j]
if pred[i,k] == -1
pred[i,j] = k
else
pred[i,j] = pred[k,j]
end
d[i,j] = d[i,k] + d[k,j]
end
if i == j && d[i,i] < 0
println("negative Dicycle")
end
end
end
end
return d, pred
end
When i am running my code with the matrix
A = [0 2 1 4 5 1; 1 0 4 2 3 4; 2 1 0 1 2 4; 3 5 2 0 3 3; 2 4 3 4 0 1; 3 4 7 3 1 0]
i don't get the right results.
For d i get the same matrix as A and pred is printed as an Array{Float64}(0,1).
I have not checked the implementation of the algorithm, but you seem to initialize pred and d incorrectly. Here is a way to do it that is I assume you indented:
n = size(C, 1) # get number of rows in C
#assert n == size(C, 2) # make sure that C is square or throw an error
pred = fill(-1, size(C)) # fill pred with -1 and make it have the same size as C
d = copy(C) # d is a copy of C
How can express this imperative function in a functional, array-based language like K (or Q)?
In sloppy C++:
vector<int> x(10), y(10); // Assume these are initialized with some values.
// BTW, 4 is just a const -- it's part of the algorithm and is arbitrarily chosen.
vector<int> result1(x.size() - 4 + 1); // A place to hold a resulting array.
vector<int> result2(x.size() - 4 + 1); // A place to hold another resulting array.
// Here's the code I want to express functionally.
for (int i = 0; i <= x.size() - 4; i++) {
int best = x[i + 0] - y[i + 0];
int bad = best;
int worst = best;
for(int j = 0; j < 4; j++) {
int tmp = x[i + j] - y[i + 0];
bad = min(bad, tmp);
if(tmp > best) {
best = tmp;
worst = bad;
}
}
result1[i] = best
result2[i] = worst
}
I would most like to see this in kdb and Q but other functional languages are welcome.
porting #silentbicycle's k directly to q yields
q)a:1+til 8
q)b:8#0
q){(max x;min x)}flip{4#y _ x}[a+b;]each til count a
4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8
another approach, slightly more vectorized (imao):
q){(max;min)#\:flip 4#'(til count x)_\:x+y}[a;b]
4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8
In Kona (an open-source K dialect):
First, set some example values (using same as the Clojure solution):
a:1+!8;b:8#0 / a is 1..8, b is eight 0s
Then:
{(|/x;&/x)}#+{4#y _ x}[a+b;]'!#a
Where a and b are your x and y variables above. (K makes a special case for the variables x, y, and z.)
To break that up a bit more:
maxmin:{(|/x;&/x)} / (max;min) pairs of x
get4:{4#y _ x} / next 4 from x, starting at y
/ with <4 remaining, will repeat; doesn't matter for min or max
/ maxmin applied to flipped results of get4(a-b) at each index 0..(length a)-1
maxmin#+get4[a-b;]'!#a
/ result
(4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8)
In Clojure (a dialect of Lisp):
(defn minmax [x y](map #(vector (- (apply max %1) %2) (- (apply min %1) %2)))(partition-all 4 1 x) y)
(minmax [1 2 3 4 5 6 7 8] [0 0 0 0 0 0 0 0])
will give
[([4 1] [5 2] [6 3] [7 4] [8 5] [8 6] [8 7] [8 8])`(result 1, result 2) as output..
Then
(map #(first %1) result) is result1
(map #(last %1) result) is result2