If statement inside If statement condition - c#

I have this code:
int a, b;
if (a > 0)
{
a--;
DoSomething()
}
else if (b > 0)
{
b--;
DoSomething();
}
I heard it's better to not write the same line (DoSomething();) twice, so is there a way to do this:
int a, b;
if (a > 0 /* if true a--; */ || b > 0 /* if true b--; */)
{
DoSomething();
}
In other words, is there a better way to do this (without writing DoSomething(); twice):
int a, b;
if (a > 0)
{
a--;
DoSomething()
}
else if (b > 0)
{
b--;
DoSomething();
}

If these are the only or the last statements in the method, you could return in an additional else statement:
if (a > 0)
{
a--;
}
else if (b > 0)
{
b--;
}
else
{
return;
}
DoSomething();
If these are the last statements in a loop you can use continue instead of return. In a switch case you can use break.
If DoSomething involves something more complex, then using a flag would be appropriate. Otherwise calling DoSomething twice is just fine.
bool isDecremented = false;
if (a > 0)
{
a--;
isDecremented = true;
}
else if (b > 0)
{
b--;
isDecremented = true;
}
if (isDecremented)
{
// Do something more complex.
}

int a, b;
if (a > 0 || b > 0)
{
if(a > 0)
a--;
else
b--;
DoSomething();
}

You could use a local method to avoid the repetition:
void DecrementAndDoSomething(ref int i)
{
i--;
DoSomething();
}
if (a > 0) DecrementAndDoSomething(ref a);
else if (b > 0) DecrementAndDoSomething(ref b);

How about writing like this?
if ((a > 0 && a-- > 0) || (b > 0 && b-- > 0))
DoSomething();

Related

GCD of three numbers (without using array) euclidean algorithm

I have a task, that gives me a little headache here. The goal is to find Greatest Common Divisor with three integers, I succeded in doing it with two fairly easily, but with three it get's a little complicated when I can't use any arrays.
Here is the full code I used, finding gcd from two integers, tests all green:
public static int GetGcdByEuclidean(int a, int b)
{
if (a == 0 && b == 0)
{
throw new ArgumentException(null);
}
else if (a == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(a));
}
else if (b == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(b));
}
else
{
int abs1 = Math.Abs(a);
int abs2 = Math.Abs(b);
a = abs1;
b = abs2;
while (a != 0 && b != 0)
{
if (a > b)
{
a %= b;
}
else
{
b %= a;
}
}
return a | b;
}
}
And now I used the same principle for the GCD by three, but used something I found on web: gcd(a, b, c) = gcd(a, gcd(b, c)) = gcd(gcd(a, b), c) = gcd(gcd(a, c), b)..
public static int GetGcdByEuclidean(int a, int b, int c)
{
int result = 0;
if ((a == 0 && b == 0) && c == 0)
{
throw new ArgumentException(null);
}
else if (a == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(a));
}
else if (b == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(b));
}
else if (c == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(c));
}
else
{
int abs1 = Math.Abs(a);
int abs2 = Math.Abs(b);
int abs3 = Math.Abs(c);
a = abs1;
b = abs2;
c = abs3;
while (a != 0 && b != 0 && c != 0)
{
if (a > b && a > c && b > c)
{
b %= c;
a %= b;
result = a;
}
else if (a > b && a > c && b < c)
{
c %= b;
a %= c;
result = a;
}
else if (b > a && b > c && a > c)
{
a %= c;
b %= a;
result = b;
}
else if (b > a && b > c && a < c)
{
c %= a;
b %= c;
result = b;
}
else if (c > a && c > b && a > b)
{
a %= b;
c %= a;
result = c;
}
else
{
b %= a;
c %= b;
result = c;
}
}
return result;
}
}
Just keep your solution for 2 numbers and call it from the one for three numbers by using this formula: gcd(a, b, c) = gcd(a, gcd(b, c))
public static int GetGcdByEuclidean(int a, int b)
{
// Your working solution for two numbers...
}
public static int GetGcdByEuclidean(int a, int b, int c)
{
return GetGcdByEuclidean(a, GetGcdByEuclidean(b, c));
}
Note, in C# you can have several methods with the same name, as long as the parameter lists are different. The names of the parameters do not matter, only the number or types of the parameters must be different. This is called overloading.
A solution with an arbitrary number of numbers (but at least two):
public static int GetGcdByEuclidean(int a, int b, params int[] other)
{
int gcd = GetGcdByEuclidean(a, b);
foreach (int x in other) {
gcd = GetGcdByEuclidean(gcd, x);
}
return gcd;
}

Are switch-case statements allowed for multiple conditions?

I was going to do a complex number class, and I appear to have too many conditionals involving multiple statements on one of my functions. Here is a snippet of my program with a ToString() function:
public override string ToString()
{
if (this.real == 0 && this.imaginary == 0)
{
return "0";
}
else if (this.real == 0 && this.imaginary == 1)
{
return "i";
}
else if (this.real == 0 && this.imaginary == -1)
{
return "-i";
}
else if (this.real == 0 && (this.imaginary != 1 && this.imaginary != -1))
{
return String.Concat(this.imaginary.ToString(), "i");
}
else if (this.real != 0 && this.imaginary == 0)
{
return String.Concat(this.real.ToString());
}
else if (this.real != 0 && this.imaginary == 1)
{
return String.Concat(this.real.ToString(), " + i");
}
else if (this.real != 0 && this.imaginary == -1)
{
return String.Concat(this.real.ToString(), " - i");
}
else if (this.real != 0 && this.imaginary < -1)
{
this.imaginary = -this.imaginary;
return String.Concat(this.real.ToString(), " - ", this.imaginary.ToString(), "i");
}
return String.Concat(this.real.ToString(), " + ", this.imaginary.ToString(), "i");
}
Would switch statements be helpful for multiple conditions?
Make code more readable with eliminating redundant checks.
Use string interpolation instead of String.Concat
public override string ToString()
{
if (real == 0)
{
if (imaginary == 0)
{
return "0";
}
if (imaginary == 1)
{
return "i";
}
if (imaginary == -1)
{
return "-i";
}
if (imaginary != 1)
{
return $"{imaginary}i";
}
}
else
{
if (imaginary == 0)
{
return real.ToString();
}
if (imaginary == 1)
{
return $"{real} + i";
}
if (imaginary == -1)
{
return $"{real} - i";
}
if (imaginary < -1)
{
imaginary = -imaginary;
return $"{real} - {imaginary}i";
}
}
return $"{real} + {imaginary}i";
}
You cannot have more than one condition in switch, but it looks like this.real has only two possibilities, 0 or 1, so you can take that out an use a switch for this.imaginary.
Also it is probably better to use String.Format() or String Interpolation instead of String.Concat().
public override string ToString() {
if (this.real == 0) {
switch(this.imaginary) {
case 0:
return "0";
case 1:
return "i";
case -1:
return "-i";
default:
return $"{this.imaginary}i";
}
else {
switch(this.imaginary) {
case 0:
return this.real.ToString();
case 1:
return $"{this.real} + i";
case -1:
return $"{this.real} - i";
default:
if (this.imaginary < -1) {
this.imaginary = -this.imaginary;
return $"{this.real} - {this.imaginary}i";
}
}
}
return $"{this.real} + {this.imaginary}i";
}
Your code is overcomplicated and redundant because you've come up with a separate branch for each possible situation. Your code will be a lot simpler if you break it down and do the following:
Get the real part (if there is one) and the imaginary part (if there is one)
Combine them together if there are two parts
The following will do this:
private string RealPartString()
{
if (real == 0) { return imaginary == 0 ? "0" : null; }
return real.ToString();
}
private string ImaginaryPartString()
{
if (imaginary == 0) { return null; }
var abs = Math.Abs(imaginary);
var number = abs == 1 ? "" : abs.ToString();
// Only include the sign here if there is no real part
var sign = real == 0 && imaginary < 0 ? "-" : "";
return sign + number + "i";
}
public override string ToString()
{
var parts = new[] { RealPartString(), ImaginaryPartString() }.Where(s => s != null);
var sign = imaginary < 0 ? " - " : " + ";
return string.Join(sign, parts);
}

Increase stack size c#

My code generates characters 'L' into 2D-Array on random place, but I need program to check if there isn't 'L' already and if it is there, program should go through process of generation again. But there comes the problem, because Stackoverflowexception shows up. Does anybody have an idea how to change my code, or how to increase stack size?
(I have to mention, that I already tried increase stack size using Project Properties, but I don't have there Linker option. And also I'm new to programming, so I don't know how to use editbin or commands). Thanks in advance.
EDIT:
public void Generate()
{
Fill();
Fleet();
}
public void Fleet()
{
Ship2(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship4(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship5(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
}
public void Ship2(int x, int y, int r)
{
if (r == 0)
{
CreateShip(x, y);
CreateShip(x, (y + 1));
}
if (r == 1)
{
CreateShip(x, y);
CreateShip(x, (y + -1));
}
if (r == 2)
{
CreateShip(x, y);
CreateShip((x-1), (y));
}
if (r == 3)
{
CreateShip(x, y);
CreateShip((x+1), (y));
}
}
public void CreateShip(int x, int y)
{
if (x <= 9 && y <= 9 && x >= 0 && y >= 0)
{
if (Board[x, y] == 'L')
{
Generate();
}
else
{
Board[x, y] = 'L';
}
}
else
{
Generate();
}
}
This is the important part of code.
What you can do is: If Creation fails pass back a bool and try again from scratch.
public void Generate()
{
Fill();
while(!Fleet())
{
// I assume Fill clears your board again?!
Fill();
}
}
public bool Fleet()
{
return Ship2(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship4(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship5(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
}
public bool Ship2(int x, int y, int r)
{
if (r == 0)
{
return CreateShip(x, y) &&
CreateShip(x, (y + 1));
}
if (r == 1)
{
return CreateShip(x, y) &&
CreateShip(x, (y + -1));
}
if (r == 2)
{
return CreateShip(x, y) &&
CreateShip((x-1), (y));
}
if (r == 3)
{
return CreateShip(x, y) &&
CreateShip((x+1), (y));
}
return false;
}
public bool CreateShip(int x, int y)
{
if (x <= 9 && y <= 9 && x >= 0 && y >= 0)
{
if (Board[x, y] == 'L')
{
return false;
}
else
{
Board[x, y] = 'L';
}
}
else
{
return false;
}
return true;
}
Note: This will still not work, if the input parameters to CreateShip never change. You will now not see any Exception but the Generate method will never finish.

Only assignment, call, decrement can be used

I'm trying to find integers in a certain range that are prime. I seem to be getting an error when I put a for loop in my else statement.
private static bool prime(int n,out int factor)
{
factor = 1;
if (n < 2)
return false;
else if (n == 2 || n == 3)
return true;
else if( n % 2 == 0)
return false;
for(int r = 3; r < (Math.Sqrt(n) + 1); r + 2)
{
if ((Convert.ToInt32(n)) % r == 0)
return false;
}
}
for(int r=3;r<(Math.Sqrt(n)+1);r+2)
r+2 creates a result, but it isn't assigned to anything. You want either r = r + 2 or r += 2
There are couple of problems with your code.
Firstly you can fix the assigment problem like
r=r+2
secondly, your function needs to return something from all code paths. Which it isn't doing at the moment. I have returned true at the end, though you can choose your logic here.
private static bool prime(int n, out int factor)
{
factor = 1;
if (n < 2)
return false;
else if (n == 2 || n == 3)
return true;
else if (n % 2 == 0)
{
return false;
}
for (int r = 3; r < (Math.Sqrt(n) + 1); r = r + 2)
{
if ((Convert.ToInt32(n)) % r == 0)
return false;
}
return true;
}

What does it mean when a method returns t > 1 as a boolean?

Can someone explain what the use/meaning is of the following return statement: t > 1; (see last if statement last method)
the code is from a game called "Reversi" http://en.wikipedia.org/wiki/Reversi
This method checks if you enclose a stone of another player.
public bool allowed(int x, int y, bool player)
{
int color;
if(player == true) // true = player is blue.
color= 1;
else color= -1;
if(stone[x,y] != 0)
return false;
else
{
for (int dx = -1; dx <= 1; dx ++)
{
for (int dy = -1; dy <= 1; dy ++)
{
if (dx != 0 || dy != 0) // 0, 0 must be skipped, own stone.
{
if (close(color, x, y, dx, dy))
return true;
}
}
}
}
return false;
}
public bool close(int color, int x, int y, int dx, int dy)
{
int s;
int testx;
int testy;
for(int t=1; t<stone.Length;t++)
{
testx = x + t * dx;
testy = y + t * dy;
if(testx >= board.Width || testx <= 0 || testy >= board.Heigth|| testy <= 0)
return false;
s = stone[x + t * dx, y + t * dy];
if (s == 0) return false;
if (s == color) return t>1;
}
return true;
}
This code:
return t > 1;
Is equivalent to:
if (t > 1)
{
return true;
}
else
{
return false;
}
Except the latter approach is unnecessarily verbose and unfortunately quite common to see in real code.
Any expression to the right of a return statement is evaluated, and then the value is returned from the function.
In this case, t can either be greater than 1, or not - meaning it's either true or false - meaning either true or false will be returned, depending on the value of t.
It's exactly equivalent to:
if(t>1)
return true;
else
return false;
Returns true if t is greater than 1, otherwise it returns false.
return t > 1;
is same as
if (t > 1)
return true;
else
return false;
is same as
bool greaterThanOne;
if (t > 1)
greaterThanOne = true;
else
greaterThanOne =false;
return greaterThanOne;
return t>1 is equal to
if (t > 1)
{
return true;
}
else
{
return false;
}
Also there is an another using of return like;
static string AmIAwesome(bool b)
{
return b ? "Yes, I'm" : "No, I'm not";
}
Which is the same logic with first one.

Categories