Program to guess number gets incredibly slow - c#

So, I decided to have some fun and make a program that will come up with a number and you have to guess it with it telling you if you're too high/too low. However, I decided it would be more fun if the computer could come up with the random numbers itself.
I use a simple method here which basically has the program check if a value is in an array, and if it is, come up with another random number. And when a number is too high, start from the size of how large the number can be and go down to that number (that way if it's too high of a number, it never guesses that high or higher again).
So, this works great for small numbers. I think when doing a number like 1,000 or something, it guessed it within 15 tries. However, when I did a 10,000,000 (I know, it's a bit extreme, but I wanted to see C#'s power since I'm fairly new to the language).
The program got about 10 guesses in and it started slowing down incredibly. I had put in a 250ms sleep timer to make it look more like it was guessing (since it is instant for things like 1,000 or 10,000), but when taking it out, it still slowed down. I think this is probably because if it guesses a number like 3 million, it has to add 7 million values to an array (I'm using a List so that it has an "infinite" value).
So what exactly can I do at this point? I want it to be able guess big numbers, but it doesn't really seem possible at this point. How could I do this?
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Program {
class Program {
static void Main(string[] args) {
Random random = new Random();
int selectedNumber = random.Next(1, 101);
int maxNumber;
int guessNumber = 0;
int inputNumber = 0;
// Intro
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("Welcome to the High Low - Computer version program!");
System.Threading.Thread.Sleep(4000);
Console.WriteLine("\n--------------------------------------------------------");
Console.ForegroundColor = ConsoleColor.DarkYellow;
// This way the computer guesses rather than you
char who = 'C';
Console.Write("\nHow high do you want the computer's number to be max > ");
maxNumber = Convert.ToInt32(Console.ReadLine());
List<int> guessedNumbers = new List<int>();
selectedNumber = random.Next(1, maxNumber);
do {
// System.Threading.Thread.Sleep(250);
Console.ForegroundColor = ConsoleColor.DarkYellow;
if (who == 'M') {
Console.Write("\nPlease enter your guess > ");
guessNumber = Convert.ToInt32(Console.ReadLine());
}
else {
while (true) {
guessNumber = random.Next(1, maxNumber);
if (!(guessedNumbers.Contains(guessNumber))) {
guessedNumbers.Add(guessNumber);
inputNumber++;
break;
}
}
Console.WriteLine("Please enter your guess > {0}", guessNumber);
}
Console.ForegroundColor = ConsoleColor.DarkGreen;
if (guessNumber < selectedNumber) {
Console.WriteLine("\nYou're guessing too low!\n");
for (int i = 0; i < guessNumber; i++) {
guessedNumbers.Add(i);
inputNumber++;
}
}
else if (guessNumber > selectedNumber) {
Console.WriteLine("\nYou're guessing too high!\n");
for (int i = maxNumber; i > guessNumber; i--) {
guessedNumbers.Add(i);
inputNumber++;
}
}
} while (guessNumber != selectedNumber);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("\nCongratulations! You correctly guessed that {0} is the computer's number!", selectedNumber);
Console.ReadKey();
}
}
}
Edit: I think I'll try a way to make it so that it only adds the numbers that are higher or lower if they aren't already in there, to keep from having duplicate numbers.

The way you're trying to find the number using the computer's power isn't really efficient, why don't you just change the ranges of the possible guessing numbers based on if the previously guessed number is higher or lower than the correct number like so:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Highest number:");
int maxNumber = Convert.ToInt32(Console.ReadLine());
Random rand = new Random();
int correctNumber = rand.Next(0, maxNumber);
Console.WriteLine("Trying to guess number now..");
int guessedNumber = 0;
int lowBound = 0;
int highBound = maxNumber;
int guesses = 0;
while(guessedNumber != correctNumber)
{
guessedNumber = rand.Next(lowBound, highBound);
if(guessedNumber > correctNumber)
{
highBound /= 2;
lowBound /= 2;
}
else if(guessedNumber < correctNumber)
{
lowBound *= 2;
highBound *= 2;
}
++guesses;
}
Console.WriteLine($"Took me {guesses} guesses.");
Console.ReadKey();
}
}
This takes less than a second for 10,000,000 entries on my machine.

for (int i = 0; i < guessNumber; i++)
{
guessedNumbers.Add(i);
inputNumber++;
}
Everytime you enter these types of loops, you add 'guessnumber' items to the list, possibly millions.
Consider re-reading your code and understanding what it does.
Also, you should consider encapsulating your code to avoid making a behemoth of your main()

Another way is to use a Binary Search approach to guess the number and avoid the additional overhead caused by writing and searching for guess values.
This should run in O(log n).
int minGuess = 0;
int maxGuess = 1000000;
Random random = new Random();
int selectedNumber = random.Next(minGuess, maxGuess);
Console.WriteLine($"Selected number: {selectedNumber}");
int guess;
int count = 0;
do
{
count++;
guess = (minGuess + maxGuess) / 2;
Console.WriteLine($"Guess: {guess}");
if (selectedNumber < guess)
maxGuess = guess - 1;
else
minGuess = guess + 1;
} while (guess != selectedNumber);
Console.WriteLine($"Guessed it in {count} tries");
Console.ReadLine();

Related

Declaring a variable in a loop and using it outside?

I'm very new to c# and am trying to run this bit of code. I'm trying to make it so the question "How many miles were you able to travel in week {number}?" is repeated 4 times and this: int totalaverage = Convert.ToInt32(Console.ReadLine()); is repeated 4 times and each time added up. Then I need to use it outside the loop to make the finalaverage. Is there any way to do this?
using System;
namespace HelloWorld
{
class Program
{
static void Main()
{
Console.WriteLine("Whats your name?");
string input = Console.ReadLine();
Console.WriteLine($"Hi {input}");
Console.WriteLine("What were you hoping to hit for your average?");
int average = Convert.ToInt32(Console.ReadLine());
int number = 1;
while (number < 5)
{
Console.WriteLine($"How many miles were you able to travel in week {number}?");
int totalaverage = Convert.ToInt32(Console.ReadLine());
number = number + 1;
}
int finalaverage = totalaverage / 4;
Console.WriteLine($"{input} you have averaged {finalaverage} miles per week");
if (finalaverage >= average)
{
Console.WriteLine("Congratulations you have met your target");
}
else
{
Console.WriteLine("Sorry you have not met your target");
}
}
}
}
You need to declare your variable outside of your loop, in order to use it outside of your loop, something like this:
int number = 1;
int totalaverage = 0;
while (number < 5)
{
Console.WriteLine($"How many miles were you able to travel in week {number}?");
totalaverage = Convert.ToInt32(Console.ReadLine());
number = number + 1;
}
int finalaverage = totalaverage / 4;
Console.WriteLine($"{input} you have averaged {finalaverage} miles per week");
if (finalaverage >= average)
{
Console.WriteLine("Congratulations you have met your target");
}
else
{
Console.WriteLine("Sorry you have not met your target");
}

C# Array - identify the input if it is repeating or not

I want to create an algorithm that would identify if the user input is repeating or not. If it is repeating it will prompt the user a message if its not repeating it will continue the process.
public static class Program
{
public static void Main()
{
Console.WriteLine("input array of numbers: );
int[] array = new int[4];
for(int i=0; i<3; i++)
{
array[i] = int.Parse(Console.ReadLine());
if(array[i] == array[0])
{
Console.WriteLine("repeating inputs")
}
}
Console.WriteLine("Highest number is:" + array.MaxLenght);
Console.ReadLine();
}
}
Explanation: The user will be prompted by message "inter array of numbers:" then the user will now input the numbers. If the user inputs the same number or if the number was already inputted, the user will be prompted by a message something like "repeating inputs! Input another number". After the user input another number unique to the previously interred the program will continue and print out the largest number base on the inputs.
i'm not sure if I understood you correctly but this is what i can extrapolated from your post :
you want to get input from the user and check if it's repeating or not and then print the highest number (based on your Console.WriteLine("Highest number is:" + array.MaxLenght); )
this is how i'd approach it
Console.WriteLine("input array of numbers: ");
List<int> uniqueInts = new List<int>();
int[] array = new int[4];
for (int i = 0; i < 3; i++)
{
array[i] = int.Parse(Console.ReadLine());
if (!uniqueInts.Contains(array[i]))
uniqueInts.Add(array[i]);
}
//getting the max number
//assuming the first number is the max
int max = uniqueInts[0];
for (int i = 1; i < uniqueInts.Count; i++)
{
if (max < uniqueInts[i])
max = uniqueInts[i];
}
Console.WriteLine("The highest number is : " + max);
There are a lot of assumptions that I'm making with this answer. I'm assuming you're struggling to get the value of the item prior to the current iteration considering you have if(array[i] == array[0]).
If that's the case, then simply change array[0] to array[i-1].
Wait! Before you do that, you need to add a check to make sure you aren't on the first iteration. If you don't, you'll get an exception thrown on the first iteration, because you'll be trying to grab array[-1], which isn't valid.
for(int i=0; i<3; i++)
{
array[i] = int.Parse(Console.ReadLine());
if(i > 0)
{
if (array[i] == array[i-1])
Console.WriteLine("repeating inputs")
}
}
Make these few changes, and I think you'll get what you're after.

Dice Simulator int c#

i m facing a problem in dice simulator in c#.The function RandomGenerator generates a pair of dice until the sum of these two becomes equal to the given number(from 2 to 12) in parameter.A count variable holds the number of times the pair of dice is rolled.The problem is that when i enter an even number it correctly returns the count.But when i enter an odd number it does nothing,not even gives an error,the dash goes on blinking and blinking.The code is given below.Can anyone help me??
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static int RandomGenerator(int n)
{
Random rand1 = new Random();
Random rand2 = new Random();
int sum = rand1.Next(1,7) + rand2.Next(1,7);
int count = 1;
{
sum = rand1.Next(1,7) + rand2.Next(1,7);
count++;
}
return count;
}
static void Main(string[] args)
{
Console.WriteLine("Hello! this program a pair of dice until total on dice is equal to your given number.\n\n");
Console.WriteLine("Enter the number :");
int num = int.Parse(Console.ReadLine());
int rolls = RandomGenerator(num);
Console.WriteLine("The number of rolls are:" + rolls);
}
}
}
The problem is that you're using two Random instances. By default they're initialized with Environment.TickCount seed, which has precision about 15 milliseconds. This means that it's pretty much guaranteed that your instances of class Random get identical seed and hence generate identical values on every call to Next. The sum of two identical numbers is always even.
A proper solution would be to use a single instance of Random for both dice.
Suggested solution from me:
public static int RandomGenerator(int n)
{
Random random = new Random();
int sum = 0;
int count = 0;
do
{
sum = random.Next(1, 7) + random.Next(1, 7);
count++;
} while (sum != n);
return count;
}
Victor Efimov is right about the Random instance and I faced a similar issue once with the random generator for generating color :)
I also suggest you to perform sanity check on the user's input to make sure the values entered are always between 2 and 12. This is to avoid being caught in do-while loop when the condition sum != n will never come true.
Aren't you missing a while or for-loop?
I think you should have something like the code below in your RandomGenerator method:
static int RandomGenerator(int n)
{
Random rand1 = new Random();
int sum = rand1.Next(1,7) + rand1.Next(1,7);
int count = 1;
//while the sum variable isn't equal to your provided number, roll the dices again
while(sum != n)
{
sum = rand1.Next(1,7) + rand1.Next(1,7);
count++;
}
return count;
}

Searching sets of numbers in random numbers using binary search algorithm

My Code below is not working, not giving me any output. It was working well when I asked users to enter set of numbers and find within. But when I tried to search within random numbers, it is not working at all. Can anyone help me figure out, what did I do wrong, because program build successfully. It just won't giving the correct output.
{
class program
{
public class BinarySearch
{
public static int Search(int[] list, int x, int lower, int upper)
{
if (lower == upper)
{
int middle = (lower + upper) / 2;
if (x == list[middle])
return middle;
else if (x > list[middle] )
return Search(list, x, lower, middle - 1);
else
return Search(list, x, middle + 1, upper);
}
return 0;
}
public static void Main(String[] args)
{
int key;
int index;
int low = 0;
int high = 1000;
int[] list = new int[1000];
Random RandomNumber = new Random();
for (int i = 0; i < 1000; i++)
{
list[i] = RandomNumber.Next(1, 1000);
}
foreach (int j in list)
{
Console.WriteLine("{0}", j);
}
Console.WriteLine("...................................................\n");
Console.WriteLine("\nEnter the number to be searched in the list.");
key = Convert.ToInt32(Console.ReadLine());
index = Search(list, key, low, high);
Console.WriteLine("...................................................\n");
if (index == 0)
Console.WriteLine("Key {0} not found", key);
else
Console.WriteLine("Key {0} found at index {1}", key, index);
}
}
}
}
You're not sorting the "list".
Binary search requires the list to be sorted by the same rules you're using < and > inside the binary search algorithm, otherwise it will not work.
So sort the numbers in the array and the binary search should work much better.
Note, I think you've reversed the partition statements inside the numbers. If x > list[middle], then you need to search the upper part, not the lower part. This alone will not explain or fix your problem though, first you need to sort the numbers.
Finally, know that 0 is a valid index into the array, which means that you won't be able to distinguish between "not found" and "found at index 0" with your code.
My advice: Find an existing implementation of binary search and copy that, or at least use it as a source for inspiration.

sort without Array.Sort

I just barely understood how to use if statement and "for loop." In addition right now I have to do this
Sort the integer elements within the array from lowest (element 0) to highest (element 4). Do not use the preexisting Array.Sort method; code your own.
This is a homework problem and I don't even know where to start. Can somebody walk me through this?
class Program
{
static void Main(string[] args)
{
int i;
double power = 0, sum = 0;
int[] mArray = new int[5];
Console.WriteLine("Please Enter Number Between 10 and 50 \nMake sure all of your Number entered correctly \notherwise you will need to enter everything again ");
for (i = 0; i < mArray.Length; i++)
{
Console.WriteLine("Please enter your Number.");
mArray[i] = Convert.ToInt32(Console.ReadLine());
if (mArray[i] >= 50 || mArray[i] <= 10)
{
i--;
Console.WriteLine("Please enter numbers only between 10 and 50.");
}
}
for (i = 0; i < mArray.Length; i++)
{
sum = sum + (mArray[i]);
}
double mean = sum / mArray.Length;
for (i = 0; i < mArray.Length; i++)
{
power += Math.Pow((mArray[i] - mean), 2);
}
double rMean = power / (mArray.Length - 1);
Console.WriteLine("Mean {0}", mean);
Console.WriteLine("Variance {0}", rMean);
Console.WriteLine("Here is sorted numbers");
Console.ReadKey();
}
}
There are many sorting algorithms you can try like Insertion Sort
Selection Sort,
Bubble Sort,
Shell Sort,
Merge Sort,
Heap Sort,
Quick Sort,
And many Others.

Categories

Resources