How do I detect an infinite loop occuring in my code? - c#

So my code is to check if a given number is a 'happy number'. It squares each digit of the number, adds them and continues to do so until either the result of the addition is 1 (which means it is a happy number) or until it results in a 4 (which means it is not a happy number).
What's happening is that there are many numbers which cause an infinite loop (therefore meaning they are not a happy number) and I'm wondering how I would construct my code so that it will detect when there's an infinite loop occuring? I have some ideas but all flawed.
My code is as follows:
using System;
namespace Happy_numbers_problem
{
class Program
{
static int HappyNumbers(string Number)
{
string Output = Number;
while ((Convert.ToInt32(Output) != 1) && (Convert.ToInt32(Output) != 4))
{
string Result2 = "0";
for (int Index = 0; Index < Output.Length; Index++)
{
string Character = Output.Substring(Index, 1);
int Calc = Convert.ToInt32(Character);
int Result = Calc * Calc;
//Adding Result2 and Result, then turning it into a string.
Result2 = Convert.ToString(Convert.ToInt32(Result2) + Result);
if (Index == (Output.Length) - 1)
{
Output = Result2;
}
}
}
return Convert.ToInt32(Output);
}
static void Main(string[] args)
{
Console.WriteLine("Please enter a number");
string Number = Console.ReadLine();
int Output = HappyNumbers(Number);
if (Output == 1)
{
Console.WriteLine(Number + " is a happy number");
}
else if (Output == 4)
{
Console.WriteLine(Number + " is not a happy number");
}
else
{
Console.WriteLine(Number + " is not a happy number");
}
}
}
}

The problem resides in your while condition. If your output needs to be 1 or 4 to break out of the loop and deliver the output to latter be analysed, you have to use the operator or || instead of the operator and &&.

Related

Elements in array (when reproduced from a dictionary value) are reversed

My goal is to make a math expression interpreter with c#, for example if you type "A=3", it'll save the A as a dictionary key and 3 as its value, this program has more features so if you type "B=3" and then "A=B+3" and then "Show(A)", it must display "6" as the answer.
Everything is right until I type something like "A=10" "B=10" "C=A+B" and finally "Show(C)", because Variables' value are 2-digit (or more) numbers in this case, when producing the final result, numbers are saved in the string like "01+01" instead of "10+10" (because A and B values are 10 so A+B should be 10+10), so it's kinda reversed.
I tried to reverse the string and then evaluate the answer but that didn't work as well, simply it gives me "1+1" for some reason!
Notes:
expression evaluation is done by "return Convert.ToInt32(new DataTable().Compute(result, null));"
because strings are immutable in c#, when every expression like "A+B" or "3+5" comes in the method, I create a new empty string like (string result = " ";) and then with the help of "result = ValidExpression[i] + result.Remove(counter, 0);", I change the variables with values (note = if all the elements of input are numbers, answer is right) like "A" with "23" and put them in the new string and then evaluate the final string. But as I said, it saves the 23 as 32 so the answer will be wrong.
This is my code and the bug is probably in the LongProcessing method.
Thanks for your helps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Data;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome To The Program\nCorrect Syntax:");
Console.WriteLine("A=10\nB=15\nC=A+B\nD=13/4-2+A-C+B\nShow(D)");
Console.WriteLine("\nEnter your input:");
Expression E = new Expression();
string expression = "start";
while (expression != "exit")
{
expression = Console.ReadLine();
// for show command
if (expression.Contains("Show") == true)
try { E.Show(expression[5]); }
catch (Exception e)
{
Console.WriteLine("input is not correct, Can not show anything. please try again");
}
if (E.Validation(expression) == false)
Console.WriteLine("input is not correct, please try again");
else
E.Processing(expression);
}
Console.ReadKey();
}
}
class Expression
{
public Dictionary<Char, String> Variables = new Dictionary<Char, String>();
public Expression()
{ }
public Boolean Validation(string expression)
{
// true if c is a letter or a decimal digit; otherwise, false && true if c is a decimal digit; otherwise, false.
if (!Char.IsLetterOrDigit(expression[0]) || Char.IsDigit(expression[0]))
return false;
else
return true;
}
public void Processing(String ValidExpression)
{
// Update Dictionary with new values per key
if (Variables.ContainsKey(ValidExpression[0]))
Variables.Remove(ValidExpression[0]);
string temp = " ";
if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
{
// removing the variable name and "=" from the string
for (int i = 2; i < ValidExpression.Length; i++)
temp = ValidExpression[i] + temp.Remove(i, 0);
Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
}
}
// something is wrong in this method
public int LongProcessing(String ValidExpression)
{
string temp;
int counter = 0;
string result = " ";
for (int i = 0; i < ValidExpression.Length; i++)
{
//changing variables (letters) with values
if (Char.IsLetter(ValidExpression[i]))
{
if (Variables.ContainsKey(ValidExpression[i]))
{
Variables.TryGetValue(ValidExpression[i], out temp);
for (int j = 0; j < temp.Length; j++)
{
result = temp[j] + result.Remove(counter, 0);
counter++;
}
}
}
else
{
result = ValidExpression[i] + result.Remove(counter, 0);
counter++;
}
}
// checks if all of the string elements are numbers
if (ValidExpression.All(char.IsDigit))
return Convert.ToInt32(ValidExpression);
else
{
return Convert.ToInt32(new DataTable().Compute(result, null));
}
}
public void Show(Char ValidExpression)
{
Console.WriteLine(Variables[ValidExpression]);
}
}
}
This is broken:
for (int i = 2; i < ValidExpression.Length; i++)
temp = ValidExpression[i] + temp.Remove(i, 0);
temp.Remove(i, 0) is a non op, you might as well just write temp
So let's plot the loop:
Assume ValidExpression is "A=10"
Temp starts out as " "
First iteration, temp is "1 "
Second iteration, temp is "01 "
Any operation that works left to right through a string, character by character, pulling a character out and sticking it on the start of a growing string, will reverse the string
Perhaps you meant to not have a loop and instead do temp = ValidExpression.Substring(2) ?
Here are some suggestions:
Start by looking at the value of "temp" in "Processing". To assist in your debugging, add a "Console.WriteLine" statement.
public void Processing(String ValidExpression)
{
// Update Dictionary with new values per key
if (Variables.ContainsKey(ValidExpression[0]))
Variables.Remove(ValidExpression[0]);
string temp = " ";
if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
{
// removing the variable name and "=" from the string
for (int i = 2; i < ValidExpression.Length; i++)
{
temp = ValidExpression[i] + temp.Remove(i, 0);
Console.WriteLine(" temp: " + temp); //added for debugging
}
Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
}
}
A couple of other things:
The user is never informed how to exit.
There is a class named "Expression" and a string variable named
"expression". This is likely to cause confusion.
You may also want to look at this post: how to convert a string to a mathematical expression programmatically

How do I make a statement follow the same "if" rules as before

I am trying to write a mini-quiz and I want the "try again" button to follow the same rules as the "if" statement as before the "else"
using System;
public class Program
{
public static void Main()
{
int x;
x = int.Parse(Console.ReadLine());
Console.WriteLine("Find a number that can be divided by both 7 and 12");
if ((x % 7 == 0) && (x % 12 == 0))
{
Console.WriteLine("well done, " +x+ " can be divided by 7 and 12");
}
else
{
Console.WriteLine("Wrong, try again.");
Console.ReadLine();
}
}
}
I want the ReadLine after the else statement to follow the same rules as the "if" statement before it but it needs a whole new statement to follow and copy-pasting the statement seems like an inefficient solution.
Normally this kind of processing is done in a while loop, which continues to loop until the user answers correctly. So the key is then to create a condition that will become false when there's a correct answer.
Notice that we also have the x variable re-assigned to the Console.ReadLine() method in the else block, otherwise we're always comparing the old value of x and the loop will never end.
For example:
bool answeredCorrectly = false;
while (!answeredCorrectly)
{
if ((x % 7 == 0) && (x % 12 == 0))
{
Console.WriteLine("well done, " + x + " can be divided by 7 and 12");
answeredCorrectly = true; // This will have us exit the while loop
}
else
{
Console.WriteLine("Wrong, try again.");
x = int.Parse(Console.ReadLine());
}
}
If you want to be really tricky about it, you could write a method that will get an integer from the user, and which takes function that can be used to validate that the input is correct (any method that takes in an int and returns a bool).
This way, you can create a validation method and pass that (along with the prompt for the user) to the method that gets an integer from the user.
Note that we're using the int.TryParse method to try to get an integer from the string input. This method is really handy because it does two things: First, it returns true if the parsing succeeds, and second, it returns the int value in an out parameter. This way we can use the return value to ensure they entered a number, and we can use the output parameter to see if the number meets our conditions:
private static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
{
int result = 0;
bool answeredCorrectly = false;
while (!answeredCorrectly)
{
// Show message to user
Console.Write(prompt);
// Set to true only if int.TryParse succeeds and the validator returns true
answeredCorrectly = int.TryParse(Console.ReadLine(), out result) &&
(validator == null || validator.Invoke(result));
if (!answeredCorrectly) Console.WriteLine("Incorrect, please try again");
}
return result;
}
With this method in place, we can now call it from our main method as often as we like, with whatever validation we like, and we don't need to re-write all the looping code each time:
int x = GetIntFromUser("Enter a number that can be divided by both 7 and 12: ",
i => i % 7 == 0 && i % 12 == 0);
x = GetIntFromUser("Enter a negative number: ", i => i < 0);
x = GetIntFromUser("Enter a number between 10 and 20: ", i => i > 10 && i < 20);
You could even use it to create a number guessing game with just a few lines of code!
int randomNumber = new Random().Next(1, 101);
int x = GetIntFromUser("I'm thinking of a number from 1 to 100. Try to guess it: ", i =>
{
Console.WriteLine(i < randomNumber
? $"{i} is too low - guess a larger number."
: i > randomNumber ? $"{i} is too high - guess a smaller number." : "Correct!");
return i == randomNumber;
});
Have you considered using a while block and break; on the successful condition?
using System;
public class Program
{
public static void Main()
{
int x;
Console.WriteLine("Find a number that can be divided by both 7 and 12");
while (true)
{ //Loop the code until it is broken out of
x = int.Parse(Console.ReadLine());
if ((x % 7 == 0) && (x % 12 == 0))
{
Console.WriteLine("well done, " + x + " can be divided by 7 and 12");
Console.ReadKey(); //Pause the program so it doesnt break out immediately
break; //Break out of the while loop
}
else
{
Console.WriteLine("Wrong, try again.");
}
}
}
}

C# code issue - Code not working properly

I wrote a basic number guessing game from C#. It seems to return the 3rd option ("Wrong choice! Please try again.") every time no matter what var c is chosen by the user. I was trying with characters (s instead of 1 and w instead of 2 etc with c as a string) but it gave the same results. Not sure where it's going bad.
using System;
namespace Challanges
{
class Program
{
static int guess = 500;
static int low = 1;
static int high = 1000;
static bool cont = false;
static void Guess() //guesses and adjusts variables according to input.
{
int c;
Console.WriteLine("Is your number greater or less than: " + guess + Environment.NewLine + "If it is less than, press 1; if it is greater, press 2." + Environment.NewLine + "If it is your number, press 3.");
c = Convert.ToInt32(Console.Read());
if (c == 1)
{
high = 500;
guess = low + high / 2;
}
else if (c == 2)
{
low = 500;
guess = low + high / 2;
}
else if (c == 3)
{
Console.WriteLine("Congratulations!! We found your number!");
cont = true;
}
else
{
Console.WriteLine("Wrong choice! Please try again.");
Console.ReadKey();
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!" + Environment.NewLine + "Let's play a guessing game. Think of a number between 1 and 1000." + Environment.NewLine + "Type your number :)");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Your number is: " + x + Environment.NewLine + "Too easy?");
Console.ReadKey();
Console.WriteLine("Think of a number");
if(cont == false)
{
Guess();
} else
{
Console.ReadKey();
}
}
}
}
As mentioned in the comments before, Console.Read() returns a character code. The character code for the number 1 is 49, thus your conditions fail and the else block is executed.
What you wanted to do was use Console.ReadLine()which returns a string instead of character codes. If you cast that string into an Int32 you should be able to evaluate your conditions correctly.

How do I locate a specific digit

I am trying to create 7 BOOM game. if you don't know the rules, everyone takes turns and says the next number but if the number can be divided by seven or contain seven you should say BOOM instead. so in my version, you insert a number and the program should show you all the numbers to that point.
So here is my problem, I succeeded in implementing the first part but I am having a problem with the second one. This is what I have until now:
class Program
{
static void Main(string[] args)
{
int num1 = int.Parse(Console.ReadLine());
int num2 = 0;
bool boolean;
while (num1>num2)
{
num2++;
if (num2%7 == 0)
{
Console.Write("BOOM, ");
}
else
{
Console.Write(num2 + ", ");
}
}
}
}
Just change your validation to:
if (num2%7 == 0 || num2.ToString().IndexOf('7') != -1)
{
// (..)
}
The IndexOf function looks for and returns the position of a substring in a string. If it is not found, it returns -1.
As pointed by #Dimitry, another option is
if (num2%7 == 0 || num2.ToString().Contains('7'))
{
// (..)
}
This uses the extension method Contains that returns true or false if the substring exists on the string.
public static void Main()
{
Console.Write("Please enter a number: ");
int number = int.Parse(Console.ReadLine());
// validate number here....
for (int i = 1; i <= number; i++)
{
string value = IsMultipleOrContains7(i) ? "BOOM" : i.ToString();
Console.WriteLine(value);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
public static bool IsMultipleOrContains7(int number)
{
if (number % 7 == 0)
{
return true;
}
return number.ToString().Contains("7");
}

How can I make a program loop back to the start if else is true? C#

Couldn't find any other answer on the site that covers this. If else is run and an error message is displayed, is it possible to restart the program by looping back to the start instead of restarting the console?
class Program
{
static void Main(string[] args)
{
int User;
int Array;
StreamWriter outfile = new StreamWriter("C://log.txt");
Console.WriteLine("Input an number between 1 and 100");
User = Convert.ToInt32(Console.ReadLine());
if (User < 101 && User > 0)
{
for (Array = 1; Array <= User; Array++)
{
Console.WriteLine(Array + ", " + Array * 10 * Array);
outfile.WriteLine(Array + ", " + Array * 10 * Array);
}
{
Console.WriteLine("Press Enter To Exit The Console");
outfile.Close();
Console.ReadLine();
}
}
else
{
Console.WriteLine("Sorry you input an invalid number. ");
Console.ReadLine();
}
}
}
Sorry! To be more clear I need to make the Program start again if the user inputs an invalid number
Thanks for the help!
You can do this instead
User = Convert.ToInt32(Console.ReadLine());
while (User >= 101 || User <= 0)
{
Console.WriteLine("Sorry you input an invalid number. ");
User = Convert.ToInt32(Console.ReadLine());
}
An easy way of doing this is placing your code inside a while loop, so that the code keeps repeating. The only way to exit the loop would be for the condition you just set in the if clause to be true. So something along the lines of:
class Program
{
static void Main(string[] args)
{
int User;
int Array;
bool isUserWrong = true; //This is a flag that we will use to control the flow of the loop
StreamWriter outfile = new StreamWriter("C://log.txt");
while(isUserWrong)
{
Console.WriteLine("Input an number between 1 and 100");
User = Convert.ToInt32(Console.ReadLine());
if (User < 101 && User > 0)
{
for (Array = 1; Array <= User; Array++)
{
Console.WriteLine(Array + ", " + Array * 10 * Array);
outfile.WriteLine(Array + ", " + Array * 10 * Array);
}
isUserWrong = false; // We signal that we may now leave the loop
}
else
{
Console.WriteLine("Sorry you input an invalid number. ");
Console.ReadLine();
//Note that here we keep the value of the flag 'true' so the loop continues
}
}
Console.WriteLine("Press Enter To Exit The Console");
outfile.Close();
Console.ReadLine();
}
}

Categories

Resources