With some help I have managed to get the right answer to these questions but I want to get my head around the concepts (i.e. understanding why these codes are correct), as understanding is very important and not just memory of syntax.
The first question is You're given the result of 3 competitions (true = win) , the prize for the first is 1, second is 2, third is 3. Return the total prize amount (you can win any combination of prizes)
The answer is:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
How does the program know that if you were to win, let's say, the first, second and third prizes, that the total is 6? Or if you were to win the first and third, the total is 4? In other words, how does the code above account for all possible combinations?
The second question is You're given the result of 3 competitions in one of which you've won (true = win). The prize for the first is 1, second is 2, third is 3. Return the prize amount.
My answer is:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Without the "return 0;" part at the end, my code was shown as incorrect. Why? As the question states that I have won one of the prizes, so in other words, I am not leaving the competition empty-handed.
Thanks in advance
Well, lets take it step by step.
First answer:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
What happens here is the following:
The variable result is initialized with a value of 0.
What follows is a series of if statements. Notice how they are only if and not if-else, meaning they are not mutually exclusive.
When an if statement is true, then result += [some number] happens. This means that result is assigned the value (result + [some number]).
Finally, result is returned.
Second answer:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Over here you are told that you have won one of them for sure. If you have not won the first, then you could have won the second or the third. If you have also not won the second, then you must have won the third. So the correct code would be:
if (first)
return 1;
else if (second)
return 2;
else
return 3;
In this case, the if statements are mutually exclusive, since you are told you have won one of them. Unlike the first answer, this syntax guarantees that one of the values (1, 2, or 3) will be returned.
The return guarantee is important because you have defined your function as having return type int. This means that, no matter what happens in the code, it will always return an int. In your code, if it weren't for the return 0, then there would be no return statement if all ifs were false. Of course, you are told that at least one will be true. The compiler however doesn't know that, and so it won't let you compile a function that doesn't fulfill the requirement of always returning a value.
The first piece of code works as follows (reading as pseudocode)
define a numer named result
set its value to 0
if the parameter (first) equals true, add 1 to result
[do this again for (second), and (third), but with their respective numeric values]
return result
it just counts the score, then returns it.
The second part of your question :
you defined your method as guaranteeing to return an int. thus, you cannot write the method without following up on that guarantee. you cannot return NOTHING (void), or the compiler will complain.
you also cannot return null , since an int is not nullable.
If we took the logic of your second question, and were told to make it capable of accepting any number of rounds, the reason for that last return statement might become more obvious:
public static int GetPrize(params bool[] scores)
{
for (int i = 0; i < scores.Length; i++)
{
if (scores[i]) // there is no guarantee any of the bools passed along equals true, so we might never hit this return statement.
return i + 1;
}
//if we never hit the first return statment,
//we will end up here, and will not have won anything.
//we still need to return an int, though.
return 0;
}
Related
I need to compare 2 strings using a For without using String.compare. (It's a homework ... I started programming C# 2 weeks ago)
I just can't figure out how to use the for loop to answer the question. I don't know what to put in for(). I tried for( string text1 = "something",) but I can't figure out what toput after the, in the for loop.
Since this is a homework question, I would recommend stop reading the answer as soon as you think you have enough information to solve it on your own before getting to the solution at the end.
Let's assume a simple method signature, first:
public static bool AreStringEqual(string str1, string str2)
{
}
And our goal is to implement (write the code for) this method. We'll assume our goal is Return true if the strings are equal, and return false if they are not. We won't do anything fancy like make it case insensitive.
We can do some basic checks on our strings, first. If they are of different length, then we can immediately assume the strings are different, and return false:
if (str1.Length != str2.Length)
{
return false;
}
This block checks the length, and if they differ, then false is immediately returned and the rest of the method doesn't get executed.
At this point we can guarantee the strings are the same length, so we can loop over the strings and compare them character by character using a for loop.
for(int counter = 0; counter < str1.Length; counter++)
{
}
This is a pretty standard for-loop that just counts a number from zero to one less than the length of the string. It doesn't matter if we use str1 or str2 for the upper bound of the loop since we already know they are the same length.
To get the character in a string, we can use the Indexer Syntax to get the character at a give position. The numbers start at zero in C# and .NET.
str1[0] gets the first character, str1[1] gets the second, etc.
We can then plug the variable in the for loop into the indexer for str1 and str2, then compare the characters. If they are not equal, then return false.
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
And finally, if the code gets through the for loop without returning false, then return true at the end. Putting it all together, it looks like this:
public static bool AreStringEqual(string str1, string str2)
{
if (str1.Length != str2.Length)
{
return false;
}
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
return true;
}
I've found a really cool feature of a compilator. However, I cannot understand logic of this behaviour.
static int IncrementValue(ref int i) { return i++;}
and Main method:
static void Main(string[] args)
{
int a = 2;
int b = IncrementValue(ref a);
Console.WriteLine(a+b);
}
The output is 5.
My question is:
Why is "b" field equal 2? (In my view, it ought to be 3 as "ref" keyword is not copying by value, but the keyword takes field by value. Consequently, "b" should be as "a+1")
Since you wrote it as;
return i++
This will still return 2 as a value but it will increase a value to 3 after the expression.
If you wrote it as;
return ++i
This will return incremented value which is 3, and since a will be 3 after the execute it, it will be printed 6 as a result.
Further reading
What is the difference between ++i and i++?
i++ is the post increment operator. It will increment the value afterwards, instead of before the value is returned.
Change i++ to ++i to make it increment before the value is returned, or increment the value in a separate statement and then return the value:
static int IncrementValue(ref int i) { return ++i; }
Or:
static int IncrementValue(ref int i) { i++; return i; }
(The reason you see different values when returning the integer, is that the result is copied. It is not a reference, else the return statement would not be useful at all).
I am doing a small project on 4x4 tic-tac-toe game. I am using Alpha Beta Search for finding the next best move. In the alpha beta search, I am using a cutoff evaluation function that is being called in "utility" function of the following algorithm
I implemented everything successfully, but the problem is the utility function doesn't return a negative value and I really don't know why! Following is the function
private static int utility(GameTreeNode gtn, bool isMin = false)
{
int nodeValue = 0;
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
nodeValue = 50;
if (isMin) nodeValue = -50; /// here
break;
case Status.Incomplete:
if (isMin)
nodeValue = gtn.evaluate(State.X);
else
nodeValue = gtn.evaluate(State.O);
break;
}
// case Status.Draw:
return nodeValue;
}
isMin is set to true, when it is called from MinValue function
isMin is the move of O and the AI's move is X. If O wins the utility is supposed to return -50. But it returns only 0. I debugged the program and it actually assigns -50 to nodeValue (nodeValue changes in the debugger to -50), but when I receive in the Min or Max function, it is zero.
Note: All the int used in the entire project is signed int. No unsigned keyword is used, if you are thinking the function-caller is unsigned
The full code of alpha-beta search is here: http://pastie.org/8538015
Please friends, help as soon as possible.
Since you're using an optional parameter in your method signature, I'd caution you to pay attention to what your code is actually running when entering your function. You said you debugged it and the value gets assigned, but I don't have enough context to know if it only happens in one of many cases or not. Anyway, just be careful with those!
I would rewrite your function like this:
private static int utility(GameTreeNode gtn, bool isMin)
{
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
return isMin
? -50
: 50;
case Status.Incomplete:
return isMin
? gtn.evaluate(State.X)
: gtn.evaluate(State.O);
default:
throw new NotImplementedException("The status is not implemented.");
}
}
A few improvements I see with this approach:
You don't need to store a value and return it at the end. In your case, you're always storing 50 into nodeValue when you take the Status.Success path, and then sometimes assigning -50 to it. Unless you're adamant about one return in your function, I think this approach is more clear. Might just be my opinion though.
There's a default in the switch statement so that you'll explicitly throw an exception in the case where you have a status that isn't implemented.
There is no optional parameter to your function. I don't see the benefit of making this parameter optional. In my opinion, it only looks like it's adding room to make things harder to debug.
EDIT:
Based on the code at:http://pastie.org/8538015#33,43
It looks like the only time you can ever get utility to return a negative value is when if (gtn.Nodes.Count == 0) return utility(gtn, true); is hit in the private static int MinValue(GameTreeNode gtn, int alpha, int beta) function. Otherwise, unless there's more code which you haven't posted, no other call to the utility function will hit the logical path your going for. You've mentioned when you step into there, you can see the value for nodeValue get properly assigned.
I'm suggesting you change:
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0) return utility(gtn, true);
gtn.Value = Globals.MAXINT;
To
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0)
{
int retVal = utility(gtn, true);
return retVal;
}
gtn.Value = Globals.MAXINT;
At least temporarily, and then put a breakpoint on return retVal. If your utility function is actually setting the value you expect like you say, there's no way that it could magically go away when it returns it to the MinValue function. I have a feeling something fishy is happening and the code isn't actually executing the path you expect.
I have a simple program that is used to pass inputs to an array given the inputted size and inputted elements by the user as follows:
Full code
All the code works fine except this snippet :
for(int i=0; i<size; i++) {
flagger = false;
while(flagger == false) {
System.Console.WriteLine("Please enter number " + i + " : ");
nextInput = System.Console.ReadLine();
flagger = errorCheck(nextInput);
}
int varPass = System.Convert.ToInt32(nextInput);
System.Console.WriteLine(flagger);
arr[i] = varPass;
}
No matter what size I input the loop exits early and sorts an array with some empty elements, can anyone see the problem?
In errorCheck you're setting the value of size as you're passing it in the out parameter.
So the next time the user inputs a number smaller than i the loop exits early.
Create a dummy int or handle your error checking differently.
Example:
static bool errorCheck(string input) {
int temp=0;
if (int.TryParse(input, out temp))
return true;
return false;
}
This "bug" happens because size is static.
You can simplify your code further by just returning the result of TryParse.
static bool checkErr(string input) {
int temp=0;
return int.TryParse(input, out temp);
}
You haven't included errorCheck method which seems crucial to me.
If errorCheck returns true the Loop WILL end prematurely.
EDIT: Oops, you did include a link to full code.
As my predecessor said, errorCheck(...) modifies "size". Maybe that's why I still prefix member variables with underscore. It's so easy to miss.
I have written a method in c# to get a count of a table, and saves the count in settings properties.
public static bool CompareCount(int? currentCount)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
if (currentCount < Properties.Settings.Default.Count)
{
return false;
}
else
{
return true;
}
}
At first time if the count returned is 20. I will save it in the settings and I shud not compare that wiht the previous count. ON second time I want to compare the current count wiht the previoulsy saved count in settings. The above method should assign the current count for the first time . but on second time it shud compare.
thanks in advance.
First of all, think about what would happen when you cast the int? that's coming in to int if the parameter is null. It doesn't make sense to use a nullable parameter if you don't do anything with it later on. You should either change the parameter type to int or you could do this:
Properties.Settings.Default.Count = currentCount ?? 0;
Then, the method will always return true, as the if condition is always false - remember you're setting Properties.Settings.Default.Count to currentCount just two lines above that? So how should it ever be larger than currentCount?
You need to define for yourself how to determine "the first time" and "the second time". What's the condition to find out whether the method is run for the first time? For the code below I'll assume that there's some default value for Properties.Settings.Default.Count that helps you determine whether the method runs for the first time.
Then, from what you say, your code should look like this:
public static bool CompareCount(int? currentCount)
{
int countValue = currentCount ?? 0;
if (Properties.Settings.Default.Count == <some default value>)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
}
else
{
return currentCount >= Properties.Settings.Default.Count;
}
}
What is your problem in implementing it? You have all the blocks already here at hand. Just reorder them properly.
If the problem is that the "int Count" defined in settings is "0" by default, you can change it i.e. to default to -1 so it obviously will be NOT a Count written before. Or, you can change it to int? to have default null..
Ask the current found Count to check if it is equal to the default value (zero, or not found or set your own once not found let say -1), so once not found you do not compare otherwise compare the values.
For Example:
public static bool CompareCount(int? currentCount)
{
int foundCount = ReadFoundCountFromProperties;
if (foundCount != 0)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
if (currentCount < foundCount)
return false;
return true;
}