Related
A 2 dimensional array with a size of NxN, composed of 1 and 0.
A neighbor is a 1 in the north / south / west / east of the index
Recursively find how many neighbors an index in the array has (neighbors that touch other neighbors are also included).
For the array I built I should get 6, but instead I get a stack overflow exception, and I don't get why.
Below is my 7x7 array, that for index 2, 5 should return the value of 6.
Example:
static void Main(string[] args)
{
int[,] arr = {
{ 0,0,0,1,0,0,0 },
{ 1,0,0,1,1,0,0 },
{ 0,0,0,0,1,1,0 },
{ 0,0,0,0,1,0,0 },
{ 0,0,0,0,0,0,0 },
{ 0,1,1,1,1,0,0 },
{ 1,0,0,1,0,0,0 },
};
Console.WriteLine(Recursive(arr,2,5));
Console.ReadLine();
}
Routine under test:
static public int Recursive(int[,] arr, int x, int y)
{
if (x < 0 || y < 0 || x > arr.GetLength(0) || y > arr.GetLength(1))
{
return 0;
}
// check if a 1 has neighbors
if (arr[x, y] == 1)
{
return 1 +
Recursive(arr, x - 1, y) +
Recursive(arr, x + 1, y) +
Recursive(arr, x, y - 1) +
Recursive(arr, x, y + 1);
}
else
{
return 0;
}
}
Please, note that when you compute Recursive(arr, x, y) you call both Recursive(arr, x - 1, y) and Recursive(arr, x + 1, y):
return 1 +
Recursive(arr, x - 1, y) + // <- both x - 1
Recursive(arr, x + 1, y) + // <- and x + 1
Recursive(arr, x, y - 1) +
Recursive(arr, x, y + 1);
On the next recursive call, when you try to compute Recursive(arr, x + 1, y) it calls Recursive(arr, x + 2, y) as well as Recursive(arr, x + 1 - 1, y) which is Recursive(arr, x, y). So you have a vicious circle: to compute Recursive(arr, x, y) you must compute Recursive(arr, x, y) and stack overflow as the the result.
The way out is to break the circle and don't let read the same cell again and again (we can just set it to 0 for this):
public static int Recursive(int[,] arr, int x, int y)
{
// out of the grid
if (x < 0 || y < 0 || x > arr.GetLength(0) || y > arr.GetLength(1))
return 0;
// empty cell
if (arr[x, y] == 0)
return 0;
// do not read the cell again! From now on treat it as an empty cell
arr[x, y] = 0;
int result = 1; // the cell itself
// let have a loop instead of four calls
for (int d = 0; d < 4; ++d)
result += Recursive(arr, x + (d - 2) % 2, y + (d - 1) % 2);
// Restore after the recursive call:
// let us do not damage arr with permanently setting cells to 0
// and return arr to its original state
arr[x, y] = 1;
return result;
}
Edit: non recursive solution, where we memorize in visited all the visited cells:
public static int Memoization(int[,] arr, int x, int y) {
if (x < 0 || y < 0 || x > arr.GetLength(0) || y > arr.GetLength(1))
return 0;
if (arr[x, y] == 0)
return 0;
int result = 0;
var agenda = new Queue<(int x, int y)>();
agenda.Enqueue((x, y));
var visited = new HashSet<(int x, int y)> { (x, y) };
while (agenda.Count > 0) {
result += 1;
var (oldX, oldY) = agenda.Dequeue();
for (int d = 0; d < 4; ++d) {
int newX = oldX + (d - 2) % 2;
int newY = oldY + (d - 1) % 2;
if (newX < 0 || newY < 0 || newX > arr.GetLength(0) || newY > arr.GetLength(1))
continue;
if (arr[newX, newY] == 0)
continue;
if (visited.Add((newX, newY)))
agenda.Enqueue((newX, newY));
}
}
return result;
}
Start by considering the simplest possible input. In this case it would be an array like
int[,] arr = { {1, 1 }}
I.e. an array consisting of only two items.
Start by the first left item, this is one, so next all neighbors recursed to.
All but the right neighbor is outside the array so will be ignored.
The right item is one, so all neighbors to this will be recursed to, including the left item.
Since you end up processing the left item again, you will continue the recursion until you run out of stack space.
The point here is that you need to keep track of all the points you have already visited. For example by using a HashSet<(int x, int y)>.
This question already has answers here:
Unassigned local variable mystery
(3 answers)
Closed 2 years ago.
Good Day guys! I'm trying to make solve a programming challenge named NextPrime. Its just basically will return the next number that is prime. for example the input is 8, the return value is 11 since 11 is a prime number. I made my code below and got this Use of unassigned local variable result. The code below is my source code:
public static int NextPrime(int num)
{
int half = num / 2;
int outer = num * 2;
int x, y, result;
for (x = num; x <= outer; x++)
{
for (y = 2; y <= half; y++)
{
if (x % y == 0)
{
break;
}
else if (y == half)
{
result = x;
x = outer + 1;
break;
}
}
}
return result;
}
Well, result can well appear uninitialized; the easiest example is
var demo = NextPrime(-1);
Note, that outer loop for (x = num; x <= outer; x++) is not entered and that's why result is not assigned.
What can you do? Direct approach is to implement IsPrime method:
public static bool IsPrime(int x) {
if (x <= 1)
return false;
else if (x % 2 == 0) // we have only one even prime, that is 2
return x == 2;
int n = (int)(Math.Sqrt(x) + 0.5);
for (int divisor = 3; divisor <= n; divisor += 2)
if (x % divisor == 0)
return false;
return true;
}
And then use it in NextPrime:
public static int NextPrime(int num) {
if (num <= 1)
return 2;
for (int x = num + 1 + num % 2; ; start += 2)
if (IsPrime(x))
return x;
}
Compiler Error CS0165
Use of unassigned local variable 'name'
The C# compiler doesn't allow the use of uninitialized variables. If
the compiler detects the use of a variable that might not have been
initialized, it generates compiler error CS0165. For more information,
see Fields. This error is generated when the compiler encounters a
construct that might result in the use of an unassigned variable, even
if your particular code does not. This avoids the necessity of overly
complex rules for definite assignment.
You need to be explicit about what is returned if the loops don't run. The compiler only goes so far with static analysis and doesn't probe whether loops are meaningfully setting values within
public static int NextPrime(int num)
{
int half = num / 2;
int outer = num * 2;
int result = 0; // Explicit
for (var x = num; x <= outer; x++)
for (var y = 2; y <= half; y++)
if (x % y == 0)
break;
else if (y == half)
{
result = x;
x = outer + 1;
break;
}
return result;
}
I've been having troubles trying to get my fractional calculator to work. I'm trying to get the simplifying to work, it works correctly simplifiyng positive fractions, but if I were to put a negative fraction it won't simplify it, I'm not sure what I'm doing wrong and I've read over it numerous times (the Gcd and Reduce functions).
Im new to all of this, any help appreciated.
My Reduce and GCD functions:
public int gcd()
{
// assigned x and y to the answer Numerator/Denominator, as well as an
// empty integer, this is to make code more simple and easier to read
int x = answerNumerator;
int y = answerDenominator;
int m;
// check if numerator is greater than the denominator,
// make m equal to denominator if so
if (x > y)
m = y;
else
// if not, make m equal to the numerator
m = x;
// assign i to equal to m, make sure if i is greater
// than or equal to 1, then take away from it
for (int i = m; i >= 1; i--)
{
if (x % i == 0 && y % i == 0)
{
//return the value of i
return i;
}
}
return 1;
}
public void Reduce()
{
try
{
//assign an integer to the gcd value
int gcdNum = gcd();
if (gcdNum != 0)
{
answerNumerator = answerNumerator / gcdNum;
answerDenominator = answerDenominator / gcdNum;
}
if (answerDenominator < 0)
{
answerDenominator = answerDenominator * -1;
answerNumerator = answerNumerator * -1;
}
}
catch (Exception exp)
{
// display the following error message
// if the fraction cannot be reduced
throw new InvalidOperationException(
"Cannot reduce Fraction: " + exp.Message);
}
}
I think the problem is that, when you determine the GCD, you are checking that the value is >= 1 in your for loop, even though it may be negative. In order to avoid this, you should capture the absolute values of the numerator and denominator when determining the GCD.
For example, this should fix it:
public int gcd()
{
// assigned x and y to the absolute values of the answer Numerator/Denominator,
// as well as an empty integer, this is to make code more simple and easier to read
int x = Math.Abs(answerNumerator);
int y = Math.Abs(answerDenominator);
int m;
// check if numerator is greater than the denominator,
// make m equal to denominator if so
if (x > y)
m = y;
else
// if not, make m equal to the numerator
m = x;
// assign i to equal to m, make sure if i is greater
// than or equal to 1, then take away from it
for (int i = m; i >= 1; i--)
{
if (x % i == 0 && y % i == 0)
{
//return the value of i
return i;
}
}
return 1;
}
Short Answer
You need:
int x = Math.Abs(answerNumerator);
int y = Math.Abs(answerDenominator);
Running Code
Here is a running Fiddle for you: https://dotnetfiddle.net/nBzr0i
Output:
Initial: 2/4
Reduced: 1/2
---
Initial: 2/-4
Reduced: -1/2
---
Running Code:
using System;
public class Program
{
public static void Main()
{
Calc.Reduce(2,4);
Calc.Reduce(2,-4);
}
}
public static class Calc
{
public static int gcd(int answerNumerator, int answerDenominator)
{
// assigned x and y to the answer Numerator/Denominator, as well as an
// empty integer, this is to make code more simple and easier to read
int x = Math.Abs(answerNumerator);
int y = Math.Abs(answerDenominator);
int m;
// check if numerator is greater than the denominator,
// make m equal to denominator if so
if (x > y)
m = y;
else
// if not, make m equal to the numerator
m = x;
// assign i to equal to m, make sure if i is greater
// than or equal to 1, then take away from it
for (int i = m; i >= 1; i--)
{
if (x % i == 0 && y % i == 0)
{
//return the value of i
return i;
}
}
return 1;
}
public static void Reduce(int answerNumerator, int answerDenominator)
{
Console.Write("Initial: ");
WriteFraction(answerNumerator, answerDenominator);
try
{
//assign an integer to the gcd value
int gcdNum = gcd(answerNumerator, answerDenominator);
if (gcdNum != 0)
{
answerNumerator = answerNumerator / gcdNum;
answerDenominator = answerDenominator / gcdNum;
}
if (answerDenominator < 0)
{
answerDenominator = answerDenominator * -1;
answerNumerator = answerNumerator * -1;
}
}
catch (Exception exp)
{
// display the following error message
// if the fraction cannot be reduced
throw new InvalidOperationException("Cannot reduce Fraction: " + exp.Message);
}
Console.Write("Reduced: ");
WriteFraction(answerNumerator, answerDenominator);
Console.WriteLine("---");
}
public static void WriteFraction(int answerNumerator, int answerDenominator)
{
Console.WriteLine(string.Format("{0}/{1}", answerNumerator, answerDenominator));
}
}
Can somebody please explain how this recursive function is doing? I'm struggling to understand how you can multiply numbers by using just +
static int Multiply(int x, int y)
{
if (y == 1)
{
return x;
}
else
{
return x + Multiply(x, y - 1);
}
}
Remember your basic arithmetic.
X * 2 = X + X
X * 3 = X + X + X
etc.
So I can factorise X * 3 as
X * 3 = X + (X * 2)
so in the function you have:
X * Y = X + (X * (Y-1))
Therefore
X * Y = Multiply(X, Y) = (X + Multiply(X, Y -1))
Which is essentially the recursion.
To explain with an Example...
Multiply(5, 4) will call
Multiply(5, 3) will call
Multiply(5, 2) will call
Multiply(5, 1)
For each call it will cumulatively add 5 like
5 + 5 + 5 + 5 = 20
Good Luck!
Simple. For e.g.
5 + 5 + 5 = 5 x 3
We can simply put this as Multiply(5, 3)
it is :
x + y(count)-1.
x+(x + (y count-1))
Example :
if x=3 y=4
x+((y-1))
3+(3)=> iteration1
3+(3+3) => iteration 2
3+(3+3+3) => iteration 3
Final => 3+(3+3+3)
Result => 12
Recursion is not the way to go for this requirement given stack limits. Also, evaluate your function with (1, 0) to observe the case where y is less than 1.
Here's a way to "multiply" using addition only with the aid of incrementing which is arguably +/- 1 addition:
static int Multiply(int x, int y)
{
int result = 0;
while (y > 0)
{
result += x;
y--;
}
while (y < 0)
{
result -= x;
y++;
}
return result;
}
That method is not correct because it crashes when you try to multiply by zero.
I wrote a correct method.
public static int Product(int a, int b)
{
if (a == 0 || b == 0) return 0;
else return a + Product(a,b - 1);
}
I'm trying to implement Improved Noise in my XNA game, but my Improved Noise function keeps returning 0.0f. It's the exact same code as Ken Perlin's (http://mrl.nyu.edu/~perlin/noise/), just ported to C#.
I've tried rewriting the class and even copy and pasting directly from the site (and then porting to C#, of course), but it just won't output any value but 0.
Here's the code that I'm using:
public class PerlinNoise
{
private int[] permutations = new int[512];
private Random random;
public PerlinNoise()
: this(Environment.TickCount)
{ }
public PerlinNoise(int seed)
{
random = new Random(seed);
for (int i = 0; i < 256; i++)
{
permutations[i] = i;
}
for (int i = 0; i < 256; i++)
{
int k = random.Next(256 - i) + i;
int l = permutations[i];
permutations[i] = permutations[k];
permutations[k] = l;
permutations[i + 256] = permutations[i];
}
}
private int fastfloor(float x)
{
return x > 0 ? (int)x : (int)x - 1;
}
private float fade(float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
private float lerp(float t, float a, float b)
{
return a + t * (b - a);
}
public float grad(int hash, float x, float y, float z)
{
int h = hash & 15;
float u = h < 8 ? x : y,
v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
public float noise3d(float x, float y, float z)
{
int X = fastfloor(x) & 0xff,
Y = fastfloor(y) & 0xff,
Z = fastfloor(z) & 0xff;
x -= fastfloor(x);
y -= fastfloor(y);
z -= fastfloor(z);
float u = fade(x);
float v = fade(y);
float w = fade(z);
int A = permutations[X] + Y, AA = permutations[A] + Z, AB = permutations[A + 1] + Z,
B = permutations[X + 1] + Y, BA = permutations[B] + Z, BB = permutations[B + 1] + Z;
return lerp(w, lerp(v, lerp(u, grad(permutations[AA], x, y, z),
grad(permutations[BA], x - 1, y, z)),
lerp(u, grad(permutations[AB], x, y - 1, z),
grad(permutations[BB], x - 1, y - 1, z))),
lerp(v, lerp(u, grad(permutations[AA + 1], x, y, z - 1),
grad(permutations[BA + 1], x - 1, y, z - 1)),
lerp(u, grad(permutations[AB + 1], x, y - 1, z - 1),
grad(permutations[BB + 1], x - 1, y - 1, z - 1))));
}
public float noise2d(float x, float y)
{
return noise3d(x, y, 0f);
}
} `
To test it, I simply did:
string[] args = Console.ReadLine().Split(' ');
PerlinNoise noise = new PerlinNoise();
int x = args[0];
int y = args[1];
int z = args[2];
Console.WriteLine(noise.noise3d(x, y, z));
And as I said above, it'll always output 0.
It seems to output 0.0f if all arguments are integral numbers. Change your testing code to
var input = Console.ReadLine()
.Split(' ')
.Select(s => float.Parse(s,
System.Globalization.CultureInfo.InvariantCulture))
.ToArray();
and try to enter, for example, 4234.2123 3123.12312 423.2434.
I'm not quite sure if it is desired behavior, but
x -= Math.Floor(x); // FIND RELATIVE X,Y,Z
y -= Math.Floor(y); // OF POINT IN CUBE.
z -= Math.Floor(z);
will always make x, y & z = 0 if they are integral numbers; fade(0.0f) is also always zero.
Multiply your inputs by (1 / MAX_VALUE) in your input case, just multiply by 1 / 256 or so, and never give it anything larger than that. When used in your game, multiply the input by (1 / MAXIMUM_CHOORD_VALUE).