I'm fairly new to C# and I made a simple program simmulating lotto draws. It takes first (random) numbers and calculates how many draws it takes to win. It's a polish lotto, so there are 6 numbers to match.
Everything works fine, when program is run in simple for loop. But there is a problem, when I use Parallel For or whatever other multitasking or multithreding option.
First the code:
class Program
{
public static int howMany = 100;
static void Main(string[] args)
{
Six my;
Six computers;
long sum = 0;
double avg = 0;
int min = 1000000000;
int max = 0;
for (int i = 0; i < howMany; i++)
{
my = new Six();
Console.WriteLine((i + 1).ToString() + " My: " + my.ToString());
int counter = 0;
do
{
computers = new Six();
counter++;
} while (!my.Equals(computers));
Console.WriteLine((i + 1).ToString() + " Computers: " + computers.ToString());
Console.WriteLine(counter.ToString("After: ### ### ###") + "\n");
if (counter < min)
min = counter;
if (counter > max)
max = counter;
sum += counter;
}
avg = sum / howMany;
Console.WriteLine("Average: " + avg);
Console.WriteLine("Sum: " + sum);
Console.WriteLine("Min: " + min);
Console.WriteLine("Max: " + max);
Console.Read();
}
}
class Six : IEquatable<Six>
{
internal byte first;
internal byte second;
internal byte third;
internal byte fourth;
internal byte fifth;
internal byte sixth;
private static Random r = new Random();
public Six()
{
GenerateRandomNumbers();
}
public bool Equals(Six other)
{
if (this.first == other.first
&& this.second == other.second
&& this.third == other.third
&& this.fourth == other.fourth
&& this.fifth == other.fifth
&& this.sixth == other.sixth)
return true;
else
return false;
}
private void GenerateRandomNumbers()
{
byte[] numbers = new byte[6];
byte k = 0;
for (int i = 0; i < 6; i++)
{
do
{
k = (byte)(r.Next(49) + 1);
}while (numbers.Contains(k));
numbers[i] = k;
k = 0;
}
Array.Sort(numbers);
this.first = numbers[0];
this.second = numbers[1];
this.third = numbers[2];
this.fourth = numbers[3];
this.fifth = numbers[4];
this.sixth = numbers[5];
}
public override string ToString()
{
return this.first + ", " + this.second + ", " + this.third + ", " + this.fourth + ", " + this.fifth + ", " + this.sixth;
}
}
And when I try to make it Parallel.For:
long sum = 0;
double avg = 0;
int min = 1000000000;
int max = 0;
Parallel.For(0, howMany, (i) =>
{
Six my = new Six();
Six computers;
Console.WriteLine((i + 1).ToString() + " My: " + my.ToString());
int counter = 0;
do
{
computers = new Six();
// Checking when it's getting stuck
if (counter % 100 == 0)
Console.WriteLine(counter);
counter++;
} while (!my.Equals(computers));
Console.WriteLine((i + 1).ToString() + " Computers: " + computers.ToString());
Console.WriteLine(counter.ToString("After: ### ### ###") + "\n");
// It never get to this point, so there is no problem with "global" veriables
if (counter < min)
min = counter;
if (counter > max)
max = counter;
sum += counter;
});
Program gets stuck at some point. Counters get to ~3,000-40,000 and refuses to go further.
What I tried:
Making class a struct
Collecting Garbage every ~1000 iterations
Using ThreadPool
Using Task.Run
Making random class Program member only (tired to make Six class "lighter")
But I got nothing.
I know that this might be a very simple thing for some of you, but man got to learn somehow ;) I even bought a book about async programming to find out why doesn't it work, but couldn't figure it out.
Random isn't thread safe...
Wait for your code to stop writing new lines in the parallel version and the pause. This stops all threads. You'll notice that all your parallel threads are in the while loop.
The numbers array's are all 1,0,0,0,0,0 and r.Next only returns 1. which the byte array always contains. So, you broke Random
To fix this you'll need to make r thread safe, either by locking r every time you access r.Next or changing the static declaration to
private static readonly ThreadLocal<Random> r
= new ThreadLocal<Random>(() => new Random());
and the Next call becomes
k = (byte)(r.Value.Next(49) + 1);
This will create a new static Random instance per thread.
As you noted, creating lots of Random's at the same time result the in same sequence of numbers being produced, to get around this add a seed class
static class RGen
{
private static Random seedGen = new Random();
public static Random GetRGenerator()
{
lock (seedGen)
{
return new Random(seedGen.Next());
}
}
}
and change the declaration to
private static readonly ThreadLocal<Random> r
= new ThreadLocal<Random>(() => RGen.GetRGenerator());
This will ensure each new random instance has a different seed value.
I found a solution based on what James Barrass wrote:
public static readonly ThreadLocal<Random> r = new ThreadLocal<Random>(() => new Random(Thread.CurrentThread.ManagedThreadId + DateTime.Now.Miliseconds));
That made program running well :)
Related
Beginner to programming & have been assigned a heads or tails coin flip project.
I've figured out how to make it randomly generate the number of requested flips and print out the answers. However, I'm supposed to have it add up how many times the user's input came up into the correctCount variable and I can't find anywhere how to do it. I've tried searching on here and different sites from searching throughout Google. I assume I need to take their string input and convert it somehow, like if result == string, then correctCount + 1 basically, but can't figure out how to make that happen since you can't do that with int & string. Any info or hints would be very helpful - thank you!
class Coin
{
static void Main(string[] args)
// UserInput
{
Console.Write("Guess which will have more: heads or tails?");
string headsOrTailsGuess = Console.ReadLine() + "\n";
Console.Write("\n" + "How many times shall we flip the coin? ");
int numberOfFlips = int.Parse(Console.ReadLine() + "\n");
// Declare variables
int correctCount = 0;
int heads = 0;
int tails = 1;
Random rand = new Random();
for (int i = 0; i < numberOfFlips; i++)
{
int result = rand.Next(0, 2);
if (result == 0)
{
Console.WriteLine("Heads!");
}
else
{
Console.WriteLine("Tails!");
}
}
Console.WriteLine("Your guess, " + headsOrTailsGuess + "came up " + correctCount + " time(s).");```
As PMF mentioned, you have to not only receive user choice, but also analyse it.
A simple comparison should be more that enough here, although you might want to add some validation to user input.
static void Main(string[] args)
// UserInput
{
int choice; //variable for parsed user choice
Console.Write("Guess which will have more: heads or tails?");
string headsOrTailsGuess = Console.ReadLine() + "\n";
if(headsOrTailsGuess.ToLower().Trim() == "heads"){ //here you look if its heads
choice = 0;
}
else{ //we can write additional if here to avoid other options from counting as tails
choice = 1;
}
Console.Write("\n" + "How many times shall we flip the coin? ");
int numberOfFlips = int.Parse(Console.ReadLine() + "\n");
// Declare variables
int correctCount = 0;
int heads = 0;
int tails = 1;
Random rand = new Random();
for (int i = 0; i < numberOfFlips; i++)
{
int result = rand.Next(0, 2);
if (result == 0)
{
Console.WriteLine("Heads!");
}
else
{
Console.WriteLine("Tails!");
}
if(result == choice){ //comparing result to parsed choice and incrementing the counter
correctCount++;
}
}
Console.WriteLine("Your guess, " + headsOrTailsGuess + "came up " + correctCount + " time(s).");
}
Here's another way to do it using Linq.
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
// UserInput
{
Console.Write("Guess which will have more: heads or tails?");
string headsOrTailsGuess = Console.ReadLine();
Console.Write("\n" + "How many times shall we flip the coin? ");
int numberOfFlips = int.Parse(Console.ReadLine() + "\n");
// Declare variables
List<string> resultList = new List<string>();
Random rand = new Random();
for (int i = 0; i < numberOfFlips; i++)
{
int result = rand.Next(0, 2);
resultList.Add(result == 1? "Heads!" : "Tails!");
}
var guessCount = resultList.Where(a=>a.ToUpper().Contains(headsOrTailsGuess.ToUpper())).Count();
resultList.ForEach( a=> Console.WriteLine(a));
Console.WriteLine("Your guess, " + headsOrTailsGuess + " came up " + guessCount + " time(s).");
Console.WriteLine(headsOrTailsGuess);
}
}
}
using System;
Console.WriteLine("Guess which will have more: heads or tails?");
var headsChosen = false;
var input = string.Empty;
do
{
input = Console.ReadLine();
headsChosen = input.ToLower() == "heads";
} while (input.ToLower() != "heads" && input.ToLower() != "tails");
Console.WriteLine("How many times shall we flip the coin?");
var flips = 0;
do
{
} while (!int.TryParse(Console.ReadLine(), out flips));
var rnd = new Random();
var heads = 0;
var tails = 0;
for (int i = 0; i < flips; i++)
{
if (rnd.Next(0, 2) == 0)
{
Console.WriteLine("Heads!");
heads++;
}
else
{
Console.WriteLine("Tails!");
tails++;
}
}
var userGuessed = (headsChosen && heads > tails) || (!headsChosen && tails > heads);
Console.WriteLine($"You {(userGuessed ? "guess" : "loose")}!");
Working on an assignment where i need to accomplish the following: On a survey a question asks the surveyed person to rate something from 1-5 (whole number). The end user of your program iinputs the answers for that question on an unknown number of surveys. Write a program that allows this and outputs the percent response for each value (1, 2, 3, 4, and 5).
I did a previous Console app with a loop to collect an average and I am unsure how to collect a percent response on 5 different possible inputs.
Below is my previous code.
namespace WhileLoopsMean
public class MeanProgram
static void Main(string[] args)
{
long test, sum, loop, count;
double avg;
Console.Write("How many tests? ");
count = long.Parse(Console.ReadLine());
sum = 0;
loop = 1;
while (loop <= count)
{
Console.Write("enter score " + loop + " : ");
test = long.Parse(Console.ReadLine());
sum = sum + test;
loop = loop + 1;
}
avg = sum;
avg = avg / count;
Console.WriteLine("\naverage : " + avg);
Console.WriteLine("\n\nenter a score of -100 to end\n");
count = 1;
sum = 0;
Console.Write("enter score " + count + " : ");
test = long.Parse(Console.ReadLine());
sum = sum + test;
while (test != -100)
{
count = count + 1;
Console.Write("enter score " + count + " : ");
test = long.Parse(Console.ReadLine());
if (test != -100)
{
sum = sum + test;
}
else { }
}
count = count - 1;
avg = sum;
avg = avg / count;
Console.WriteLine("\naverage : " + avg);
Console.ReadKey();
class Program {
static void Main(string[] args) {
string input = "";
List<List<int>> answers = new List<List<int>>();
int questionsCount = ReadInt32("The number of questions: ");
for (int i = 0; i < questionsCount; i++) {
answers.Add(new List<int>());
}
while (input == "" || input == "y") {
for (int i = 0; i < answers.Count; i++) {
List<int> a = answers[i];
a.Add(ReadInt32($"Question [{i}]: "));
}
input = Read("Continue (y/n)? ").ToLower();
}
WriteLine("End of input!");
for (int i = 0; i < answers.Count; i++) {
List<int> a = answers[i];
Write($"Average for question[{i}]: {a.Average()}\n");
}
ReadKey();
}
static string Read (string a) {
Write(a);
return ReadLine();
}
static int ReadInt32 (string a = "") {
Write(a);
return ToInt32(ReadLine());
}
}
Try this out. You can customize the questions. And note that to use Write() and WriteLine(), you should add
using static System.Console;
at the top, in the references of the project.
I am trying to optimize a search algorithm I am using to find marked Symbols in TwinCat 3 through the ADS Interface. The question is not TwinCat related so don't get scared off yet.
The problems:
Symbols are not loaded at once. I think the TwinCatAds library use lazy loading.
Symbols have treelike structure of non-binary not balanced tree.
The solution:
You can open more than one stream to ADS. And handle the the streams in multiple threads.
The question is, I divide the first level of symbols by the number of the processor cores. So Because the tree is unbalanced some of the Threads finish faster than the others. Because of this I need a nicer solution how to divide the work between the threads.
PS: I can't use the Parallel.ForEach(). Because of the streams it results in the same or greater time amount as the single thread solution.
My test code looks looks this, it just counts all Symbols of a huge Project.
using TwinCAT.Ads;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Collections;
namespace MultipleStreamsTest
{
class Program
{
static int numberOfThreads = Environment.ProcessorCount;
static TcAdsClient client;
static TcAdsSymbolInfoLoader symbolLoader;
static TcAdsSymbolInfoCollection[] collection = new TcAdsSymbolInfoCollection[numberOfThreads];
static int[] portionResult = new int[numberOfThreads];
static int[] portionStart = new int[numberOfThreads];
static int[] portionStop = new int[numberOfThreads];
static void Connect()
{
client = new TcAdsClient();
client.Connect(851);
Console.WriteLine("Conected ");
}
static void Main(string[] args)
{
Connect();
symbolLoader = client.CreateSymbolInfoLoader();
CountAllOneThread();
CountWithMultipleThreads();
Console.ReadKey();
}
static public void CountAllOneThread()
{
Stopwatch stopwatch = new Stopwatch();
int index = 0;
stopwatch.Start();
Console.WriteLine("Counting with one thread...");
//Count all symbols
foreach (TcAdsSymbolInfo symbol in symbolLoader)
{
index++;
}
stopwatch.Stop();
//Output
Console.WriteLine("Counted with one thred " + index + " symbols in " + stopwatch.Elapsed);
}
static public int countRecursive(TcAdsSymbolInfo symbol)
{
int i = 0;
TcAdsSymbolInfo subSymbol = symbol.FirstSubSymbol;
while (subSymbol != null)
{
i = i + countRecursive(subSymbol);
subSymbol = subSymbol.NextSymbol;
i++;
}
return i;
}
static public void countRecursiveMultiThread(object portionNum)
{
int portionNumAsInt = (int)portionNum;
for (int i = portionStart[portionNumAsInt]; i <= portionStop[portionNumAsInt]; i++)
{
portionResult[portionNumAsInt] += countRecursive(collection[portionNumAsInt][i]);//Collection Teil
}
}
static public void CountWithMultipleThreads()
{
Stopwatch stopwatch = new Stopwatch();
int sum = 0;
stopwatch.Start();
Console.WriteLine("Counting with multiple thread...");
for (int i = 0; i < numberOfThreads; i++)
{
collection[i] = symbolLoader.GetSymbols(true);
}
int size = (int)(collection[0].Count / numberOfThreads);
int rest = collection[0].Count % numberOfThreads;
int m = 0;
for (; m < numberOfThreads; m++)
{
portionStart[m] = m * size;
portionStop[m] = portionStart[m] + size - 1;
}
portionStop[m - 1] += rest;
Thread[] threads = new Thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++)
{
threads[i] = new Thread(countRecursiveMultiThread);
threads[i].Start(i);
Console.WriteLine("Thread #" + threads[i].ManagedThreadId + " started, fieldIndex: " + i);
}
//Check when threads finishing:
int threadsFinished = 0;
bool[] threadFinished = new bool[numberOfThreads];
int x = 0;
while (true)
{
if (threads[x].Join(10) && !threadFinished[x] )
{
Console.WriteLine("Thread #" + threads[x].ManagedThreadId + " finished ~ at: " + stopwatch.Elapsed);
threadsFinished++;
threadFinished[x] = true;
}
x++;
x = x % numberOfThreads;
if (threadsFinished == numberOfThreads) break;
Thread.Sleep(50);
}
foreach (int n in portionResult)
{
sum += n;
}
sum += collection[0].Count;
stopwatch.Stop();
//Output
Console.WriteLine("Counted with multiple threds in Collection " + sum + " symbols " + " in " + stopwatch.Elapsed);
for (int i = 0; i < numberOfThreads; i++)
{
Console.WriteLine("#" + i + ": " + portionResult[i]);
}
}
}
}
The console output:
If you trying to run the Code use TwinCat.Ads Version 4.0.17.0(that i am using). They broke something in the new version that is available with NuGet.
Make a thread pool and keep track of threads running and idling status. At each branch check if there is idling threads, if there is assign thread to sub branch.
I have a problem I need to solve using C#. There is an array of decimal numbers (representing quantities of an item received by a warehouse at different times). This array is already sorted in the order in which the quantities were received. I need to be able to find the earliest combination of quantities that sum up to a specified total quantity.
So for example, say I have some quantities that came in chronologically as follows [13, 6, 9, 8, 23, 18, 4] and say my total quantity to match is 23. Then I should be able to get [13, 6, 4] as the matching subset although [6, 9, 8] and [23] are also matching but not the earliest.
What would be the best approach/algorithm for this?
I have so far come up with a rather naive approach using recursion.
public class MatchSubset
{
private decimal[] qty = null;
private decimal matchSum = 0;
public int operations = 0;
public int[] matchedIndices = null;
public int matchCount = 0;
private bool SumUp(int i, int n, decimal sum)
{
operations++;
matchedIndices[matchCount++] = i;
sum += qty[i];
if (sum == matchSum)
return true;
if (i >= n - 1)
{
matchCount--;
return false;
}
if (SumUp(i + 1, n, sum))
return true;
sum -= qty[i];
matchCount--;
return SumUp(i + 1, n, sum);
}
public bool Match(decimal[] qty, decimal matchSum)
{
this.qty = qty;
this.matchSum = matchSum;
matchCount = 0;
matchedIndices = new int[qty.Count()];
return SumUp(0, qty.Count(), 0);
}
}
static void Main(string[] args)
{
var match = new MatchSubset();
int maxQtys = 20;
Random rand = new Random(DateTime.Now.Millisecond);
decimal[] qty = new decimal[maxQtys];
for (int i = 0; i < maxQtys - 2; i++)
qty[i] = rand.Next(1, 500);
qty[maxQtys - 2] = 99910;
qty[maxQtys - 1] = 77910;
DateTime t1 = DateTime.Now;
if (match.Match(qty, 177820))
{
Console.WriteLine(DateTime.Now.Subtract(t1).TotalMilliseconds);
Console.WriteLine("Operations: " + match.operations);
for (int i = 0; i < match.matchCount; i++)
{
Console.WriteLine(match.matchedIndices[i]);
}
}
}
The matching subset can be as short as one element and as long as the original set (containing all elements). But to test the worst case scenario, in my test program I am using an arbitrarily long set of which only the last two match the given number.
I see that with 20 numbers in the set, it calls the recursive function over a million times with a max recursion depth of 20. If I run into a set of 30 or more numbers in production, I am fearing it will consume a very long time.
Is there a way to further optimize this? Also, looking at the downvotes, is this the wrong place for such questions?
I was unable to end up with something revolutionary, so the presented solution is just a different implementation of the same brute force algorithm, with 2 optimizations. The first optimization is using iterative implementation rather than recursive. I don't think it is significant because you are more likely to end up with out of time rather than out of stack space, but still it's a good one in general and not hard to implement. The most significant is the second one. The idea is, during the "forward" step, anytime the current sum becomes greater than the target sum, to be able to skip checking the next items that have greater or equal value to the current item. Usually that's accomplished by first sorting the input set, which is not applicable in your case. However, while thinking how to overcome that limitation, I realized that all I need is to have for each item the index of the first next item which value is less than the item value, so I can just jump to that index until I hit the end.
Now, although in the worst case both implementations perform the same way, i.e. may not end in a reasonable time, in many practical scenarios the optimized variant is able to produce result very quickly while the original still doesn't end in a reasonable time. You can check the difference by playing with maxQtys and maxQty parameters.
Here is the implementation described, with test code:
using System;
using System.Diagnostics;
using System.Linq;
namespace Tests
{
class Program
{
private static void Match(decimal[] inputQty, decimal matchSum, out int[] matchedIndices, out int matchCount, out int operations)
{
matchedIndices = new int[inputQty.Length];
matchCount = 0;
operations = 0;
var nextLessQtyPos = new int[inputQty.Length];
for (int i = inputQty.Length - 1; i >= 0; i--)
{
var currentQty = inputQty[i];
int nextPos = i + 1;
while (nextPos < inputQty.Length)
{
var nextQty = inputQty[nextPos];
int compare = nextQty.CompareTo(currentQty);
if (compare < 0) break;
nextPos = nextLessQtyPos[nextPos];
if (compare == 0) break;
}
nextLessQtyPos[i] = nextPos;
}
decimal currentSum = 0;
for (int nextPos = 0; ;)
{
if (nextPos < inputQty.Length)
{
// Forward
operations++;
var nextSum = currentSum + inputQty[nextPos];
int compare = nextSum.CompareTo(matchSum);
if (compare < 0)
{
matchedIndices[matchCount++] = nextPos;
currentSum = nextSum;
nextPos++;
}
else if (compare > 0)
{
nextPos = nextLessQtyPos[nextPos];
}
else
{
// Found
matchedIndices[matchCount++] = nextPos;
break;
}
}
else
{
// Backward
if (matchCount == 0) break;
var lastPos = matchedIndices[--matchCount];
currentSum -= inputQty[lastPos];
nextPos = lastPos + 1;
}
}
}
public class MatchSubset
{
private decimal[] qty = null;
private decimal matchSum = 0;
public int operations = 0;
public int[] matchedIndices = null;
public int matchCount = 0;
private bool SumUp(int i, int n, decimal sum)
{
operations++;
matchedIndices[matchCount++] = i;
sum += qty[i];
if (sum == matchSum)
return true;
if (i >= n - 1)
{
matchCount--;
return false;
}
if (SumUp(i + 1, n, sum))
return true;
sum -= qty[i];
matchCount--;
return SumUp(i + 1, n, sum);
}
public bool Match(decimal[] qty, decimal matchSum)
{
this.qty = qty;
this.matchSum = matchSum;
matchCount = 0;
matchedIndices = new int[qty.Count()];
return SumUp(0, qty.Count(), 0);
}
}
static void Main(string[] args)
{
int maxQtys = 3000;
decimal matchQty = 177820;
var qty = new decimal[maxQtys];
int maxQty = (int)(0.5m * matchQty);
var random = new Random();
for (int i = 0; i < maxQtys - 2; i++)
qty[i] = random.Next(1, maxQty);
qty[maxQtys - 2] = 99910;
qty[maxQtys - 1] = 77910;
Console.WriteLine("Source: {" + string.Join(", ", qty.Select(v => v.ToString())) + "}");
Console.WriteLine("Target: {" + matchQty + "}");
int[] matchedIndices;
int matchCount;
int operations;
var sw = new Stopwatch();
Console.Write("#1 processing...");
sw.Restart();
Match(qty, matchQty, out matchedIndices, out matchCount, out operations);
sw.Stop();
ShowResult(matchedIndices, matchCount, operations, sw.Elapsed);
Console.Write("#2 processing...");
var match = new MatchSubset();
sw.Restart();
match.Match(qty, matchQty);
sw.Stop();
ShowResult(match.matchedIndices, match.matchCount, match.operations, sw.Elapsed);
Console.Write("Done.");
Console.ReadLine();
}
static void ShowResult(int[] matchedIndices, int matchCount, int operations, TimeSpan time)
{
Console.WriteLine();
Console.WriteLine("Time: " + time);
Console.WriteLine("Operations: " + operations);
if (matchCount == 0)
Console.WriteLine("No Match.");
else
Console.WriteLine("Match: {" + string.Join(", ", Enumerable.Range(0, matchCount).Select(i => matchedIndices[i].ToString())) + "}");
}
}
}
It takes the total number of rolls and divides them by 10. For example, if it took 56 rolls so my average is 5.6.
Random numGen = new Random ();
int numOfAttempt = 0;
int Attempt = 0;
int avrBefore = 0;
int avrAfter = 0;
for (int i = 1; i <= 10; i++)
do {
Attempt = numGen.Next (1, 7);
Console.WriteLine (Attempt);
numOfAttempt++;
avrBefore = numOfAttempt;
avrAfter = avrBefore / 10;
} while (Attempt != 6);
Console.WriteLine ("He tried " + numOfAttempt + " times to roll a six.");
Console.WriteLine ("The average number of times it took to get a six was " + avrAfter);
Console.ReadKey ();
maybe you need to reset the vars inside the for loop, before the while:
for (int i = 1; i <= 10; i++){
int numOfAttempt = 0;
int Attempt = 0;
int avrBefore = 0;
int avrAfter = 0;
do {//your code
You are diving by ten at the wrong time.
You are dividing by ten even when you haven't done ten iterations.
This code below instead shows the correct average at each iteration.
void Main()
{
Random numGen = new Random ();
int totalAttempts = 0;
for (int i = 1; i <= 10; i++)
{
int attempts = 0;
int attempt = 0;
do {
attempt = numGen.Next (1, 7);
attempts++;
} while (attempt != 6);
totalAttempts+=attempts;
Console.WriteLine ("He tried " + attempts + " times to roll a six.");
Console.WriteLine ("The average number of times it took to get a six was " + (double)totalAttempts / i);
}
}
So you want to know how many times it took to get a six. This is quite simple. You just have to save how many times you rolled the dices and how many times you got a six.
Random numGen = new Random ();
int attempt = 0;
int numOfAttempt = 0;
int numberOfSixes = 0;
int i;
for (i = 0; i < 10; i++) {
do {
attempt = numGen.Next (1, 7);
Console.WriteLine (Attempt);
numOfAttempt++;
} while (Attempt != 6);
numberOfSixes++;
}
Console.WriteLine ("He tried " + numOfAttempt + " times to roll a six.");
Console.WriteLine ("The average number of times it took to get a six was " + (numberOfAttempt/numberOfSixes));
Console.ReadKey ();
I hope you understand my approach.
I would appreciate it if you could elaborate your thought process behind avrBefore,avrAfter and divide by 10. I didn't get that.
You can shorten down the code a lot and get it correct:
Random numGen = new Random();
int numOfAttempt = 0;
for (int i = 0; i < 10; i++)
{
int attempt = 0;
while (attempt != 6)
{
attempt = numGen.Next(1, 7);
Console.WriteLine (attempt );
numOfAttempt++;
}
}
Console.WriteLine("He tried " + numOfAttempt + " times to roll a six.");
Console.WriteLine("The average number of times it took to get a six was " + numOfAttempt / 10.0);
Console.ReadKey();