breaks while loop when all die rolls the same number - c#

using System;
using System.Collections.Generic;
namespace AnyDice
{
class Program
{
static void Main(string[] args)
{
int diceSides;
int rollDie;
int count = 0;
bool keepRolling = true;
List<int> num = new List<int>();
Random random = new Random();
Console.Write("Write the number of sides of your die: ");
diceSides = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Type the numbers of the die");
for (int i = 0; i < diceSides; i++)
{
int rank = 1 + i;
Console.Write(rank + "~~> ");
num.Add(Convert.ToInt32(Console.ReadLine()));
}
num.Sort();
Console.WriteLine("\nHere's the die and its contents");
for (int i = 0; i < num.Count; i++)
{
Console.Write("[");
Console.Write(num[i]);
Console.Write("]");
}
Console.WriteLine("\nHow many times do you want to roll at once");
rollDie = Convert.ToInt32(Console.ReadLine());
while (keepRolling)
{
for (int i = 0; i < rollDie; i++)
{
Console.Write("[");
Console.Write(num[random.Next(num.Count)]);
Console.Write("]");
count++;
}
Console.ReadLine();
}
Console.WriteLine("It took you " + count + " attempts");
Console.ReadLine();
}
}
}
For example if (4,4,4,4) is rolled or (2,2) in any "n" number of column the while loop breaks.
I thought of storing each die rolled value in another arraylist and comparing each value in it. If its all equal then it breaks.. but I have no clue on how to implement it.

We have Linq. It lives in the System.Linq namespace and this might help you.
I'll should two ways of checking if all die are the same:
int first = dies.First();
if (dies.All(i => i == first))
{
// break if all are equals to the first die
}
Or using Distinct we can filter out any copies.
if (dies.Distinct().Count() == 1)
{
// if we only have unique items and the count is 1 every die is the same
}

I am not 100% sure I understand your requirement, but in any case, you should write a separate function that returns a flag indicating whether the array is in a state that should trigger a break.
bool KeepRolling(int[] num)
{
for (int i=0; i<num.Length; i++)
{
if (num[i] >= i) return false;
}
return true;
}
Then just call it from within your loop:
keepRolling = KeepRolling(num);

while (keepRolling)
{
rolls.Clear();
for (int i = 0; i < rollDie; i++)
{
var firstRoll = num[random.Next(num.Count)];
rolls.Add(firstRoll);
Console.Write(firstRoll + " ");
count++;
}
if (rolls.Distinct().Count() == 1)
{
Console.WriteLine("It took you " + count + " attempts");
keepRolling = false;
break;
}
Console.ReadLine();
}

Related

return and while in function

This function accepting input and telling the user whether the input is number or not a number.
static string isnum()
{
Console.WriteLine("Write a number please");
string a = Console.ReadLine();
string nums = "123456789";
int cnt = 0;
for (int i = 0; i < a.Length; i++)
{
for (int j = 0; j < nums.Length; j++)
{
if (a[i] == nums[j])
{
cnt++;
break;
}
}
}
if (cnt == a.Length)
{
Console.WriteLine(a + " is a number");
return a;
}
else
{
Console.WriteLine(a + " is not a number");
return "";
}
}
isnum();
I would like this function to repeat herself if the input is not a number, till the input will be a number, and then to stop.
This function working now, but she's working only one time.
When I'm trying to add a while block to the function to make her run again and again till the input is number I'm getting the "not all code paths return a value" error.
is it because a "return" statement ends a function, and therefore prevent her to run again?
how can I solve that?
Thank you very much!
You can fix this with creating a loop arround it and do not return when it's not a number.
static string isnum()
{
// just loop forever.
while (true)
{
Console.WriteLine("Write a number please");
string a = Console.ReadLine();
string nums = "123456789";
int cnt = 0;
for (int i = 0; i < a.Length; i++)
{
for (int j = 0; j < nums.Length; j++)
{
if (a[i] == nums[j])
{
cnt++;
break;
}
}
}
if (cnt == a.Length)
{
Console.WriteLine(a + " is a number");
return a;
}
else
{
Console.WriteLine(a + " is not a number");
// don't return here
}
}
}
In this case the best approach is to use do while because you want your code to at least run once.
you have one problem in your code which is returning when variable is not a number. see these modifications:
static string isnum()
{
do{
Console.WriteLine("Write a number please");
string a = Console.ReadLine();
string nums = "123456789";
int cnt = 0;
for (int i = 0; i < a.Length; i++)
{
for (int j = 0; j < nums.Length; j++)
{
if (a[i] == nums[j])
{
cnt++;
break;
}
}
}
if (cnt == a.Length)
{
Console.WriteLine(a + " is a number");
return a;
}
else
{
Console.WriteLine(a + " is not a number");
}
}while(true);
}
Call it in a while loop, and loop until the result is a number:
string result = "";
while (result == "")
{
result = isnum();
}
Console.WriteLine("result is a number: " + result);
Instead of looping you can try querying the a string with a help of Linq:
using System.Linq;
...
static string isnum() {
// Keep asking user until he/she provides a number
while (true) {
Console.WriteLine("Write a number please");
string a = Console.ReadLine();
// Number is
// 1. Has at least one character
// 2. All characters of number are digits
if (a.Length > 0 && a.All(c => c >= '0' && c <= '9')) {
Console.WriteLine($"{a} is a number");
// we have a proper number, let's return int
return a;
}
Console.WriteLine($"{a} is not a number");
}
}

C# - Keeping total number of correct guesses inside a variable

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")}!");

Splitting Array into new arrays and printing them with spaces

This program will sort numbers and depending if they are greater than or less than 100, put them into their own array.
The problem I have is printing this array. I would like the last number on the line, to not be followed by a space. I have tried many many times to get this to work now and figured I'd ask here.
I know of Console.Write("\b"); but I prefer to find a way of editing the loop so I don't have to do this. Here is the code:
using System;
using System.Linq;
class SplitArray
{
public static void Main(string[] args)
{
int[] myArray = GetNumbersFromConsole();
int[] smallNumbers = new int[myArray.Length];
int[] bigNumbers = new int[myArray.Length];
int bigIndex = 0;
int littleIndex = 0;
for (int i = 0; i < myArray.Length; i++)
{
if(myArray[i] > 100)
{
bigNumbers[bigIndex++] = myArray[i];
}
else if(myArray[i] < 100)
{
smallNumbers[littleIndex++] = myArray[i];
}
}
Console.Write("Big: ");
for (int i = 1; i < bigIndex; ++i)
{
Console.Write(bigNumbers[i]);
Console.Write(" ");
}
Console.WriteLine();
//Console.WriteLine($"{bigNumbers[0]}");
Console.Write("Little: ");
for (int i = 0; i < littleIndex; i++)
{
Console.Write($"{smallNumbers[i]}");
Console.Write(" ");
}
Console.ReadLine();
}
static int[] GetNumbersFromConsole()
{
int count = int.Parse(Console.ReadLine());
int[] result = new int[count];
for (int i = 0; i < count; ++i)
{
result[i] = int.Parse(Console.ReadLine());
}
return result;
}
}
You could just capture your Console.Write(" "); in an if statement.
if(i != littleIndex - 1)
{
Console.Write(" ");
}
littleIndex - 1 is the last time your loop executes, so this will just prevent it from adding the trailing white space. Just do the same for your big numbers as you're printing them out.
There is a builtin utility string.Join
var str = string.Join(" ",bigNumbers);
Console.WriteLine("Big: " + str);
I was playing around some more and just thought I'd try posting the first object in the array before running this loop (also changed loop so the first item didn't get printed twice).
Thank you everyone - I solved it! :)
using System;
using System.Linq;
namespace Arrays
{
class SplitArray
{
public static void Main(string[] args)
{
int[] myArray = GetNumbersFromConsole();
int[] smallNumbers = new int[myArray.Length];
int[] bigNumbers = new int[myArray.Length];
int bigIndex = 0;
int littleIndex = 0;
for (int i = 0; i < myArray.Length; i++)
{
if(myArray[i] > 100)
{
bigNumbers[bigIndex++] = myArray[i];
}
else if(myArray[i] < 100)
{
smallNumbers[littleIndex++] = myArray[i];
}
}
Console.Write("Big: ");
Console.Write($"{bigNumbers[0]} ");
for (int i = 1; i < bigIndex; i++)
{
Console.Write(bigNumbers[i]);
if (i != bigIndex - 1)
{
Console.Write(" ");
}
}
Console.WriteLine();
Console.Write("Little: ");
Console.Write($"{smallNumbers[0]} ");
for (int i = 1; i < littleIndex; i++)
{
Console.Write($"{smallNumbers[i]}");
if (i != littleIndex - 1)
{
Console.Write(" ");
}
}
Console.ReadLine();
}
static int[] GetNumbersFromConsole()
{
int count = int.Parse(Console.ReadLine());
int[] result = new int[count];
for (int i = 0; i < count; ++i)
{
result[i] = int.Parse(Console.ReadLine());
}
return result;
}
}
}

Array Duplicate Elimination with c#?

I have a program here that need some improvements. This Program inputs 5 elements in an Array and Removes if any duplicates. It works but the problem is that it sets every duplicate to zero. I don't want to display zero. I want it completely destroyed and eliminated. I don't want that duplicate element to appear. This is what I have so Far! Could Use some help. Thank You.
// Gurpreet Singh
// Duplicate Program
using System;
class duplicate
{
static void Main()
{
const int Array_Size = 5;
int [] number = new int [Array_Size];
int i;
for ( i = 0; i < Array_Size; i++)
{
Console.Write("Element " + i + ": ");
number[i] = Int32.Parse(Console.ReadLine());
if (number[i] < 9 || number[i] > 101)
{
Console.WriteLine("Enter Number between 10 - 100");
number[i] = Int32.Parse(Console.ReadLine());
}
}
for (i = 0; i < Array_Size; i++)
{
for (int j = 0; j < Array_Size; j++)
{
if (i != j)
{
if (number[j] == number[i])
number[j] = 0;
}
}
}
Console.WriteLine("Duplicate Removed:");
for (i = 0; i < Array_Size; i++)
{
Console.WriteLine("Element " + i + " " + number[i]);
}
Console.ReadLine();
}
}
The easiest way is to use Linq's Distinct method:
number = number.Distinct().ToArray();
This will return a new array without any duplicates.
The duplicate is displayed as zero, since you assign the value of the duplicate to be zero, in the line,
if(number[j]==number[i])
number[j]=0
to delete the element from the array, use the following code:
if(number[j]==number[i])
{
int k=j;
while(k<Array_Size-1)
{
number[k]=number[k+1];
k++;
}
Array_Size--;
}
the statement Array_Size--; is done so that the last element is not repeated twice
This is my complete code in which I put some double-for-loop statement to
prevent it from inserting the duplicated integers in an array.
Have a look.
class Program
{
static void Main(string[] args)
{
const int ARRAY_SIZE = 5;
int[] ArrayTable = new int[ARRAY_SIZE];
int Element=0;
int a;
for(a=0; a<ArrayTable.Length;a++)
{
Console.Write("Please Enter an integer (between 10-100): ");
Element = Int32.Parse(Console.ReadLine());
while (Element < 10 || Element > 100)
{
Console.Write("Try again (between 10-100): ");
Element = Int32.Parse(Console.ReadLine());
}
ArrayTable[a] = Element;
for (int b = 0; b < a; b++)
{
while (ArrayTable[a] == ArrayTable[b])
{
Console.Write("Integer Duplicated!\nTry again: ");
Element = Int32.Parse(Console.ReadLine());
ArrayTable[a] = Element;
Console.WriteLine();
while (Element < 10 || Element > 100)
{
Console.Write("Try again (between 10-100): ");
Element = Int32.Parse(Console.ReadLine());
ArrayTable[a] = Element;
}
}
}
}
for (int c = 0; c < ArrayTable.Length; c++)
{
Console.Write("{0} ", ArrayTable[c]);
}
}

Count occurences in byte list/array using another byte list/array

I am trying to get a count of all the times a byte sequences occurs in another byte sequences. It cannot however re-use a bytes if it already counted them. For example given the string
k.k.k.k.k.k. let's assume the byte sequence was k.k it would then find only 3 occurrences rather than 5 because they would be broke down like: [k.k].[k.k].[k.k]. and not like [k.[k].[k].[k].[k].k] where they over lap and essentially just shift 2 to the right.
Ideally the idea is to get an idea how a compression dictionary or run time encoding might look. so the goal would be to get
k.k.k.k.k.k. down to just 2 parts, as (k.k.k.) is the biggest and best symbol you can have.
Here is source so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
static class Compression
{
static int Main(string[] args)
{
List<byte> bytes = File.ReadAllBytes("ok.txt").ToList();
List<List<int>> list = new List<List<int>>();
// Starting Numbers of bytes - This can be changed manually.
int StartingNumBytes = bytes.Count;
for (int i = StartingNumBytes; i > 0; i--)
{
Console.WriteLine("i: " + i);
for (int ii = 0; ii < bytes.Count - i; ii++)
{
Console.WriteLine("ii: " + i);
// New pattern comes with refresh data.
List<byte> pattern = new List<byte>();
for (int iii = 0; iii < i; iii++)
{
pattern.Add(bytes[ii + iii]);
}
DisplayBinary(bytes, "red");
DisplayBinary(pattern, "green");
int matches = 0;
// foreach (var position in bytes.ToArray().Locate(pattern.ToArray()))
for (int position = 0; position < bytes.Count; position++) {
if (pattern.Count > (bytes.Count - position))
{
continue;
}
for (int iiii = 0; iiii < pattern.Count; iiii++)
{
if (bytes[position + iiii] != pattern[iiii])
{
//Have to use goto because C# doesn't support continue <level>
goto outer;
}
}
// If it made it this far, it has found a match.
matches++;
Console.WriteLine("Matches: " + matches + " Orig Count: " + bytes.Count + " POS: " + position);
if (matches > 1)
{
int numBytesToRemove = pattern.Count;
for (int ra = 0; ra < numBytesToRemove; ra++)
{
// Remove it at the position it was found at, once it
// deletes the first one, the list will shift left and you'll need to be here again.
bytes.RemoveAt(position);
}
DisplayBinary(bytes, "red");
Console.WriteLine(pattern.Count + " Bytes removed.");
// Since you deleted some bytes, set the position less because you will need to redo the pos.
position = position - 1;
}
outer:
continue;
}
List<int> sublist = new List<int>();
sublist.Add(matches);
sublist.Add(pattern.Count);
// Some sort of calculation to determine how good the symbol was
sublist.Add(bytes.Count-((matches * pattern.Count)-matches));
list.Add(sublist);
}
}
Display(list);
Console.Read();
return 0;
}
static void DisplayBinary(List<byte> bytes, string color="white")
{
switch(color){
case "green":
Console.ForegroundColor = ConsoleColor.Green;
break;
case "red":
Console.ForegroundColor = ConsoleColor.Red;
break;
default:
break;
}
for (int i=0; i<bytes.Count; i++)
{
if (i % 8 ==0)
Console.WriteLine();
Console.Write(GetIntBinaryString(bytes[i]) + " ");
}
Console.WriteLine();
Console.ResetColor();
}
static string GetIntBinaryString(int n)
{
char[] b = new char[8];
int pos = 7;
int i = 0;
while (i < 8)
{
if ((n & (1 << i)) != 0)
{
b[pos] = '1';
}
else
{
b[pos] = '0';
}
pos--;
i++;
}
//return new string(b).TrimStart('0');
return new string(b);
}
static void Display(List<List<int>> list)
{
//
// Display everything in the List.
//
Console.WriteLine("Elements:");
foreach (var sublist in list)
{
foreach (var value in sublist)
{
Console.Write("{0,4}", value);
}
Console.WriteLine();
}
//
// Display total count.
//
int count = 0;
foreach (var sublist in list)
{
count += sublist.Count;
}
Console.WriteLine("Count:");
Console.WriteLine(count);
}
static public int SearchBytePattern(byte[] pattern, byte[] bytes)
{
int matches = 0;
// precomputing this shaves some seconds from the loop execution
int maxloop = bytes.Length - pattern.Length;
for (int i = 0; i < maxloop; i++)
{
if (pattern[0] == bytes[i])
{
bool ismatch = true;
for (int j = 1; j < pattern.Length; j++)
{
if (bytes[i + j] != pattern[j])
{
ismatch = false;
break;
}
}
if (ismatch)
{
matches++;
i += pattern.Length - 1;
}
}
}
return matches;
}
}
Refer to the post to get the non binary of the file should be, here is the binary data:
011010110010111001101011001011100110101100101110011010110010111001101011001011100110101100101110 I am hope to have it smaller than how it started.
private static int CountOccurences(byte[] target, byte[] pattern)
{
var targetString = BitConverter.ToString(target);
var patternString = BitConverter.ToString(pattern);
return new Regex(patternString).Matches(targetString).Count;
}
With this solution you'd have access to the individual indexes that matched (while enumerating) or you could call Count() on the result to see how many matches there were:
public static IEnumerable<int> Find<T>(T[] pattern, T[] sequence, bool overlap)
{
int i = 0;
while (i < sequence.Length - pattern.Length + 1)
{
if (pattern.SequenceEqual(sequence.Skip(i).Take(pattern.Length)))
{
yield return i;
i += overlap ? 1 : pattern.Length;
}
else
{
i++;
}
}
}
Call it with overlap: false to solve your problem or overlap: true to see the overlapped matches (if you're interested.)
I have a couple of other methods with slightly different API (along with better performance) here, including one that work directly on streams of bytes.
quick and dirty with no regex. although i'm not sure if it answers the intent of the question, it should be relatively fast. i think i am going to run some timing tests against regex to see for sure the relative speeds:
private int CountOccurrences(string TestString, string TestPattern)
{
int PatternCount = 0;
int SearchIndex = 0;
if (TestPattern.Length == 0)
throw new ApplicationException("CountOccurrences: Unable to process because TestPattern has zero length.");
if (TestString.Length == 0)
return 0;
do
{
SearchIndex = TestString.IndexOf(TestPattern, SearchIndex);
if (SearchIndex >= 0)
{
++PatternCount;
SearchIndex += TestPattern.Length;
}
}
while ((SearchIndex >= 0) && (SearchIndex < TestString.Length));
return PatternCount;
}
private void btnTest_Click(object sender, EventArgs e)
{
string TestString1 = "k.k.k.k.k.k.k.k.k.k.k.k";
string TestPattern1 = "k.k";
System.Console.WriteLine(CountOccurrences(TestString1, TestPattern1).ToString()); // outputs 6
System.Console.WriteLine(CountOccurrences(TestString1 + ".k", TestPattern1).ToString()); // still 6
System.Console.WriteLine(CountOccurrences(TestString1, TestPattern1 + ".").ToString()); // only 5
}

Categories