I am trying to read in a string via input from the user and store it in an array. The string must be single digit numbers separated by a space. The user will enter exactly 20 numbers and no number can occur twice in a row.
Example string:
1 2 9 6 3 2 4 5 8 1 3 6 4 7 8 2 1 9 6 3
Here is the code I have to do this, as well as error check and it's not working properly. I think I am way over thinking the error checking. refString is an int array of size 20 in the code below.
case 2:
bool validated = false;
Console.WriteLine("\nPlease enter a 20 character reference string, each separated by a single space");
Console.WriteLine("A number should not occur twice in a row, ex: 1 5 4 4 6");
Console.WriteLine("Each character must be an integer 1-9");
Console.WriteLine("Example reference string: 1 2 3 4 2 1 5 6 2 1 2 3 7 6 3 2 1 2 3 6");
Console.WriteLine("\nEnter reference string: ");
string s = Console.ReadLine();
refString = s.Split(' ').Select(n => Convert.ToInt32(n)).ToArray(); //split string and add numbers into array
int totalCount = refString.Length;
//if the user entered exactly 20 numbers, check to see if any of the numbers occur twice in a row
if (totalCount == 20)
{
for (i = 1; i < 20; i++)
{
while (refString[i] == refString[i - 1]) //make sure two of the same number side by side do not occur
{
break;
}
}
}
while (totalCount != 20 || !validated)
{
for (i = 1; i < 20; i++)
{
while (refString[i] == refString[i - 1]) //make sure two of the same number side by side do not occur
{
Console.WriteLine("\nError: reference string is NOT 20 numbers");
Console.WriteLine("\nEnter reference string: ");
s = Console.ReadLine();
refString = s.Split(' ').Select(n => Convert.ToInt32(n)).ToArray();
totalCount = refString.Length;
}
}
if (totalCount == 20)
{
for (i = 1; i < 20; i++)
{
while (refString[i] == refString[i - 1]) //make sure two of the same number side by side do not occur
{
break;
}
}
}
}
break;
}
Try something like:
case 2:
bool correctNumber = true;
bool repeats = false;
Console.WriteLine("\nPlease enter a 20 character reference string, each seperated by a single space");
Console.WriteLine("A number should not occur twice in a row, ex: 1 5 4 4 6");
Console.WriteLine("Each character must be an integer 1-9");
Console.WriteLine("Example reference string: 1 2 3 4 2 1 5 6 2 1 2 3 7 6 3 2 1 2 3 6");
Console.WriteLine("\nEnter reference string: ");
string s = Console.ReadLine();
refString = s.Split(' ').Select(n => Convert.ToInt32(n)).ToArray(); //split string and add numbers into array
correctNumber = refString.Length == 20;
if (correctNumber)
{
for (i = 1; i < 20; i++)
{
if(refString[i] == refString[i - 1])
{
repeats = true;
break;
}
}
}
else
{
Console.WriteLine("Error: reference string is NOT 20 numbers");
}
if (repeats)
{
Console.WriteLine("Error: reference string contains repeated numbers");
}
break;
That will check for the two fail conditions and output relevant messages.
You can use regex to check if there are two contiguous repeating digits
if(!Regex.IsMatch(n,#".*(\d) \1.*"))
s.Split(" ").Select(x=>int.Parse(x));
bool correct = false;
while(!correct){
// ask for numbers until correct
Console.WriteLine("\nEnter reference string: ");
string s = Console.ReadLine();
refString = s.Split(' ').Select(n => Convert.ToInt32(n)).ToArray();
int totalCount = refString.Length;
// check
if (totalCount == 20) {
correct = true;
for (i = 1; i < refString.Length; i++) {
if(refString[i] == refString[i - 1]) {
// consecutive number
Console.WrinteLine("Error: same consecutive number "+refString[i]);
correct = false;
break;
}
}
}else{
Console.WrinteLine("Error: not 20 elements");
}
}
One trick you can do is use Linq to filter out all the bad values, then check the count hasn't dropped below 20:
var listOfInts = stringTest.Split(' ').Select(n => Convert.ToInt32(n)).ToList();
// filter ints with adjacent values and out of range
var count =
listOfInts.Where((i, j) => (j + 1 == listOfInts.Count || // adjacent values
i != listOfInts[j + 1])
&& i > 0 && i < 10) // out of range
.Count(); // total
If count < 20, then you know something was invalid (either out-of-range or next to an identical value).
Related
Lets assume we have an input from keyboard.
I dont know the length of the input, but I know that the first part is an array of integers, where consecutive groups of three numbers describe assets: type,value,amount.
then termination number is -1 then I have another array of integers and then again termination number -1
For example:
1 500 5 2 25 100 3 10 50 -1 3 9 -1
So I want to have 2 containers to work with first is {(1,500,5),(2,25,100),(3,10,50)} and second is {3,9}.
How I can make this happen?
This will give you a List of structs containing the asset data triples from the first part of the string, and an array of ints from the second part:
public struct assetData {
public int type;
public int value;
public int amount;
};
void Main()
{
string keyboard = "1 500 5 2 25 100 3 10 50 -1 3 9 -1";
string[] parts = keyboard.Split("-1", StringSplitOptions.RemoveEmptyEntries);
int[] assetInput = parts[0].Trim().Split().Select(int.Parse).ToArray();
int[] numbers = parts[1].Trim().Split().Select(int.Parse).ToArray();
// take 3 numbers at a time into assetData structs. Store them.
var assetInfo = new List<assetData>();
for (int i = 0; i < assetInput.Length; i += 3)
{
assetData item;
item.type = assetInput[i];
item.value = assetInput[i+1];
item.amount = assetInput[i+2];
assetInfo.Add(item);
}
}
variant for array input:
public struct assetData {
public int type;
public int value;
public int amount;
};
void Main()
{
string keyboard = "1 500 5 2 25 100 3 10 50 -1 3 9 -1";
int[] input = keyboard.Trim().Split().Select(int.Parse).ToArray();
// 3 numbers at a time into assetData structs. Store them.
var assetInfo = new List<assetData>();
int i;
for (i=0; input[i] != -1; i += 3)
{
assetData item;
item.type = input[i];
item.value = input[i+1];
item.amount = input[i+2];
assetInfo.Add(item);
}
i++; // skip the -1
var numbers = new List<int>();
while (i < input.Length - 1) {
numbers.Add(input[i]);
i++;
}
}
find numbers in an input range that are evenly divisible by 3. Only =, ++, -- operators can be used.
I've tried to get the remainder using shift operators and other loops but I always require a -= or something similar.
Console.Clear();
int n,
d,
count = 1;
// get the ending number
n = getNumber();
// get the divisor
d = 3;// getDivisor();
Console.WriteLine();
Console.WriteLine(String.Format("Below are all the numbers that are evenly divisible by {0} from 1 up to {1}", d, n));
Console.WriteLine();
// loop through
while (count <= n)
{
// if no remainder then write number
if(count % d == 0)
Console.Write(string.Format("{0} ", count));
count++;
}
Console.WriteLine();
Console.WriteLine();
Console.Write("Press any key to try again. Press escape to cancel");
Expected results:
Enter the ending number: 15
Below are all the numbers that are evenly divisible by 3 from 1 up to 15
3, 6, 9, 12, 15
If the == operator is permitted for the assignment, you can have something like
int remainder = 0; // assumes we always count up from 1 to n, we will increment before test
Inside the loop replace the existing if with
remainder++;
if (remainder == 3) {
Console.Write(string.Format("{0} ", count));
remainder = 0;
}
[EDIT: Typo in code corrected]
Think about the underlying maths:
2 x 3 = 3 + 3
3 x 3 = 3 + 3 + 3
4 * 3 = 3 + 3 + 3 + 3
...and so on.
Also, to be evenly divisible by 3 means that the number multiplying 3 must be even.. So...
public bool EvenlyDivisibleBy3(int aNumber)
{
int even = 2;
int currentMultiple = 0;
while (currentMultiple < aNumber)
{
int xTimes = 0;
for (int x = 1; x <= even; x++)
{
((xTimes++)++)++; // add three to xTimes
}
currentMultiple = xTimes;
(even++)++: // next even number
}
return currentMultiple == aNumber;
}
in this case I want to take the number of elements in the array , but the array is dependent on user input
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
for (int i = first; i <= second; i++)
{
if (i % 5 == 0)
{
int[] some =new int [i];
int c =some.Length;
Console.WriteLine(c);
}
}
I tried several options, but the output is still a list of the numbers divisible by 5 without remainder. How is right to do?
example: first = 15, second = 50.
Expected output = 8.
8 numbers divisible by 5 without remainder(15,20,25,30...50)
You can just loop through the numbers and count how many you find that are divisible by 5:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
int cnt = 0;
for (int i = first; i <= second; i++) {
if (i % 5 == 0) {
cnt++;
}
}
However, you dont have to generate the numbers to know how many there are. You can just calculate where the last number is (as that is easier than the first) and then calculate how many there are before that but after the first:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
second -= second % 5;
int cnt = (second - first) / 5 + 1;
For example for the input 3 and 11 you want to count the numbers 5 and 10. The expression 11 % 5 gives 1, so second becomes 10 (the last number). Then second - first is 7, doing integer division with 5 gives 1, and then add 1 gives 2.
If my array contains random numbers in respective order (1,2,3,4,5,6,7) and I want to create another array of my guesses (1,4,2,4,5,6,7), I would like to see how many I got correct, respectively.
Here's my code:
Console.WriteLine("Can you guess the numbers that have appeared on the screen respectively?");
for (int i = 1; i < num.Length; i++)
{
Console.Write(i + ". ");
string temp = Console.ReadLine();
userGuess[i] = Convert.ToInt32(temp);
}
for (int i = 1; i < num.Length; i++)
{
if (num[i] == userGuess[i])//Here's my problem. I am unable to
//test whether my guess resides in the num array.
{
count++;
}
}
Console.WriteLine("You got " + count + " guesses right.");
Count should end up with 5 correct if I was to choose 1,4,2,4,5,6,7, judging that my num array contains 1,2,3,4,5,6,7 respectively.
Thanks!
Like #failedprogramming said, you missmatch index between array userGuess and num.
I know you want to start user input with no."1" but, it will get your userguess array will be moving in wrong index.
1 2 3 4 5 6 7
blank 1 4 2 4 5 6
So, you have no right answer.
Maybe you can use this:
Console.WriteLine("Can you guess the numbers that have appeared on the screen respectively?");
for (int i = 1; i < num.Length+1; i++)
{
Console.Write(i + ". ");
string temp = Console.ReadLine();
userGuess[i-1] = Convert.ToInt32(temp);
}
for (int i = 0; i < num.Length; i++)
{
if (num[i] == userGuess[i])//Here's my problem. I am unable to
//test whether my guess resides in the num array.
{
count++;
}
}
Console.WriteLine("You got " + count + " guesses right.");
Since the two arrays are of equal length, you can use LINQ's Zip() method:
var result = num.Zip(userGuess, (n, u) => n == u ? 1 : 0).Sum();
This compares each corresponding element in the two lists, returning 1 for a match or 0 for a non-match, then adds up the values. The result is effectively the number of matches.
So this is what I want my output to look like:
How many numbers? 10
Give number 1: 1
Give number 2: 3
Give number 3: 1
Give number 4: 3
Give number 5: 4
Give number 6: 6
Give number 7: 4
Give number 8: 8
Give number 9: 2
Give number 10: 1
Number 1 appeared 3 times
Number 2 appeared 1 times
Number 3 appeared 2 times
Number 4 appeared 2 times
Number 6 appeared 1 times
Number 8 appeared 1 times
The thing is, I've got the part which reads the user input done. However, I have no idea how to continue with the part which tells how many times each number appeared.
Also, I'm doing this as a schoolwork so most of the code is in Finnish. I hope you can still understand it, though.
using System;
namespace Ohjelma
{
class Ohjelma
{
static void Main()
{
Console.Write("Kuinka monta lukua? ");
int pituus = Convert.ToInt32(Console.ReadLine());
int[] luvut = new int[pituus];
for (int i = 0; i < pituus; i++)
{
Console.Write("Anna {0}. luku:", i + 1);
luvut[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < luvut.Length; i++)
{
Console.Write(luvut[i]);
}
Console.ReadLine();
}
}
}
Edit: Sorry about the code block on the example of what it should output, not exactly sure how to use blockquotes even though I tried. Thanks!
You can use LINQ like:
var query = luvut.GroupBy(r => r)
.Select(grp => new
{
Value = grp.Key,
Count = grp.Count()
});
For output you can use:
foreach (var item in query)
{
Console.WriteLine("Value: {0}, Count: {1}", item.Value, item.Count);
}
int[] num = { 1, 1, 1, 3, 3, 4, 5, 6, 7, 0 };
int[] count = new int[10];
//Loop through 0-9 and count the occurances
for (int x = 0; x < 10; x++){
for (int y = 0; y < num.Length; y++){
if (num[y] == x)
count[x]++;
}
}
//For displaying output only
for (int x = 0; x < 10; x++)
Console.WriteLine("Number " + x + " appears " + count[x] + " times");
Program Output:
Number 0 appears 1 times
Number 1 appears 3 times
Number 2 appears 0 times
Number 3 appears 2 times
Number 4 appears 1 times
Number 5 appears 1 times
Number 6 appears 1 times
Number 7 appears 1 times
Number 8 appears 0 times
I understand how bad it feels when all your classmates had finish theirs, and you are still struggling. My codes should be simple enough for your learning.
If you don't want to use LINQ, you can code as follows:-
public class Program
{
public static void Main()
{
int[] arr1 = new int[] {1,3,3,5,5,4,1,2,3,4,5,5,5};
List<int> listArr1 = arr1.ToList();
Dictionary<int,int> dict1 = new Dictionary<int,int>();
foreach(int i in listArr1)
{
if(dict1.ContainsKey(i))
{
int value = dict1[i];
value++;
dict1[i]= value;
}
else
{
dict1.Add(i,1);
}
}
for(int x = 0 ; x < dict1.Count(); x++)
{
Console.WriteLine("Value {0} is repeated {1} times", dict1.Keys.ElementAt(x),dict1[dict1.Keys.ElementAt(x)]);
}
}
}