Understanding Cyclomatic complexity of a simple condition - algorithm

I am trying to understand the cyclomatic complexity concept and came across in web that the cyclomatic complexity for below code (pseudo) is 3, but I thought, as there are 4 possible test scenarios, cyclomatic complexity has to be 4
If (Condition 1)
Statement 1
Else
Statement 2
If (Condition 2)
Statement 3
Else
Statement 4
Could you please help me understand.
Thanks
4 possible test scenarios are:
condition1 = true, condition2 = true;
condition1 = true, condition2 = false;
condition1 = false, condition2 = true;
condition1 = false, condition2 = false;

I think you confused between path coverage and cyclomatic complexity
cyclomatic complexity <= number of paths
https://en.wikipedia.org/wiki/Cyclomatic_complexity

Related

Implementing isPrime in Scala using tail recursion

I'm working on an exercise which requires me to implement isPrime in scala using tail recursion. I do have an implementation however, I'm having issues with producing the right base case.
So my algorithm involves checking all numbers from 2 to N/2, since N/2 would be the largest factor of N.
def isPrime(n: Int): Boolean = {
def isPrimeUntil(t: Int): Boolean = {
if(t == 2) true
else n % t != 0 && isPrimeUntil(t - 1)
}
isPrimeUntil(n/2)
}
So basically if I want to check if 15 is a prime I will check all numbers from 7 to 2.
Here is my trace:
isPrimeUntil(7) -> true && isPrimeUntil(6)
-> true && isPrimeUntil(5)
-> false && isPrimeUntil(4)
Because of short-circuit evaluation, the function returns false at this point.
However, my implementation fails for the basic case of checking if 3 is prime.
3 isn't your only problem. It also returns true for 4 ...
Your base case should be 1, not 2:
def isPrimeUntil(t: Int): Boolean = t == 1 || t > 1 && n%t != 0 && isPrimeUntil(t-1)
Although Krzystof correctly pointed that the source of the problem is integer division, I don't like his solution. I believe that the proper fix is change the test to
if(t <= 2) true
With such check in the case of n = 3 and so n/2 = 1 it will stop without going to t = 0.
Some benefits:
The modified check (t <= 2) on almost any modern hardware is as efficient as the check for (t == 2)
IMHO it better conveys the logic
It is very inefficient way to write (n.toDouble/2).ceil.toInt that way. It's easier and faster to write (n+1)/2 instead of doing 2 conversion (to double and back to int)
It doesn't require an excessive check for all odd n ((n+1)/2 is never the smallest divisor for an odd n where there is a difference between n/2 and ceil(n/2))

Why is my Ruby code for Project Euler #10 so slow?

I am relatively new to Ruby but it seems simple enough as far as a language goes. I am working through the Euler Project with Ruby and I'm having a huge issue with speed on the following:
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
My code:
beginning_time = Time.now
(1..10000).each { |i| i }
def isPrime(num)
factors = 0
primecount = 1
while primecount <= num
if (num%primecount == 0)
factors += 1
end
if (factors > 2)
return false
end
primecount += 1
end
return true
end
def make_sieve(num)
sieve = Array.new(num)
summation = 0
for i in 1..num
if(isPrime(i) == true)
summation += i
puts i
for x in i..num
if x%i == 0
# Go through entire array and make all multiples of i False
sieve[x] = false
else
sieve[i] = true
end
end
else
# If i is NOT prime, move to the next number. in the For Loop
next
end
end
puts summation
end
make_sieve(2000000)
end_time = Time.now
puts "Time elapsed #{(end_time - beginning_time)*1000} milliseconds"
I think I have the right idea with the sieve but I really have no clue what's going on that makes this program run so slow. I run it with 20,000 and it takes about 15 seconds, which seems slow even still, although the output comes out MUCH faster than when I put 2,000,000.
Am I going about this the wrong way logically or syntactically or both?
Your isPrime() test is very slow on primes; but you don't even need it. The key to sieve is, initially all the numbers are marked as prime; then for each prime we mark off all its multiples. So when we get to a certain entry in the sieve, we already know whether it is a prime or not - whether it is marked true for being prime, or it is marked false for being composite (a multiple of some smaller prime).
There is no need to test it being prime, at all.
And to find the multiples, we just count: for 5, it's each 5th entry after it; for 7 - each 7th. No need to test them with % operator, just set to false right away. No need to set any of them to true, because all numbers were set to true at the start.
You seem to be writing JavaScript code in Ruby, and are missing the subtleties that makes Ruby so elegant. You should take a look at something like Ruby Best Practices, which is quite a light read but deals with using Ruby idioms instead of imposing the concepts of another language.
As has been said, the whole point of an Eratosthenes sieve is that you just remove all compound numbers from a list, leaving just the primes. There is no need to check each element for primeness.
This is a Rubyish solution. It runs in about 1.5 seconds. It is a little complicated by the representing number N by array element N-1, so (i+i+1 .. num).step(i+1) is equivalent to (n * 2 .. num).step(n)
def make_sieve(num)
sieve = Array.new(num, true)
sieve.each_with_index do |is_prime, i|
next if i == 0 or not is_prime
(i+i+1 .. num).step(i+1) { |i| sieve[i] = false }
end
puts sieve.each_index.select { |i| sieve[i] }.map { |i| i+1 }.inject(:+)
end
make_sieve(2_000_000)
output
142913828923

Ruby - Sqrt on a very large Integer cause Rounding issues

I'm trying to solve a Fibonacci problem and am stumbling into rounding issues.
If i = 8670007398507948658051921 then fib1 = 19386725908489880000000000.0.
My code is below - thanks for any help.
def is_fibonacci?(i)
fib1 = Math.sqrt(5*(i**2)+4)
fib2 = Math.sqrt(5*(i**2)-4)
fib1 == fib1.round || fib2 == fib2.round ? true : false
end
Doing sqrt like that will not work for such big values, because sqrt returns a Float and its precision will not suffice here. I would advice you to implement your own sqrt function. There are several algorithms out there suggesting how to do that, but I personally thing using a binary search for computing the reverse for a function is the easiest:
def sqrt a
begv = 1
endv = a
while endv > begv + 1
mid = (endv + begv)/2
if mid ** 2 <= a
begv = mid
else
endv = mid
end
end
return begv
end
Alternatively you may try using BigDecimal for the sqrt(simply raise to power 0.5), but I like above method better as it does not involve any double calculations.

Probabilistic Sieve of Eratosthenes

Consider the following algorithm.
function Rand():
return a uniformly random real between 0.0 and 1.0
function Sieve(n):
assert(n >= 2)
for i = 2 to n
X[i] = true
for i = 2 to n
if (X[i])
for j = i+1 to n
if (Rand() < 1/i)
X[j] = false
return X[n]
What is the probability that Sieve(k) returns true as a function of k ?
Let's define a series of random variables recursively:
Let Xk,r denote the indicator variable, taking value 1 iff X[k] == true by the end of the iteration in which the variable i took value r.
In order to have fewer symbols and since it makes more intuitive sense with the code, we'll just write Xk,i which is valid although would have been confusing in the definition since i taking value i is confusing when the first refers to the variable in the loop and the latter to the value of the variable.
Now we note that:
P(Xk,i ~ 0) = P(Xk,i-1 ~ 0) + P(Xk,i-1 ~ 1) * P(Xk-1,i-1 ~ 1) * 1/i
(~ is used in place of = just to make it understandable, since = would otherwise take two separate meanings and looks confusing).
This equality holds by virtue of the fact that either X[k] was false at the end of the i iteration either because it was false at the end of the i-1, or it was true at that point, but in that last iteration X[k-1] was true and so we entered the loop and changed X[k] with probability of 1/i. The events are mutually exclusive, so there is no intersection.
The base of the recursion is simply the fact that P(Xk,1 ~ 1) = 1 and P(X2,i ~ 1) = 1.
Lastly, we note simply that P(X[k] == true) = P(Xk,k-1 ~ 1).
This can be programmed rather easily. Here's a javascript implementation that employs memoisation (you can benchmark if using nested indices is better than string concatenation for the dictionary index, you could also redesign the calculation to maintain the same runtime complexity but not run out of stack size by building bottom-up and not top-down). Naturally the implementation will have a runtime complexity of O(k^2) so it's not practical for arbitrarily large numbers:
function P(k) {
if (k<2 || k!==Math.round(k)) return -1;
var _ = {};
function _P(n,i) {
if(n===2) return 1;
if(i===1) return 1;
var $ = n+'_'+i;
if($ in _) return _[$];
return _[$] = 1-(1-_P(n,i-1) + _P(n,i-1)*_P(n-1,i-1)*1/i);
}
return _P(k,k-1);
}
P(1000); // 0.12274162882390949
More interesting would be how the 1/i probability changes things. I.e. whether or not the probability converges to 0 or to some other value, and if so, how changing the 1/i affects that.
Of course if you ask on mathSE you might get a better answer - this answer is pretty simplistic, I'm sure there is a way to manipulate it to acquire a direct formula.

Complexity of recursive algorithm

I have an algorithm, and I would like to find out the complexity of it, but there is recursion, and I don't know how to count with recursion. My code is:
public boolean algorithm(int x, int y) {
if (x == matrixHeight - 1 && matrix1[x][y] == '0') {
return true;
} else if (x == 1 && matrix1[x-1][y] == '0') {
return true;
} else if (y == matrixWidth - 1 && matrix2[x][y] == '0') {
return true;
} else if (y == 1 && matrix2[x][y-1] == '0') {
return true;
}
if (matrix1[x-1][y] == '0' && tempMatrix[x-1][y] == '-'){
path.push(new int[]{x-1, y});
tempMatrix[x-1][y] = '+'
if (!algorithm(x-1, y)) {
path.pop();
} else {
return true;
}
}
if (matrix2[x][y] == '0' && tempMatrix[x][y+1] == '-'){
path.push(new int[]{x, y+1});
tempMatrix[x][y+1] = '+';
if (!algorithm(x, y+1)) {
path.pop();
} else {
return true;
}
}
if (matrix1[x][y] == '0' && tempMatrix[x+1][y] == '-'){
path.push(new int[]{x+1, y});
tempMatrix[x+1][y] = '+';
if (!algorithm(x+1, y)) {
path.pop();
} else {
return true;
}
}
if (matrix2[x][y-1] == '0' && tempMatrix[x][y-1] == '-'){
path.push(new int[]{x, y-1});
tempMatrix[x][y-1] = '+';
if (!algorithm(x, y-1)) {
path.pop();
} else {
return true;
}
}
return false;
}
There, x, y are coordinates in matrix.
matrix1 and matrix2 are two-dimensional arrays that contain '0' or '1'
tempMatrix is a two-dimensional array that contains '+' or '-'
path is a Stack
matrixHeight is matrix1.length
matrixWidth is matrix[0].length
N, M is the size of the matrix (constant)
Note: this is maze solver that uses backtrack.
For recursion, you need to generate a recurrence relation and solve. See http://en.wikipedia.org/wiki/Recurrence_relation. There is no set way to solve every recurrence relation or even to generate one from an algorithm.
An example is with merge sort. Consider how much work is done at each recursive call. First, there is a constant time division; then two recursive calls are made; then there is a linear time merge. How much work does the recursive call take? Well, each one does the same thing, two recursive calls plus linear merge step. So you need an expression for how deep and wide the tree goes. You know for input size of n, the height of the tree is O(log(n)), and at each step a total of O(n) merge work is done, so therefore O(n log(n)) work is done total.
It looks like a depth first maze solver that returns true if you can exit the labyrinth and false otherwise. The complexity is O(lines * columns) because you visit each cell a constant number of times in the worst case.
1 1 1 1
1 0 0 1
0 0 0 1
1 1 1 1
Start at (1, 1). Your algorithm will go up, backtrack, go right, try up again, backtrack, right again, backtrack, then down and so on. For labyrinths constructed like this it looks like your algorithm will spend a lot of time solving them.
In fact, most recursive (depth first to be more accurate) approaches will spend a long time, because it will always be possible to force them to do a maximum number of steps.
Look into the Lee algorithm for a better approach.
There is actually a really simple analysis of the complexity of this algorithm.
Each call to algorithm makes zero to four recursive calls to algorithm and does some constant amount of other work. So, if we can bound the number of times that algorithm is called then we know the complexity. Now, note that just before every call to algorithm (except for the first) you change an element of tempMatrix from '-' to '+'. And so, the number of calls to algorithm is bounded by the size of tempMatrix, and the complexity is O(matrixWidth * matrixHeight).
Another approach (that would be more obvious with more meaningfull variable names) is simply noticing that you are doing a depth-first search on the x-y grid. And so each "square" will be visited once.

Resources