i need to organize the numbers and get the median and mode from any quantity of numbers, so i tried different ways to implement this but i just can't get with the solution.
public static void Main()
{
int i, n;
int[] a = new int[100];
Console.Write("\n\nRead n number of values in an array and display it in reverse order:\n");
Console.Write("------------------------------------------------------------------------\n");
Console.Write("Input the number of elements to store in the array :");
n = Convert.ToInt32(Console.ReadLine());
//quantity of numbers to insert
Console.Write("Input {0} number of elements in the array :\n", n);
for (i = 0; i < n; i++)
{
Console.Write("element - {0} : ", i);
a[i] = Convert.ToInt32(Console.ReadLine());
}
//individial numbers to insert
Console.Write("\nThe values store into the array are : \n");
for (i = 0; i < n; i++)
{
Console.Write("{0} ", a[i]);
}
}
i tried to use this, but i don't know how to use it
public static class Extensions
{
public static decimal GetMedian(this int[] array)
{
int[] tempArray = array;
int count = tempArray.Length;
Array.Sort(tempArray);
decimal medianValue = 0;
if (count % 2 == 0)
{
// count is even, need to get the middle two elements, add them together, then divide by 2
int middleElement1 = tempArray[(count / 2) - 1];
int middleElement2 = tempArray[(count / 2)];
medianValue = (middleElement1 + middleElement2) / 2;
}
else
{
// count is odd, simply get the middle element.
medianValue = tempArray[(count / 2)];
}
return medianValue;
}
}
Median is a middle item (or average of two middle items) in the sorted collection:
using System.Linq;
...
int[] a = ...
...
double median = a
.OrderBy(item => item) // from sorted sequence
.Skip((a.Length - 1) / 2) // we skip leading half items
.Take(2 - a.Length % 2) // take one or two middle items
.Average(); // get average of them
Mode is the local maximum of the distribution, the most frequent element in it:
int mode = a
.GroupBy(item => item)
.OrderByDescending(group => group.Count())
.First().Key;
Related
I have a large sequence of integers (1M+).
Whenever a user queries my API, I need to pick one of these integers in a non-sequential, not random and non-repeating way. I cannot store the history of all integers previously returned.
I came up with a "shaking" algorithm which simply moves values around within a very large array:
static int[] Shake(
int[] values,
Func<int, bool> predicate,
Func<int, int> moveBy)
{
static int Adjust(int index, int size)
{
while (index > size - 1) index -= size;
while (index < 0) index += size;
return index;
}
var count = values.Length;
for (var oldIndex = 0; oldIndex < count - 1; oldIndex++)
{
if (!predicate(oldIndex)) continue;
var newIndex = Adjust(oldIndex + moveBy(oldIndex), count);
var value = values[oldIndex];
values[oldIndex] = values[newIndex];
values[newIndex] = value;
}
return values;
}
var indexes = Enumerable.Range(0, size).ToArray();
indexes = Shake(indexes, idx => idx % 3 == 0, idx => idx + 50);
indexes = Shake(indexes, idx => idx % 2 == 0, idx => 12);
return indexes;
This algorithm works and but is not really efficient:
I need to create and loop through large collections of items
May consume lots of memory / CPU
This is a fairly slow algorithm
Instead of creating large arrays of data, I was wondering if there is another way to return a number in a
non-sequential, not random and non-repeating way (maybe a formula / mathematical series but my math sucks).
Thx for your help
Here you have an efficient and simple solution, you just need a prime number and remember n, the next time you need to increment n.
class Program
{
const long prime = 15_485_863;
static void Main(string[] args)
{
const int arrayLenght = 1_000_0000;
var numbers = new int[arrayLenght];
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = i;
}
var hashSet = new HashSet<int>();
for (int i = 0; i < numbers.Length; i++)
{
var number = GetNonSequentialNotRandomNonRepeatingNumber(numbers, i);
if (hashSet.Add(number) == false)
{
Console.WriteLine($"Something went wrong. {number} is duplicated");
}
}
}
static int GetNonSequentialNotRandomNonRepeatingNumber(int[] numbers, int n)
{
int pos = (int) ((prime * (long) n) % numbers.Length);
return numbers[pos];
}
}
I'm trying to solve whats probably an easy task, but I'm extremely new to this and don't quite have my head around working with arrays in a complex fashion. I'm trying to figure out if two inputs each corresponding numbers sum to the same number (for example with 123 and 321, 1+3 2+2 and 1+3 all equal 4).
The code I have so far has broken down each input into arrays, and I can sum those arrays into a third array, but I cant figure out how to check it with itself. Should I even bother with the 3rd array, and just figure out how to check the sums of the array in a loop?
public static void Main()
{
Console.Write("\n\n"); //begin user input
Console.Write("Check whether each cooresponding digit in two intigers sum to the same number or not:\n");
Console.Write("-------------------------------------------");
Console.Write("\n\n");
Console.Write("Input 1st number then hit enter: ");
string int1 = (Console.ReadLine());//user input 1
Console.Write("Input 2nd number: ");
string int2 = (Console.ReadLine());//user input 2
int[] numbers = new int[int1.ToString().Length]; //changing user inputs to strings for array
int[] numbers2 = new int[int2.ToString().Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = int.Parse(int1.Substring(i, 1));//populating arrays
numbers2[i] = int.Parse(int2.Substring(i, 1));
}
int[] numbers3 = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers3[i] = (numbers[i] + numbers2[i]);
}
}
}
You can create the collections on the fly...
bool isEqual = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()))
.Zip(Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString())),
(i, j) => new
{
First = i,
Second = j,
Total = i + j
})
.GroupBy(x => x.Total)
.Count() == 1;
The output will equal true if all elements add up to the same value...
Test cases:
Should succeed
12345
54321
Should fail
12345
55432
To understand the above query, lets break it up into sections.
// Here I'm just converting a string to an IEnumerable<int>, a collection of integers basically
IEnumerable<int> ints1 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
IEnumerable<int> ints2 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
// Zip brings together two arrays and iterates through both at the same time.
// I used an anonymous object to store the original values as well as the calculated ones
var zippedArrays = ints1.Zip(ints2, (i, j) => new
{
First = i, // original value from ints1
Second = j, // original values from ints2
Total = i + j // calculated value ints1[x] + ints2[x]
});
// if the totals are [4,4,4], the method below will get rid of the duplicates.
// if the totals are [4,3,5], every element in that array would be returned
// if the totals are [4,4,5], only [4,5] would be returned.
var distinctByTotal = zippedArrays.GroupBy(x => x.Total);
// So what does this tell us? if the returned collection has a total count of 1 item,
// it means that every item in the collection must have had the same total sum
// So we can say that every element is equal if the response of our method == 1.
bool isEqual = distinctByTotal.Count() == 1;
You're 99% of the way there already. Just lose the third array and check each individual sum in your final loop.
bool isOK = numbers.Length = numbers2.Length && numbers.Length > 0;
if(isOK)
{
int expectedSum = numbers[0] + numbers2[0];
for (int i = 1; i < numbers.Length; i++)
{
var sum = (numbers[i] + numbers2[i]);
if(sum != expectedSum)
{
isOK = false;
break;
}
}
}
Console.WriteLine(isOk ? "Good job." : "You got some learning to do.");
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+",");
}
My task is to add a very big number to another and print the result.
Here is my implementation, it should give 1000 as output but it writes 0000.
How it should work:
if the two number has equal length:
just /10 for the digit %10 for the remainder. If the length of the result is bigger than the original add the last remainder to the last element of the output array.
if the two number has different length:
sum the intersection part and add the remainder (in temp) to the relative complementl.
What is wrong?
static int[] SumOfBigNumbers(int[] firstNumber, int[] secondNumber)
{
int temp = 0;
int maxLength = (Math.Max(firstNumber.Length, secondNumber.Length));
int minLength = (Math.Min(firstNumber.Length, secondNumber.Length));
int[] output = new int[maxLength + 1];
//sum of equal part
for (int counter = 0; counter < minLength; counter++)
{
output[counter] = (firstNumber[counter] + secondNumber[counter] + temp) % 10;
temp = (firstNumber[counter] + secondNumber[counter] + temp) / 10;
}
//exceptions add the temp to the bigger array
if (temp!=0)
{
//if first array is bigger than the second
if (firstNumber.Length > secondNumber.Length)
{
for (int i = minLength; i < maxLength + 1; i++)
{
output[i] = (firstNumber[i] + temp) % 10;
temp = (firstNumber[i] + temp) / 10;
}
}
//if second array is bigger than the first
else if (firstNumber.Length < secondNumber.Length)
{
for (int i = minLength; i < maxLength + 1; i++)
{
output[i] = (secondNumber[i] + temp) % 10;
temp = (secondNumber[i] + temp) / 10;
}
}
//if two number has equal length but there is temp left
else
{
output[maxLength] = temp;
}
}
return output;
}
static void Main()
{
int[] firstArray = new int[3] { 0, 0, 5 };
int[] secondArray = new int[3] { 0, 0,5 };
int[] output = SumOfBigNumbers(firstArray, secondArray);
foreach (var i in output)
{
Console.WriteLine(output[i]);
}
}
Edit: better if I copy the task: Write a method that calculates the sum of two very long positive integer numbers. The numbers are represented as array digits and the last digit (the ones) is stored in the array at index 0. Make the method work for all numbers with length up to 10,000 digits.
While BigInteger is a better way to handle big numbers, I think your bug is in while printing the output. try this:
foreach (var i in output)
{
Console.WriteLine(i);
}
also this will print 0001, better reverse it while printing
Your code works fine but you have a small bug where you display the output array.
You do a foreach (var i in output) {, but you use the i as an index, which it isn't. It is already the actual value. Just write the i to the console.
foreach (var i in output)
{
Console.WriteLine(i);
}
// Output:
// 0
// 0
// 0
// 1
Or use a for loop to go through the array by index.
for (int i = 0; i < output.Length; i++)
{
Console.WriteLine(output[i]);
}
// Output:
// 0
// 0
// 0
// 1
I am trying to create a bowling program that when you enter in your name followed by your score, it will take the average, lowest, and highest scores of the players and print them. However for some reason I cannot get the lowest score to print, as when I hit enter twice, it will use the blank value instead of the lowest entered value and name. How can I fix this so that it will display the lowest score?
{
class Program
{
static void Main(string[] args)
{
const int SIZE = 10;
int i;
// create an array with 10 elements
string[] scoreInfo = new string[SIZE];
string[] names = new string[SIZE];
int[] scores = new int[SIZE];
for (i = 0; i < SIZE; i++)
{
// Prompt the user
Console.Write("Enter your first name and score on one line");
Console.WriteLine(" separated by a space.");
// Read one line of data from the file and save it in inputStr
string inputStr = Console.ReadLine( );
// if statement to break when the user enters a zero
if (inputStr == String.Empty)
{
break;
}
// The Split method creates an array of two strings
scoreInfo = inputStr.Split();
// Parse each element of the array into the correct data type
names[i] = scoreInfo[0];
scores[i] = int.Parse(scoreInfo[1]);
}
Console.WriteLine("The avarage score is {0}", AverageScore(scores, i));
Console.WriteLine("{0} scored the lowest at {1}", names[LowScore(scores, i--)], scores[LowScore(scores, i--)]);
Console.WriteLine("{0} scored the highest at {1}", names[HighScore(scores)], scores[HighScore(scores)]);
Console.ReadLine();
Console.ReadLine();
}
static int LowScore(int[] scores, int j)
{
int min = scores.Min();
return Array.IndexOf(scores, min);
}
static int HighScore(int[] scores)
{
int max = scores.Max();
return Array.IndexOf(scores, max);
}
static double AverageScore(int[] numbers, int j)
{
double average = 0;
for (int i = 0; i < j--; i++)
{
int product = 1;
product = numbers[i] * product;
average = product / j;
}
return average;
}
}
}
Use a different data structure and make less work for yourself.
Start with a dictionary that maps names to scores so that you don't have to mess around with indexes.
Then, LINQ is your friend, as you've already noticed. You don't need to create functions for things that already exist (like min/max/average).
eg.
Dictionary<string, int> ranking = new Dictionary<string, int>();
ranking.Add("adam", 20);
ranking.Add("bill", 10);
ranking.Add("carl", 30);
double avg = ranking.Average(kvp => (double)kvp.Value);
var sorted = ranking.OrderBy(kvp => kvp.Value);
var min = sorted.First();
var max = sorted.Last();
Console.WriteLine("Average: {0}", avg);
Console.WriteLine("Lowest: {0} with {1}", min.Key, min.Value);
Console.WriteLine("Highest: {0} with {1}", max.Key, max.Value);
Modify your Average function like this:-
static double AverageScore(int[] numbers, int j)
{
double sum = 0;
for (int i = 0; i < j; i++)
{
sum += numbers[i];
}
return (double)sum / j;
}
I am not sure why you were taking product of items for finding average of scores.
And Your Min function like this:-
static int LowScore(int[] scores, int j)
{
int min = scores.Where((v, i) => i < j).Min();
return Array.IndexOf(scores, min);
}
Here, you are passing the complete array of integer, so if only 3 players entered values, rest of the values will be initialized to default, i.e. 0 for int, Thus you were getting 0 as Min value.
Also, You need to change the method invocation like this:-
Console.WriteLine("{0} scored the lowest at {1}", names[LowScore(scores, i)], scores[LowScore(scores, i)]);