"Exercise Guidelines:
First read the count of numbers, for example in a variable n. Then consequently enter n numbers with one for loop. While entering each new number, save in two variables the smallest and the largest number until this moment.(...)"
I do an exercise from C# tutorial and I have problem with extracting numbers from one line string consisting of unknown number of numbers.
I have such code so far:
Console.WriteLine("Type in several Integers:");
string input = System.Console.ReadLine();
string[] splittedLine = input.Split(' ');
foreach(string number in splittedLine)
{
Console.Write(" " + number);
}
Console.Read();
I am supposed to print smallest and biggest number from input using for loop.
As far as I understand I need to parse numbers from splitedLine array so they are integers, then compare them and use Int32.MaxValue and Int32.MinValue.
I'm stuck on "Parsing" part of the code.
---------- update -----------
When I add
int[] parsedNumbers = int.Parse(splittedLine[])
I get error that splittedLine[] needs a value. Is it possible to bulk-parse all elements from array?
The most basic solution (no linq or anything) based on your code:
Console.WriteLine("Type in several Integers:");
string input = System.Console.ReadLine();
string[] splittedLine = input.Split(' ');
int max = Int32.MinValue; // initialize the maximum number to the minimum possible values
int min = Int32.MaxValue; // initialize the minimum number to the maximum possible value
foreach(string number in splittedLine)
{
int currentNumber = int.Parse(number); // convert the current string element
// to an integer so we can do comparisons
if(currentNumber > max) // Check if it's greater than the last max number
max = currentNumber; // if so, the maximum is the current number
if(currentNumber < min) // Check if it's lower than the last min number
min = currentNumber; // if so, the minium is the current number
}
Console.WriteLine(string.Format("Minimum: {0} Maximum: {1}", min, max));
No error checking done here, so the input must be correct
To get min and max values of user input you can use LINQ.
Sample code:
Console.WriteLine("Type in several Integers:");
string input = System.Console.ReadLine();
List<int> numbers = null;
if(!string.IsNullOrWhiteSpace(input)) // Check if any character has been entered by user
{
string[] splittedLine = input.Split(' '); // Split entered string
if(splittedLine != null && splittedLine.Length != 0) // Check if array is not null and has at least one element
{
foreach (var item in splittedLine)
{
int tmpNumber;
if(int.TryParse(item, out tmpNumber)) // Parse string to integer with check
{
if (numbers == null) numbers = new List<int>(); // If is at least one integer - create list with numbers
numbers.Add(tmpNumber); // Add number to list of int
}
}
}
}
else
{
// TODO: info for user
}
if(numbers != null) // Check if list of int is not null
{
Console.WriteLine("Min: {0}", numbers.Min()); // Get min value from numbers using LINQ
Console.WriteLine("Max: {0}", numbers.Max()); // Get max value from numbers using LINQ
}
else
{
// TODO: info for user
}
Console.Read();
Min and Max value without using LINQ:
...
if(numbers != null)
{
var min = numbers[0];
var max = numbers[0];
foreach (var item in numbers)
{
if (item < min) min = item;
if (item > max) max = item;
}
Console.WriteLine("Min: {0}", min);
Console.WriteLine("Max: {0}", max);
}
...
Try
int test;
var numbers =
from n in input.Split(' ')
where int.TryParse(n, out test) // Only to test if n is an integer
select int.Parse(n)
;
int maxValue = numbers.Max();
int minValue = numbers.Min();
Without Linq
int maxValue = int.MinValue;
int minValue = int.MaxValue;
foreach(var s in input.Split(' '))
{
int number;
if(int.TryParse(s, out number))
{
maxValue = Math.Max(maxValue, number);
minValue = Math.Min(minValue, number);
}
}
class Program
{
static public void Main(string[] args)
{
// Get input
Console.WriteLine("Please enter numbers seperated by spaces");
string input = Console.ReadLine();
string[] splittedInput = input.Split(' ');
// Insure numbers are actually inserted
while (splittedInput.Length <= 0)
{
Console.WriteLine("No numbers inserted. Please enter numbers seperated by spaces");
splittedInput = input.Split(' ');
}
// Try and parse the strings to integers
// Possible exceptions : ArgumentNullException, FormatException, OverflowException
// ArgumentNullException shouldn't happen because we ensured we have input and the strings can not be empty
// FormatException can happen if someone inserts a string that is not in the right format for an integer,
// Which is : {0,1}[+\-]{1,}[0-9]
// OverflowException happens if the integer inserted is either smaller than the lowest possible int
// or bigger than the largest possible int
// We keep the 'i' variable outside for nice error messages, so we can easily understand
// What number failed to parse
int[] numbers = new int[splittedInput.Length];
int i = 0;
try
{
for (; i < numbers.Length; ++i)
{
numbers[i] = int.Parse(splittedInput[i]);
}
}
catch (FormatException)
{
Console.WriteLine("Failed to parse " + splittedInput[i] + " to an integer");
return;
}
catch (OverflowException)
{
Console.WriteLine(splittedInput[i] + " is either bigger the the biggest integer possible (" +
int.MaxValue + ") or smaller then the lowest integer possible (" + int.MinValue);
return;
}
// Save min and max values as first number
int minValue = numbers[0], maxValue = numbers[0];
// Simple logic from here - number lower than min? min becomes numbers, and likewise for max
for (int index = 1; index < numbers.Length; ++i)
{
int currentNumber = numbers[index];
minValue = minValue > currentNumber ? currentNumber : minValue;
maxValue = maxValue < currentNumber ? currentNumber : maxValue;
}
// Show output
Console.WriteLine("Max value is : " + maxValue);
Console.WriteLine("Min value is : " + minValue);
}
}
This is the most accurate, non-linq and extensive answer I could write on Notepad++
Related
In my class i have to create a method that will find multiple maximum numbers within an array. the user will input how many maximum numbers they are wanting and then the code should display all those numbers. if i select 2 this code will show me the 2 maximum numbers but if im wanting more it just doesnt work. i was trying to search the array for the maximum number and then have it display the outcome and then change that element to 0 and than repeat the loop until it hits that number (userinput). im soo frustrated can someone help me please
public static int FindingMaxNum(int[] arr, int max)
{
int userinput;
Console.Write("Enter the number of maximum values: ");
userinput = Convert.ToInt32(Console.Read());
int i = 0;
int c = 0;
for (i = 0; i < arr.Length; i++)
{
if (arr[i] >= max)
{
max = arr[i];
c++;
while (c <= userinput)
{
Console.WriteLine(max);
arr[i] = 0;
break;
}
}
}
return -1;
}
If I understand correctly, you want to get some number of items from an array whose values are greater than all the others in the array.
If so, something like this modified version of your method may do the trick:
public static void WriteMaxNum(int[] arr)
{
if (arr == null)
{
Console.WriteLine("The array is null");
return;
}
if (arr.Length == 0)
{
Console.WriteLine("The array is empty");
return;
}
int count = arr.Length;
int numMaxValues;
// Get number of max values to return from user
do
{
Console.Write("Enter the number of maximum values (1 - {0}): ", count);
} while (!int.TryParse(Console.ReadLine(), out numMaxValues) ||
numMaxValues < 1 ||
numMaxValues > count);
// Output the max values
Console.Write("The {0} max values are: ", numMaxValues);
Console.WriteLine(string.Join(", ", arr.OrderByDescending(i => i).Take(numMaxValues)));
}
Usage
static void Main(string[] args)
{
var myArray = new[] { 1, 9, 4, 8, 2, 5, 0, 7, 6, 3 };
WriteMaxNum(myArray);
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output
Simple solution with average complexity O(nlogn):
Sort the array first then print the last N nos.
int[] arr = new int[]{-5,-69,1250,24,-96,32578,11,124};
Array.Sort(arr);
int n=3;
for(int i=arr.Length-1;i>=0 && n>0 ;--i){
n--;
Console.WriteLine(arr[i]);
}
Now coming to your code, there are multiple problems. First there is no need to take 'max' as parameter in your function. Second you are looping only arr.Length times once. There should be nested loop, outer one of which has to run userInput times and inner on has to iterate over all the values. Third you should initialize to extracted value position to minimum value so that the method works for negative numbers too.
Refined code:
for(int i=0;i<userinput;++i){
int max = int.MinValue,pos=-1;
for(int j=0;j<arr.Length;++j){
if(max<arr[j]){
pos = j;
max = arr[j];
}
}
arr[pos] = int.MinValue;
Console.Write(max+",");
}
I try to write program that check the ratio between odd and even
digits in a given number. I've had some problems with this code:
static void Main(string[] args)
{
int countEven = 0 ;
int countOdd = 0 ;
Console.WriteLine("insert a number");
int num = int.Parse(Console.ReadLine());
int length = num.GetLength;
for (int i = 0;i<length ; i++)
{
if((num/10)%2) == 0)
int countEven++;
}
}
any ideas?
The problem is that int does not have a length, only the string representation of it has one.As an alternative to m.rogalski answer, you can treat the input as a string to get all the digits one by one. Once you have a digit, then parsing it to int and checking if it is even or odd is trivial.Would be something like this:
int countEven = 0;
int countOdd = 0;
Console.WriteLine("insert a number");
string inputString = Console.ReadLine();
for (int i = 0; i < inputString.Length; i++)
{
if ((int.Parse(inputString[i].ToString()) % 2) == 0)
countEven++;
else
countOdd++;
}
Linq approach
Console.WriteLine("insert a number");
string num = Console.ReadLine(); // check for valid number here?
int countEven = num.Select(x => x - '0').Count(x => x % 2 == 0);
int countOdd = num.Select(x => x - '0').Count(x => x % 2 != 0);
Let's assume your input is : 123456
Now all you have to do is to get the modulo from the division by ten : int m = num % 10;
After that just check if bool isEven = m % 2 == 0;
On the end you have to just divide your input number by 10 and repeat the whole process till the end of numbers.
int a = 123456, oddCounter = 0, evenCounter = 0;
do
{
int m = a % 10;
switch(m % 2)
{
case 0:
evenCounter++;
break;
default: // case 1:
oddCounter++;
break;
}
//bool isEven = m % 2 == 0;
}while( ( a /= 10 ) != 0 );
Online example
Made a small change to your code and it works perfectly
int countEven = 0;
int countOdd = 0;
Console.WriteLine( "insert a number" );
char[] nums = Console.ReadLine().ToCharArray();
for ( int i = 0; i < nums.Length; i++ )
{
if ( int.Parse( nums[i].ToString() ) % 2 == 0 )
{
countEven++;
}
else
{
countOdd++;
}
}
Console.WriteLine($"{countEven} even numbers \n{countOdd} odd numbers");
Console.ReadKey();
What I do is get each number as a a character in an array char[] and I loop through this array and check if its even or not.
If the Input number is a 32-bit integer (user pick the length of the number)
if asked:
The number of even digits in the input number
Product of odd digits in the input number
The sum of all digits of the input number
private void button1_Click(object sender, EventArgs e) {
int num = ConvertToInt32(textBox1.Text);
int len_num = textBox1.Text.Length;
int[] arn = new int[len_num];
int cEv = 0; pOd = 0; s = 0;
for (int i = len_num-1; i >= 0; i--) { // loop until integer length is got down to 1
arn[i] = broj % 10; //using the mod we put the last digit into a declared array
if (arn[i] % 2 == 0) { // then check, is current digit even or odd
cEv++; // count even digits
} else { // or odd
if (pOd == 0) pOd++; // avoid product with zero
pOd *= arn [i]; // and multiply odd digits
}
num /= 10; // we divide by 10 until it's length is get to 1(len_num-1)
s += arn [i]; // sum of all digits
}
// and at last showing it in labels...
label2.Text = "a) The even digits count is: " + Convert.ToString(cEv);
label3.Text = "b) The product of odd digits is: " + Convert.ToString(pOd);
label4.Text = "c) The sum of all digits in this number is: " + Convert.ToString(s);
}
All we need in the interface is the textbox for entering the number, the button for the tasks, and labels to show obtained results. Of course, we have the same result if we use a classic form for the for loop like for (int i = 0; and <= len_num-1; i++) - because the essence is to count the even or odd digits rather than the sequence of the digits entry into the array
static void Main(string args[]) {
WriteLine("Please enter a number...");
var num = ReadLine();
// Check if input is a number
if (!long.TryParse(num, out _)) {
WriteLine("NaN!");
return;
}
var evenChars = 0;
var oddChars = 0;
// Convert string to char array, rid of any non-numeric characters (e.g.: -)
num.ToCharArray().Where(c => char.IsDigit(c)).ToList().ForEach(c => {
byte.TryParse(c.ToString(), out var b);
if (b % 2 == 0)
evenChars++;
else
oddChars++;
});
// Continue with code
}
EDIT:
You could also do this with a helper (local) function within the method body:
static void Main(string args[]) {
WriteLine("Please enter a number...");
var num = ReadLine();
// Check if input is a number
if (!long.TryParse(num, out _)) {
WriteLine("NaN!");
return;
}
var evenChars = 0;
var oddChars = 0;
// Convert string to char array, rid of any non-numeric characters (e.g.: -)
num.ToCharArray().Where(c => char.IsDigit(c)).ToList().ForEach(c => {
byte.TryParse(c.ToString(), out var b);
if (b % 2 == 0)
evenChars++;
else
oddChars++;
// Alternative method:
IsEven(b) ? evenChars++ : oddChars++;
});
// Continue with code
bool IsEven(byte b) => b % 2 == 0;
}
Why am I using a byte?
Dealing with numbers, it is ideal to use datatypes that don't take up as much RAM.
Granted, not as much an issue nowadays with multiple 100s of gigabytes possible, however, it is something not to be neglected.
An integer takes up 32 bits (4 bytes) of RAM, whereas a byte takes up a single byte (8 bits).
Imagine you're processing 1 mio. single-digit numbers, and assigning them each to integers. You're using 4 MiB of RAM, whereas the byte would only use up 1 MiB for 1 mio. numbers.
And seeming as a single-digit number (as is used in this case) can only go up to 9 (0-9), you're wasting a potential of 28 bits of memory (2^28) - whereas a byte can only go up to 255 (0-255), you're only wasting a measly four bits (2^4) of memory.
I mean how to count and sum input numbers until receive "end".
thanks !
And also how to find out input is number or letter in c#?
class Program
{
static void Main(string[] args)
{
int n = 0;
int sum = 0;
string inp;
do
{
Console.Write("Numbers ");
inp = Console.ReadLine();
int num= Convert.ToInt16(inp);
sum = sum + num;
n++;
} while (too == "end");
int average = sum / n;
Console.WriteLine(" " + average);
Console.ReadLine();
}
}
I would suggest you use a normal while loop and also add validation to check to integer input.
For the while loop you want to loop until the input is not equal to "end":
while(inp != "end")
For the validation, you can use int.TryParse method:
int num = 0;
if (int.TryParse(inp, out num)) { }
Here is a modified example of your code:
int n = 0;
int sum = 0;
string inp = null;
while(inp != "end")
{
Console.Write("Numbers ");
inp = Console.ReadLine();
int num = 0;
if (int.TryParse(inp, out num))
{
sum = sum + num;
n++;
}
}
int average = sum / n;
Console.WriteLine(" " + average);
Console.ReadLine();
// A list to hold all of the numbers entered
List<int> numbers = new List<int>();
// Will hold the inputted string
string input;
// This needs to be outside the loop so it's written once
Console.Write("Numbers: " + Environment.NewLine);
// Keep going until we say otherwise
while (true)
{
// Get the input
input = Console.ReadLine();
// Will hold the outcome of parsing the input
int number = -1;
// Check to see if input was a valid number
bool success = int.TryParse(input, out number);
// If it was a valid number then remember it
// If ANY invalid or textual input is detected then stop
if (success)
numbers.Add(number);
else
break;
}
// Write the count and average
Console.WriteLine("Count:" + numbers.Count);
Console.WriteLine("Average:" + numbers.Average());
Console.ReadLine();
Input:
Numbers:
1
2
3
4
5
Output:
Count: 5
Average: 3
The only thing here a little different to what you specified is ANY invalid or textual entry causes it to finish, not just typing the word "end", although that obviously works too.
is there a way to format a double value such that it shows the n siginifacant digits only?
for example I have a double with value 123456, can we have a format string such that it displays the first 3 digits only.
double x=12346;
string s=x.ToString("Some format"); //display 123 only
is that possible?
Although there are formats that would let you drop some or all of the fraction, no format would let you drop some of the significant digits of the whole part of the number.
If you would like to keep the first three digits of the whole number, you need to divide the value so that its whole part has only three digits.
One approach to computing the divisor is taking log10N, checking if it is above 2, and dividing by 10 to the corresponding power:
private static void Print(double x) {
int n = (int)Math.Log10(x);
if (n > 2) {
x /= Math.Pow(10, n-2);
}
Console.WriteLine((int)x);
}
Demo.
You can't format the largest part of the double to only be to 3 sig. fig. but you can split the string. Try:
String s = x.ToString().Substring(0, n);
Where n is the number of significant figures you wish to keep.
I made a console application for this example. I know you need a double or int data type for the number, but I didn't know how manipulate the decimal numbers after the point, so I used a string (if you don't mind, store the number value inside string data type):
string number = "";
string digits = "";
int n = 0;
int count = 0;
number = "45.6";
//number = "456";
n = 3;
if (number.Contains('.')) //If the number has decimals...
{
if (n < number.Length)
{
if (number.IndexOf('.') < n)
{
while (count <= n) //... we will count the number in a different way.
{
if (number[count] != '.')
{
digits = digits + number[count];
}
count++;
}
}
else
{
while (count < n)
{
if (number[count] != '.')
{
digits = digits + number[count];
}
count++;
}
}
}
}
else
{
if (n <= number.Length)
{
while (count < n) //If not, we count without the decimal point.
{
digits = digits + number[count];
count++;
}
}
}
Console.WriteLine("N significant digits: " + digits);
You can try with decimal and integer numbers, but in the code, they both are strings. As I said before, if you don't mind using this data type, this example will help you, if not, you can try with "Substring" function from the String class.
For instance, if the input is set to 1234, the program will return 11213141 because digit 1 occurs once, digit 2 occurs once ... so on and so forth.
Another example: 142225 => 11234151
My program works fine with small input but if the input has 10 digits or more, the result would make no sense. Please help.
class Example
{
// Get sorted(ascending) list for each digit in num
public static List<int> GetList(long num)
{
List<int> listOfInts = new List<int>();
while (num > 0)
{
int remainder = (int) num % 10;
listOfInts.Add(remainder);
num = num / 10;
}
listOfInts.Sort();
return listOfInts;
}
// Get minimum digit in the list
public static int getMinimumInt(List<int> l)
{
int min = 10;
foreach (int s in l)
{
if (s <= min)
{
min = s;
}
}
return min;
}
// Get count of the minimum digit specified
public static int getCount(int i,List<int> l)
{
int count = 0;
foreach (int s in l)
{
if (s == i)
{
count++;
}
}
return count;
}
public static void Main()
{
long input = 1234567891020; // Arbituary input
// initialize
List<int> outputList=new List<int>(); // List that would be eventually outputted
List<int> listOfInt = new List<int>();
listOfInt = GetList(input);
//Loop end till no element left in listOfInt
while ((listOfInt.ToArray()).Length!=0)
{
int item = getMinimumInt(listOfInt);
int count = getCount(item, listOfInt);
outputList.Add(item); // Add the item to be counted
outputList.Add(count); // Add count of the item
listOfInt.RemoveRange(0, count); // Remove digits that have been counted
}
// Output the list
foreach (int i in outputList)
{
Console.Write(i);
}
Console.WriteLine();
Console.ReadLine();
}
}
}
In your GetList() function, you are casting your 10+ digit long to an integer:
int remainder = (int) num % 10;
Attempting to place a 10+ digit number into an int means you are running up against the highest value of 32-bit integers, which is 2,147,483,647. That would explain why your results seem strange.
Use a long instead. If that isn't enough you can try System.Numerics.BigInteger, which will allow you to add more digits to it until you run out of memory.
You can use this LINQ approach, it doesn't care about numbers, just chars:
string output = String.Concat(input
.GroupBy(c => c)
.Select(g => String.Format("{0}{1}", g.Key, g.Count())));
If you want the result as long use long.TryParse(output, out longvariable).
int sourceVal = 12341231;
string sourceStr = sourceVal.ToString();
List<char> uniqueChars = null;
#if LINQ
uniqueChars = sourceStr.ToCharArray().Distinct().ToList();
#else
uniqueChars = new List<char>();
foreach (char c in sourceStr)
if (!uniqueChars.Contains(c))
uniqueChars.Add(c);
#endif
string result = "";
foreach (var wantedChar in uniqueChars)
#if LINQ
result += wantedChar.ToString() + (sourceStr.Count(f => f == wantedChar)).ToString();
#else
result += wantedChar.ToString() + (sourceStr.Split(wantedChar).Length - 1).ToString();
#endif
Console.WriteLine("Result = " + result);
This was my code to keep it as similar to yours. If you want to limit the count, use a modulus on the end (% 10) to keep the count to a single digit.
Having now seen the other Linq answer, I think that is a lot neater. Given that your maximum answer would be something like 192,939,495,969,798,999 if sorted in character order ascending, you would need a long not an int to store that.
Just change
int remainder = (int) num % 10;
to
int remainder = (int)(num % 10);
The first one is casting num to int then doing the mod 10. This will result in overflow when num is larger than int.MaxValue, typically a negative number. The second does the mod 10 first then the cast, which is safe as the mod will result in a value that can easily fit into an int.