C# recursive method converting to loop - c#

I wrote this recursive method but the problem is i need to do the same with a loop.
First one is recursive, and the second one is loop but it`s not good. Any advice how to fix the loop method?
double SR(int n)
{
if (n > 1)
return Math.Sqrt(2 + SR(n - 1));
else
return Math.Sqrt(2);
}//recursion
double SR2(double n)
{
if(n > 1)
{
do
{
n = Math.Sqrt(2+Math.Sqrt(n - 1));
}
while(n <= 1);
}
else
{
n = Math.Sqrt(2);
}
return n; //loop
}

double SRloop(int n)
{
var r = Math.Sqrt(2);
for (var i = 2; i <= n; i++)
{
r = Math.Sqrt(2 + r);
}
return r;
}

Explaining Knaģis answer:
You need to grasp more the concept of recursive functions.
In general recursive functions have a notion of "base" or "stop" condition, that is, a "fixed" value the function returns when a specified condition is met, otherwise, it would continue indefinitely.
When converting to a loop, the base condition becomes the starting value of the loop.
So in the looped version, Math.Sqrt(2) becomes the starting value of n.
From there, we loop until the desired value is achieved. How to determine when to stop? In the original recursive function, the stop condition is "n <= 1" (beware, its the condition for the "else" to be reached, so its the inverse of your if). Also, in each iteration, the function receives "n - 1" as argument. So what is happening is we are decrementing n by 1 until it reaches 1; so the loop will be executed (n - 1) times. To be more clear on this point, the loop could be rewritten with for (var i = 0; i < (n-1); i++) . The effect is the same and it is more clear that the loop executes (n-1) times.
Also, check this link for more info.

Related

How to correctly iterate over all long type range

If I'd like to loop over all long's range, I would ingenually do:
for (long i = long.MinValue; i <= long.MaxValue; ++i)
{
// Do something
}
But it loops forever!
For example, if I do:
for (byte b = byte.MinValue; b <= byte.MaxValue; ++b)
{
// Do something
}
It loops forever too, but I solved like this:
for (int i = byte.MinValue; i <= byte.MaxValue; ++i)
{
byte b = Convert.ToByte(i);
// Do something
}
With long type how can I do?
With long type how can I achieve the same if I don't increment by 1, but of an higher distance?
Are those "ideas" to loop over a type range correct, are there some issues to be warned about, or can I do it better?
In your first two examples, the loop continues forever due to number range overflows.
When i (1st example) or b (2nd example) exceed the maximum value that can be stored in long (1st example) or byte (2nd example), their value overflows to the smallest value storable by that type and the loop starts over and over.
Remember: in a for-loop, first the loop condition is checked, then the counter increments. If the counter overflows during the increment, the subsequent loop condition check still evaluates to true.
To get your example working, try:
for (long i = long.MinValue; ; i++)
{
if (i == long.MaxValue)
{
break;
}
}
If you want to increment in larger steps, try:
const long step = 90000000000;
for (long i = long.MinValue; i <= long.MaxValue; )
{
// check if loop counter overflows when incrementing by the step
if (unchecked (i + step) < i)
{
break;
}
// otherwise it is safe to increment it
else
{
i += step;
}
}
This is caused by integer overflow when you try to increment past MaxValue. You could try this instead:
long i = long.MinValue;
do
{
// Do something
} while (i++ != long.MaxValue);
This way, the value of i is checked before it's incremented, and the loop terminates correctly.
You could use BigInteger to keep your loop pattern the same and avoid the overflow:
for (BigInteger i = long.MinValue; i <= long.MaxValue; ++i)
{
// Do something
}
I haven't benchmarked it, but I would imagine there would be a noticeable performance penalty for doing it this way.

While Looping an Array

I'm trying to understand a book from Don Gosselin on ASP.NET Programming with Visual C#. To solve it I just simply make it to work by adhering to while loops: one while loop is to assign a number to an array element, the other while loop is to display that array. Total array count displays 1 through 100. This should have worked but didn't. Visual Studio 2013 debugger for some reason assigns count = 100, that's why it's failing.
<%
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
%>
You should set count to 0 after first while loop:
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
count = 0;
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
You need to reset the count to 0 before you attempt the next while statement. Currently, the first loop ends when it reaches a count equal to 101. WHen you proceed to the next while, the count is 101 so the loop automatically ends. Just set count = 0; before the second while loop.
This seems like a very convoluted and unrealistic way of using while loops and arrays. In order to understand it better, it may be worth thinking about it per step.
var i = 0;
while (i < 100)
{
Response.Write(++i + "<br />");
}
The first important distinction is between i++ and ++i. The former utilises the value, and then increments by one; the latter, increments the number and then utilises the value.
In C#, you should really be working with Collections, rather than Arrays. Arrays are zero-indexed, and are renowned for causing serious errors, including exposing potential exploits. Being statically allocated, there is no failsafe when attempting to access indicies outside of the bounds of the Array. Collections, on the other hand, are (for the most part) one-indexed, dynamically allocated, and provide fallbacks when accessing indicies. The most commonly used Collection is a List.
var i = 1;
var list = new List<int>();
while (i <= 100)
{
list.Add(i++);
}
For the second while loop, it's not really suitable to use a while loop here, for any practical example. The excercise is forcing while loops where they are not needed. In this instance, the aim is to iterate through each element in the array (List) and dump its contents to the screen. Because we want to perform an action for each element, a while loop may cause issues. If the array has less than 100 elements, the program will crash, if the array has more than 100 elements, we'll miss some of them. By using a foreach loop, instead of a while, we can eliminate these potential errors.
foreach (var num in list)
{
Response.Write(num + "<br />");
}
Now, I realise that the excercise is about while loops, however, it is teaching you to use them in the wrong way. A much better way - and how you'll most often use them - is to perform an action until a particular condition is met, rather than for simple iteration. By this, I mean, a condition is set to false, then inside the while loop, we manipulate a variable, test the condition, and if it's still false, we go round again. The most common example of this is to work out factorials of numbers.
var num = 5;
var factorial = 1;
while (counter > 1)
{
factorial *= num--;
}
Response.Write(String.Format("{0}! = {1}", input, factorial));
The other main way in which while loops are used is to force an infinite loop, unless a break condition is met. I'll show a very arbitrary use of this here, but a real world example would be the loop() method in Arduino C coding, or a HTTP Listener that constantly repeats the same procedures, until stopped.
var stop = 13;
Response.Write("Pick a number between 1 and 100...<br /><br />");
while (true)
{
var num = new Random().Next(1, 101);
Response.Write(num + " ..... ");
if (num == stop) break;
Response.Write("You got lucky!<br />");
}
Response.Write("Unlucky for you!);
The best way to learn these things is to practice them. Pick a task and find out just how many ways there are to complete it. There is one last important distinction to mention though. a while loop tests the condition at the beginning of the loop. A do while loop, tests the condition at the end.
while(false)
{
// This code will never be run.
}
Compared to:
do
{
// This code will be run once only.
}
while(false)
As a final thought, here's how I'd write the original code (using a LINQ foreach loop):
var numbers = new List<int>();
for (var count = 1; count <= 100; count++)
{
numbers.Add(count);
}
numbers.ForEach(num => Response.Write(num + "<br />")));

How to display all members of a given subsequence on the console?

I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}
I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();

for loop ends prematurely when objects are removed

Hi I have a problem with a for loop.
It looks like this
for (int i = 0; i < ObjectManager.Instance.Objects.Count; i++)
{
if (ObjectManager.Instance.Objects[i] is Asteroid)
{
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
}
}
But the count gets shorter while I remove objects, which causes the loop to end prematurely. Is there a way to do this without a bunch of extra loops.
Why don't you loop backward?
// Just change the order from Count - 1 down to 0
for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; --i)
{
if (ObjectManager.Instance.Objects[i] is Asteroid)
{
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
}
}
In case you have to loop forward (e.g. if Instances should be deleted in the order they are created because they are depend on each other) you can modify for loop in this way:
for (int i = 0; i < ObjectManager.Instance.Objects.Count;) // <- No increment here
if (ObjectManager.Instance.Objects[i] is Asteroid)
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
else
i += 1; // <- Increment should be here!
Yet another possibility is Linq:
ObjectManager.Instance.Objects.RemoveAll(item => item is Asteroid);
Three options:
If ObjectManager.Instance.Objects is a List<T>, use List<T>.RemoveAll with a predicate, making your code much simpler:
// This replaces your whole loop...
ObjectManager.Instance.Objects.RemoveAll(x => x is Asteroid);
Count from the end of the collection rather than from the start, so that you don't need to adjust the index afterwards:
for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; i--)
Just decrement i after calling Remove, so that you'll look at the right index on the next iteration.
Note that in the second and third options your code will be a lot simpler to read if you extract the expression ObjectManager.Instance.Objects into a local variable before you use it 4 times. Also consider using RemoveAt(i) rather than Remove(instances[i]), assuming RemoveAt is available for the type you're using.

How is the 'e--' expression used in this simple exponent example?

I understand every cog in this code with the exception of one part: the "e--;" within the While loop. Can anybody explain its importance to me?
public class Power
{
public static void Main()
{
int e;
int result;
for(int i=0; i < 10; i++)
{
result = 1;
e = i;
while(e > 0)
{
result *= 2;
e--;
}
Console.WriteLine(string.Format("2 to the {0} power is {1}", i, result));
}
}
}
You're looking at a postfix decrement operator.
It evaluates the value of e and then subtracts one from the value; since it's a standalone statement, it simply subtracts one from e's value.
The idea here is to simply multiply result by 2 i times. It does this by setting e to i, subtracting one each iteration of the loop, and looping while it's positive. This means that the while loop will always loop i times. You could just as easily (and arguably more clearly) write:
for(int e = 0; e < i; e++)
result *= 2;
while(e > 0)
This means that your loop will run as long as e is greater than zero. e-- is decrementing e's value on each iteration. If you didn't decrement it inside of your loop then you will get an infinite loop because your condition will become always true and your loop won't end.
The e-- just decrements the value of e. It is equivalent to e = e - 1;.
The reason you decrement the value is to eventually exit of the while loop; once you set e to the value of i, the loop will run indefinitely unless the value of e becomes less or equal to zero, which makes the while loop condition of e > 0 false.
In the larger picture, you are using e to stored the current value of i and then use it to execute i times the statement result *= 2;. In other words, you are using e to count how many times the variable result needs to be multiplied by 2 during the current iteration of the outer for loop.
This is similar to doing something like,
for (int i=0; i < 10; i++)
{
result = 1;
e = 0;
for (e = i; e > 0; e--)
{
result *= 2;
}
}
Since the while loop is really acting as a for loop.
e is your counter variable. It will repeat the while loop until the result has been multiplied the specified number of times (which is whatever i is when the loop started). As others have stated, e-- just decrements the value of e by one. You can read more here. This means that, in the code you provided, it will multiply result by 2 e times which mathematically will compute 2^i (i.e. 2^0 = 1, 2^1 = 2, 2^2 = 4, etc.).
e-- means it will decrease 1 in each loop, e++ will increase 1
check this article http://msdn.microsoft.com/en-us/library/36x43w8w.aspx

Categories

Resources