Fibonacci program does not complete execution - c#

Problem Description
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms
Program
using System;
class fibonacci {
// function to return Nth value of fibonacci
public static long fibo_n(long N) {
long fibon=0;
switch (N) {
case 1: fibon=1; break;
case 2: fibon=2; break;
}
while(N>2) {
fibon=fibo_n(N-1)+fibo_n(N-2);
}
return fibon;
}
}
class fibo_tester {
static void Main() {
int N=2;
long sum=0;
while(fibonacci.fibo_n(N) <= 13) {
sum = sum + fibonacci.fibo_n(N);
N=N+3;
}
Console.WriteLine("Sum is {0}: ", sum);
}
}
I reduced the number to 13 for testing instead of 4 million, but it still hangs. Could someone please advise?
EDIT 2
switch (N) {
case 1: fibon=1; break;
case 2: fibon=2; break;
default: fibon=fibo_n(N-1)+fibo_n(N-2); break;
}

while(N>2) {
fibon=fibo_n(N-1)+fibo_n(N-2);
}
Is going to loop indefinitely, N is never updated in the loop. You probably need to remove the While() clause and change it all to return fibo_n(N-1)+fibo_n(N-2); I'm not sure what you are doing with the switch statements, etc. But that should be a start.
I would actually replace it with this (if you want to use the switch):
class fibonacci
{
// function to return Nth value of fibonacci
public static long fibo_n(long N)
{
switch (N)
{
case 0:
return 0;
case 1:
return 1;
default:
return fibo_n(N - 1) + fibo_n(N - 2);
}
}
}
You might want to consider storing the values for each value of N in a dictionary or some sort of set so that you can look them up later. Since in your main program it seems like you are going to be looping over the values (successively larger N's that may have already been calculated). I'm not sure what the N+3 is about in your main loop, but you probably are going to miss something there (false assumption of the N-1, N-2 in the recursion perhaps?)
Also, if summing and dependent on your platform and how large of a value you test for (sicne your testing the sum of the first X Fibonacci numbers) you may have to use a ulong or find some other datatype that can handle larger numbers. If I don't change everything from long to ulong on my system, the values wrap around. Fibonacci number can't be negative anyways, so why not use a ulong, or uint64 or something with more bits.

You are using BOTH a loop AND recursion - you'll need to pick one or the other. The problem spot in your code is here:
while (N>2) {
fibon = fibo_n(N-1)+fibo_n(N-2);
}
In this spot the value of N never actually changes - that happens in the recursive step. One example (not good) way to write this is:
public static long fibo_n(long N) {
if (N <= 0) return 0;
if (N == 1) return 1;
if (N <= 4) return N - 1;
return fibo_n(N-1) + fibo_n(N-2);
}
Best of luck!
Performance Note:
The reason this isn't a good approach is because function calls use memory in C# and they also take time. Looping is always faster than recursion and in this case there isn't a good reason to solve this with recursion (as opposed to a simple loop). I'll leave the code as is so you can compare to what you have, but I think you can find much better better code options elsewhere (although not all of these will be in C#).

Let's say you call your method with N equal to 3.
The switch doesn't do anything.
N is greater than 2, so we go into the while loop. The while loop does something; it computes a value, assigns it to fibon. Then N, since it hasn't changed, is still greater than 2, so we compute it again. It'll still be greater than two, so we compute it again. We never stop computing it.
Every time you assign a value to fibon you should instead be returning that value, because you're done; you have nothing left to compute. There's also no need for the while loop. You never need to execute that code more than once.
Your implementation is also super inefficient. To compute fib(5) you compute fib(4) and fib(3). To Then when computing fib(4) you compute fib(3) [again] and fib(2), when computing fib(3) both times they each compute fib(2) (so that's three times there), and if we do the math we end up seeing that you perform on the order of 2^n computations when computing fib(n). On top of that, you're calling fib n times as you're counting up from zero in your main loop. That's tons and tons and tons of needless work re-computing the same values. If you just have a simple loop adding the numbers together as you go you can compute the result with on the order of N computations.

Related

What is stopping this program from having an output

I made this code to brute force anagrams by printing all possible permutables of the characters in a string, however there is no output. I do not need simplifications as I am a student still learning the basics, I just need help getting it to work this way so I can better understand it.
using System;
using System.Collections.Generic;
namespace anagramSolver
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter anagram:");
string anagram = Console.ReadLine();
string temp = "";
List<string> storeStr = new List<string>(0);
List<int> storeInt = new List<int>(0);
//creates factorial number for anagram
int factorial = 1;
for (int i = anagram.Length; i > 0; i--)
{
factorial *= i;
}
while (storeStr.Count != factorial)
{
Random rnd = new Random();
while(temp.Length != anagram.Length)
{
int num = rnd.Next(anagram.Length - 1);
if (storeInt.Contains(num) == true)
{
}
else
{
storeInt.Add(num);
temp += anagram[num];
}
}
if (storeStr.Contains(temp) == true)
{
temp = "";
}
else
{
storeStr.Add(temp);
Console.WriteLine(temp, storeStr.Count);
temp = "";
}
}
}
}
}
edit: added temp reset after it is deemed contained by storeStr
Two main issues causing infinite loop:
1)
As per Random.Next documentation, the parameter is the "exclusive" upper bound. This means, if you want a random number between 0 and anagram.Length - 1 included, you should use rnd.Next(anagram.Length);.
With rnd.Next(anagram.Length - 1), you'll never hit anagram.Length - 1.
2)
Even if you solve 1, only the first main iteration goes well.
storeInt is never reset. Meaning, after the first main iteration, it will have already all the numbers in it.
So, during the second iteration, you will always hit the case if (storeInt.Contains(num) == true), which does nothing and the inner loop will go on forever.
Several issues here...
The expression rnd.Next(anagram.Length - 1) generates a value between 0 and anagram.Length - 2. For an input with two characters it will always return 0, so you'll never actually generate a full string. Remove the - 1 from it and you'll be fine.
Next, you're using a list to keep track of the character indices you've used already, but you never clear the list. You'll get one output (eventually, when the random number generator covers all the values) and then enter an infinite loop on the next generation pass. Clear storeInt after the generation loop to fix this.
While not a true infinite loop, creating a new instance of the random number generator each time will give you a lot of duplication. new Random() uses the current time as a seed value and you could potentially get through a ton of loops with each seed, generating exactly the same values until the time changes enough to change your random sequence. Create the random number generator once before you start your main loop.
And finally, your code doesn't handle repeated input letters. If the input is "aa" then there is only a single distinct output, but your code won't stop until it gets two. If the input was "aab" there are three distinct permutations ("aab", "aba", "baa") which is half of the expected results. You'll never reach your exit condition in this case. You could do it by keeping track of the indices you've used instead of the generated strings, it just makes it a bit more complex.
There are a few ways to generate permutations that are less error-prone. In general you should try to avoid "keep generating random garbage until I find the result I'm looking for" solutions. Think about how you personally would go about writing down the full list of permutations for 3, 4 or 5 inputs. What steps would you take? Think about how that would work in a computer program.
this loop
while(temp.Length != anagram.Length)
{
int num = rnd.Next(anagram.Length - 1);
if (storeInt.Contains(num) == true)
{
}
else
{
storeInt.Add(num);
temp += anagram[num];
}
}
gets stuck.
once the number is in storeInt you never change storeStr, yet thats what you are testing for loop exit

Confused with the Parallel.ForEach loop in C#

I'm new to C# and am basically trying to generate large Integers using the BigInteger class in C#, by feeding it a byte[] array of randomly filled values. I have another method, CheckForPrime(BigIngeger b) that checks for a prime number and simply returns true if the number is prime. So to run everything, I'm using a Parallel ForEach loop which loops infinitely until a condition is false. Here is my code:
private static IEnumerable<bool> IterateUntilFalse(bool condition)
{
while (condition) yield return true;
}
and here is my attempt at a Parallel.ForEach loop that runs till the condition is false:
public void PrintOutPrimes(int numPrimes)
{
byte[] makeBytes = new byte[512];
BigInteger makePrime;
RandomNumberGenerator r = RandomNumberGenerator.Create();
ConcurrentBag<BigInteger> bbag = new ConcurrentBag<BigInteger>();
int trackNum = 0;
bool condition = (trackNum <= numPrimes);
Parallel.ForEach(IterateUntilFalse(condition), (ignored, state) =>
{
if (trackNum > numPrimes) state.Stop();
r.GetNonZeroBytes(makeBytes);
makePrime = BigInteger.Abs(new BigInteger(makeBytes));
if (CheckForPrime(makePrime))
{
bbag.Add(makePrime);
if(bbag.TryPeek(out makePrime))
{
Console.WriteLine(makePrime);
}
Interlocked.Increment(ref trackNum);
}
});
}
I want to generate large prime numbers using the performance of Parallel.ForEach, and then print them out as it finds them. The problem seems like the code is "bypassing" the if statement in the loop and adding non-prime numbers to the concurrent bag too. Is there a way to avoid this and guarantee that only the prime numbers be added to the bag and then printed sequentially?
bool condition is not a condition, it's the result of evaluating the condition once. Basically it is always true and will never change. Therefore, your iterator will yield true forever.
To solve that, you need a real condition that can be evaluated several times, like a Lambda expression. But even with a lambda this won't work well due to race conditions in your local variables.
Actually I don't really see why you use Parallel.Foreach at all. If you want 500 primes, then use Parallel.For, not Parallel.Foreach.
Instead of generating a huge amount of random numbers and checking them for primality, choose a random number and increment it until you find a prime number. That way it's guaranteed that you get one prime number for every random number input.
Concept:
Parallel.For(0, numPrimes, (i, state)=>
{
byte[] makeBytes = new byte[512];
r.GetNonZeroBytes(makeBytes);
BigInteger makePrime = BigInteger.Abs(new BigInteger(makeBytes));
while (!IsPrime(makePrime))
makePrime += 1; // at some point, it will become prime
bbag.Add(makePrime);
});
You probably want to start with an odd number and increment by 2.
You definitely want one RNG per thread instead of accessing a single global RNG, except you have a thread-safe RNG.
You also want the byte[] to be part of the state, so that it does not get recreated per loop and messes with garbage collection.

Is there a way to make this recursive function faster? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am trying to get numbers that sum up 28.(this is just an example, however the target number can be changed). The below piece of code take approximately 4-5 min. Is there a way to make it a little faster to get combinations of numbers that sum up to "28"
output example 0,0,0,0,1,1,1,2,2,3,3,3
private void Button1_Click(object sender, EventArgs e)
{
int up = 28;
int rows = 12;
int[] chosen = new int[rows + 1];
CalculateCombination(chosen, 0, rows, 0, up - 1);
}
public void CalculateCombination(int[] chosen, int index, int r, int start, int end)
{
if (index == r)
{
return;
}
for (int i = start; i <= end; i++)
{
chosen[index] = i;
CalculateCombination(chosen, index + 1, r, i, end);
if (chosen.Sum() + chosen.Length == 28)
{
var ch = string.Join(",", chosen.Take(chosen.Length - 1));
Debug.Write(ch);
Debug.WriteLine("\t");
}
}
return;
}
First off, I assume you are doing this for an assignment. You are required to cite sources that helped you rather than passing off my work as your own in an academic context, so make sure to document in your assignment where you got help from. Don't just copy a solution and claim it as your own.
UPDATE: I misunderstood the problem from the description; I understood the problem to be to find the monotone nondecreasing sequences of length 12 that sum to 28. The problem has been clarified by the original poster in a comment; the problem is to find all non-negative sequences of a given length, say, 12 that sum to a given value, say, 28. There are 1676056044 such sequences, and enumerating them all will take some time. The answer which follows is addressed to the problem as I originally understood it.
Yes, this problem can be solved much more efficiently and clearly than you're doing here. Let's break it down.
First off, every recursive problem has one or more base cases. These are the cases that are so simple that they cannot be reduced to a simpler problem. Let's make an entrypoint and then list the base cases. What do we want? We want all the sequences of a given length, in order from smallest to largest, such that the sequence sums to a particular value.
public static IEnumerable<IEnumerable<int>> SumsTo(int sum, int least, int length)
{
OK, what are the base cases?
If length is zero and sum is zero then the empty sequence is the only solution.
If length is zero and sum is non-zero then there is no solution.
We can easily implement these rules:
if (length == 0)
{
if (sum == 0)
yield return Enumerable.Empty<int>();
yield break;
}
All right, that deals with length being zero. What about length non-zero? Are there any base cases there? Yes. If least * length is greater than sum then there cannot be any solution.
if (least * length > sum)
yield break;
All right. We know that length is at least 1 and that there is definitely a solution. What are the solutions? Well, there has to be a first number in the sequence, and it can be any value between least and sum, so let's write a loop.
for (int current = least; current <= sum; current += 1)
{
What is the solution given current? It is current followed by a sequence of size length-1 where the smallest item is current or larger that sums to sum - current. But we can compute that recursively!
var head = Enumerable.Repeat(current, 1);
foreach(var tail in SumsTo(sum - current, current, length - 1))
yield return head.Concat(tail);
}
}
And we're done:
Console.WriteLine(SumsTo(28, 0, 12).Count());
Prints out 3036, as expected and takes a fraction of a second; there are 3036 ways to sum 12 numbers from 0 to 28 to 28.
EXERCISE: make a type Sum that is either (1) empty, or (2) an integer, called the head, followed by a Sum (either empty or made of only larger elements) called the tail. Rewrite the solution so that it returns IEnumerable<Sum> rather than IEnumerable<IEnumerable<int>>.
EXERCISE: Make your Sum type implement IEnumerable<int> correctly.
EXERCISE: We generate some sums over and over again; for example, of the 3036 solutions to the length is 12, sum is 28 problem, over 100 of them end with "5, 5" so we're allocating that object many times. Memoize your solution so that it returns the same Sum object when given the same arguments.
EXERCISE: Compute the approximate amount of computation you save with this memoized solution; contrast that with the amount of memory you use. Did memory usage go up or down? Did computation speed go up or down? What does this tell you about the efficiency of memoization for this problem? Can you propose a better memoization algorithm?
EXERCISE: I have a particular pattern for strings in mind; we'll call them frob strings. It goes like this: () is a frob string, and (XY) where X and Y are replaced with frob strings is a frob string. So for example (()()) is a frob string, as is (()(()())). Make a method static IEnumerable<string> AllFrob(int s) that gives all frob strings with s pairs of parentheses. So AllFrob(1) is just (). AllFrob(2) is empty; there are no frob strings with two pairs of parentheses. AllFrob(3) is (()()), AllFrob(4) is empty, AllFrob(5) is (()(()())) and ((()())()).

Parallel for loop with BigINtegers

So i am working on a program to factor a given number. you write a number in the command line and it gives you all the factors. now, doing this sequentially is VERY slow. because it uses only one thread, if i'm not mistaking. now, i thought about doing it with Parallel.For and it worked, only with integers, so wanted to try it with BigIntegers
heres the normal code:
public static void Factor(BigInteger f)
{
for(BigInteger i = 1; i <= f; i++)
{
if (f % i == 0)
{
Console.WriteLine("{0} is a factor of {1}", i, f);
}
}
}
the above code should be pretty easy to understand. but as i said, this Very slow for big numbers (above one billion it starts to get impractical) and heres my parallel code:
public static void ParallelFacotr(BigInteger d)
{
Parallel.For<BigInteger>(0, d, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, i =>
{
try
{
if (d % i == 0)
{
Console.WriteLine("{0} is a factor of {1}", i, d);
}
}
catch (DivideByZeroException)
{
Console.WriteLine("Done!");
Console.ReadKey();
Launcher.Main();
}
});
}
now, the above code (parallel one) works just fine with integers (int) but its VERY fast. it factored 1000.000.000 in just 2 seconds. so i thought why not try it with bigger integers. and also, i thought that putting <Biginteger> after the parallel.for would do it. but it doesn't. so, how do you work with bigintegers in parallel for loop? and i already tried just a regular parallel loop with a bigInteger as the argument, but then it gives an error saying that it cannot convert from BigInteger to int. so how do you
Improve your algorithm efficiency first.
While it is possible to use BigInteger you will not have CPU ALU arithmetical logic to resolve arbitrarily big numbers logic in hardware, so it will be noticeably slower. So unless you need bigger numbers than 9 quintillion or exactly 9,223,372,036,854,775,807 then you can use type long.
A second thing to not is that you do not need to loop over all elements as it needs to be multiple of something, so you can reduce
for(BigInteger i = 1; i <= f; i++)
for(long i = 1; i <= Math.Sqrt(f); i++)
That would mean that instead of needing to iterate over 1000000000 items you iterate over 31623.
Additionally, if you still plan on using BigInt then check the parameters:
It should be something in the lines of
Parallel.For(
0,
(int)d,
() => BigInteger.Zero,
(x, state, subTotal) => subTotal + BigInteger.One,
Just for trivia. Some programming languages are more efficient in solving problems than others and in this case, there is a languages Wolfram (previously Mathematica) when solving problems is simpler, granted that you know what you are doing.
However they do have google alternative that answers you directly and it has a decent AI that processes your natural language to give you an exact answer as best as it could.
So finding factors of numbers is easy as:
Factor[9223372036854775809]
or use web api https://www.wolframalpha.com/input/?i=factor+9223372036854775809
You can also call Wolfram kernel from C#, but terms and conditions apply.

Calculate amount of memory needed for recursive function

I have following function:
public static long Fibon(long num)
{
if (num == 1)
{
return 1;
}
else if (num == 2)
{
return 1;
}
return fibon(num - 1) + fibon(num - 2);
}
this function uses recursion in order to calculate Fibonacci number. How can I calculate amount of required stack memory for executing this function before executing it? For example I want to execute this function in few separated threads with some big numbers, and before executing threads I want to know how much stack memory available I need to have.
Just looking at it, the code won't work because when num == 2, the method tries to find fibon(0).
Try
public static long Fibon(long num)
{
if (num == 1)
{
return 1;
}
else if (num == 2)
{
return 1;
}
return fibon(num - 1) + fibon(num - 2);
}
will give you 1, 1, 2, 3, 5, ...
Sorry this wasn't an answer, I don't have the reputation to comment.
edit: You'll also be able compute greater entries bu using ulong.
Since you only have to remember the previous two terms to calculate the current one, you will not face any memory problem if using a non-recursive procedure :
public static long Fibon(long num)
{
long result ;
if (num == 1) { return 1; }
else if (num=2) { return 1; }
long grandfather = 1 ;
long father = 1 ;
for (in i=2;i<=num;i++)
{
result = father + grandFather;
grandfather = father ;
father = result ;
}
return result ;
}
For nth Fibonacci term the amount of memory needed by your function is O(n), i.e., linear in the index of the term in the Fibonacci sequence. More precisely, it will be n-1 times the amount of memory needed for each recursive call, which is implementation-dependent (plus some constant).
The amount of memory needed is equal to the amount of memory in each recursive call plus the "depth" of the "execution tree". In each recursive call you either terminate or make two new calls, one on the argument n-1 and one on the argument n-2; it is obvious this has to stop after n-1 calls.
If you imagine the whole process as a binary tree with nodes labeled f(k), where the node f(k) has a left child labeled f(k-1) and a right child labeled f(k-2), then the space complexity of f corresponds to the depth of the execution tree.
I believe the number of longs needed is actually equal to the returned long.
To return 2, you need to add 2 longs. To return 3, you need to add the number of longs needed to return 2 (which is 2 longs) to 1 which == 3. The pattern continues.
Since a long is 64 bits, the memory needed is equal to the fibonacci value * 64 bits.

Categories

Resources