This is the problem given:
Write a program in C# that prompts the user to enter a number of integer values. The program
stores the integers in an array, counts the frequency of each integer and displays the frequency on the Console.
I am new to C# and don`t know Linq or dictionary yet.
static void Main(string[] args) {
//declare variables
int n,
y,
x;
int[] index;
int[] count;
//prompt user for the number of elements
Console.WriteLine("Please enter the number of element to be stored");
n = int.Parse(Console.ReadLine());
index = new int[n];
count = new int[n];
//Console.WriteLine(index.Length);
Console.WriteLine("input {0} number of element", n);
for (int i = 0; i < index.Length; i++) {
index[i] = int.Parse(Console.ReadLine());
for (y = 0; y < index.Length; y++)
if (index[y] == i) count[i]++;
}
for (int j = 0; j < index.Length; j++)
Console.WriteLine("element - {0} : {1}", j, index[j]);
Console.WriteLine("the frequency of all elements of the array");
for (x = 0; x < index.Length; x++)
Console.WriteLine("{0} occurs {1} times", index[x], x);
}
This the result I get if I select 3 integers of 2, 1, 2. 2 is repeated.
2 occurs 0 times.
1 occurs 1 times.
2 occurs 2 times.
You’re doing in wring way. And perform wise also it’s not efficient solution. You are run for loop inside for loop. You can use dictionary and store the count in it, so it will work in a single for loop.
static void GetFrequency(int[] arr)
{
Dictionary<int, int> mp = new Dictionary<int, int>();
// Traverse through array elements and count frequencies
for (int i = 0; i < arr.Length; i++)
{
if (mp.ContainsKey(arr[i]))
{
var val = mp[arr[i]];
mp.Remove(arr[i]);
mp.Add(arr[i], val + 1);
}
else
{
mp.Add(arr[i], 1);
}
}
}
Usually, when we want to query (i.e. find out frequencies) a collection (array) we use Linq:
using System.Linq;
...
var freqData = index
.GroupBy(item => item)
.Select(group => $"{group.Key} occurs {group.Count()} times.");
Console.WriteLine(string.Join(Environment.NewLine, freqData));
If you want to count frequency manually, you can use Dictionary<int, int> to have Key (item from the array)
and Value (frequency) correspondence:
Dictionary<int, int> freqData = new Dictionary<int, int>();
foreach (int item in index)
if (freqData.TryGetValue(item, out int freq))
freqData[item] = freq + 1;
else
freqData.Add(item, 1);
foreach (var pair in freqData)
Console.WriteLine($"{pair.Key} occurs {pair.Value} times.");
Related
I am trying to count how many times a number appears in an array 1 (a1) and then trying to print out that number by storing it in array 2 (a2) just once and then try to print array 2. But first using for loop and a function, I will check that if a number already exist in array 2 then move to next index in array 1, unfortunateley this code is not working; can someone please help me in trying to fix it, I don't need some complex solutions like dictionaries or lists athe moment, although it might be helpful too. thanks, I am not an expert in programming and I try to practise it in my free time, so please help me.
I just want this code to be fixed for my understanding and knowledge
class Program
{
static void Main(string[] args)
{
int i, j;
int[] a1 = new int[10];
int[] a2 = new int[10];
int[] a3 = new int[10];
//takes an input
for (i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(Console.ReadLine());
}
for (i = 0; i < a1.Length; i++)
{
Cn(a1, a2); //calls in function
i++; //increments is if true
int count = 0;
for (j = 0; j < a1.Length; j++)
{
//if a number matches with a number in second array
if (a1[i] == a1[j])
{
//do count ++
count++;
// store that number into second array
a2[i] = a1[i];
}
}
//store the number of counts in third array
a3[i] = count;
}
for (i = 0; i < a2.Length; i++)
{
if (a2[i] != 0)
{
Console.WriteLine(a2[i]);
}
}
Console.ReadLine();
}
//function to check if element at current index of array 1 exists in array 2 if yes than break
public static void Cn (int[] aa1, int [] aa2)
{
int k, j;
for ( k = 0; k < aa1.Length; k++)
{
for (j = 0; j < aa2.Length; j++)
{
if (aa1[k] == aa2[j])
break;
}
}
}
}
You probably want to do a group by count:
int[] a1 = new int[10];
var rnd = new Random();
//takes an input
for (int i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(rnd.Next(0, 11)); // or Console.ReadLine()
}
var grouped = a1
.GroupBy(x => x)
.Select(g => new
{
Item = g.Key,
Count = g.Count()
}).ToList(); // ToList() is optional, materializes the IEnumerable
foreach (var item in grouped)
{
Console.WriteLine($"number: {item.Item}, count: {item.Count}");
}
This uses a Hash algorithm internally.
You can solve this without a Hash or Dictionary but it wouldn't be very efficient because you need to do lots of linear searches through the arrays.
The advantage of a Hash algorithm is that your lookups or groupings are much faster than if you loop over a complete array to find / increment an item.
I am making a lottery game that asks the user for 10 numbers and then check it against random numbers that i have created in an array. I need to compare the two but I am not allowed to use the contains method.
I think I need to use a foreach loop to compare the arrays but really I am at a loss of what to do. I have been piecing it together from the little I know and would like to know if I am on the right track.
Is a foreach loop the correct way to compare the two arrays?
This is my code so far.
using System;
namespace lotto2
{
class Program
{
static void Main(string[] args)
{
//an array named "input" to hold the users' 10 guesses
int[] inputs = new int[10];
//an array named "lotNum" to hold 10 random numbers
int[] lotNums = new int[10];
//a for loop to loop over the inputs array. each loop will ask the user for a number
Console.WriteLine("Enter your 10 lottery numbers one at a time. The numbers must be between 1 and 25.");
for (int i = 0; i < inputs.Length; i++)
{
inputs[i] = Convert.ToInt32(Console.ReadLine());
}
//a random number generator
Random ranNum = new Random();
//loop to call the random generator 10 times and store 10 random numbers in the "lotNum" array
for (int i = 0; i < 10; i++)
{
lotNums[i] = ranNum.Next(1, 26); //chooses random numbers between 1 and 25
}
//writes out the randomly generated lotto numbers
Console.Write("\nThe lottery numbers are: ");
for (int i = 0; i < 10; i++)
{
Console.Write("{0} ", lotNums[i]);
}
//loop for checking users inputs against random generated numbers..
//foreach loop maybe?
foreach (var input in lotNums)
{
}
//print out if there are any matches, which numbers matched
//declared integer for the correct numbers the user guessed
int correct;
//end progam
Console.WriteLine("\n\nPress any key to end the program:");
Console.ReadKey();
}
}
}
Here's a program that correctly does what you want. It even ensures that you don't have duplicate lotto numbers.
void Main()
{
const int count = 10;
const int max = 25;
//an array named "input" to hold the users' 10 guesses
int[] inputs = new int[count];
//a for loop to loop over the inputs array. each loop will ask the user for a number
Console.WriteLine("Enter your {0} lottery numbers one at a time. The numbers must be between 1 and {1}.", count, max);
for (int i = 0; i < inputs.Length; i++)
{
inputs[i] = Convert.ToInt32(Console.ReadLine());
}
//a random number generator
Random ranNum = new Random();
//an array named "allNums" to hold all the random numbers
int[] allNums = new int[max];
for (int i = 0; i < allNums.Length; i++)
{
allNums[i] = i + 1;
}
//shuffle
for (int i = 0; i < allNums.Length; i++)
{
int j = ranNum.Next(0, allNums.Length);
int temporary = allNums[j];
allNums[j] = allNums[i];
allNums[i] = temporary;
}
//an array named "lotNum" to hold 10 random numbers
int[] lotNums = new int[count];
Array.Copy(allNums, lotNums, lotNums.Length);
//writes out the randomly generated lotto numbers
Console.Write("\nThe lottery numbers are: ");
for (int i = 0; i < lotNums.Length; i++)
{
Console.Write("{0} ", lotNums[i]);
}
int correct = 0;
Console.Write("\nThe correct numbers are: ");
for (int i = 0; i < lotNums.Length; i++)
{
for (int j = 0; j < inputs.Length; j++)
{
if (lotNums[i] == inputs[j])
{
Console.Write("{0} ", lotNums[i]);
correct++;
};
}
}
Console.Write("\nYou got {0} correct. ", correct);
Console.WriteLine("\n\nPress any key to end the program:");
Console.ReadLine();
}
You're on the right way.
My implementation would be:
foreach (var input in inputs)
{
for (int i = 0; i < lotNums.Length; i++){
if(input == lotNums[i]){
Console.WriteLine(lotNums[i]);
}
}
}
This will compare every number of the input array with the lottery array.
I'm printing every match, but you can set a variable to True if it finds a match or add every matching number into an array if you need it.
This is what I have tried.I hope it makes sense?
static void LottoMethod(int[] randNums,int[] userNums)
{
Console.WriteLine("Guess 10 numbers");
for(int i = 0; i <= userNums.Length-1; i++)
{
userNums[i] = Int32.Parse( Console.ReadLine());
}
Console.WriteLine("The numbers you entered: ");
foreach(int k in userNums)
{
Console.Write(k+" ");
}
//generate 10 numbers randomly
Random rnds = new Random();
for(int k = 0; k <= randNums.Length - 1; k++)
{
randNums[k] = rnds.Next(1, 26);
}
Console.WriteLine("Random Numbers");
foreach(int i in randNums)
{
Console.Write(i + " ");
}
int correctNums = 0;
//Check if random numbers correspond with entered numbers
try
{
for(int i = 0; i <= randNums.Length-1; i++)
{
for(int j = 0; j <= userNums.Length-1; j++)
{
if (randNums[i] == userNums[j])
{
correctNums++;
}
}
}
Console.WriteLine($"There are {correctNums} numbers ");
}
catch(Exception e) {
throw new Exception(e.ToString());
}
}
You have to calculate intersection of two sequences. You have three options:
Double foreach loop. This is something to avoid as it has time complexity O(m*n). It it not a problem for 10 items, but we should make programs that scale.
Using hash join. You can use HashSet for this and it would be my preferred method. But as it inherently implies using Contains, it is not the option here.
Merging sorted sequences. This would be the way to go here.
The program is rather self explanatory, it produces and intersects two random sequences.
static Random rnd = new Random((int)DateTime.Now.Ticks);
static int[] GetRandomArray(int arrSize, int minNumber, int maxNumber)
{
int[] tmpArr = new int[maxNumber - minNumber + 1];
for (int i = 0; i < tmpArr.Length; ++i)
{
tmpArr[i] = i + minNumber; // fill with 1, 2, 3, 4,...
}
int[] ret = new int[arrSize];
for (int i = 0; i < ret.Length; ++i)
{
int index = rnd.Next(tmpArr.Length - i); //choose random position
ret[i] = tmpArr[index];
tmpArr[index] = tmpArr[tmpArr.Length - 1 - i]; //fill last of the sequence into used position
}
return ret;
}
static IEnumerable<int> GetMatches(int[] a, int[] b)
{
Array.Sort(a);
Array.Sort(b);
for (int i = 0, j = 0; i < a.Length && j < b.Length;)
{
if (a[i] == b[j])
{
yield return a[i];
++i;
++j;
}
else if (a[i] > b[j])
{
++j;
}
else
{
++i;
}
}
}
static void Main(string[] args)
{
var a = GetRandomArray(5, 3, 7);
var b = GetRandomArray(10, 1, 25);
Console.WriteLine("A: " + string.Join(", ", a));
Console.WriteLine("B: " + string.Join(", ", b));
Console.WriteLine("Matches: " + string.Join(", ", GetMatches(a, b)));
Console.ReadKey();
}
The result is something like:
A: 7, 4, 6, 3, 5
B: 17, 1, 8, 14, 11, 22, 3, 20, 4, 25
Matches: 3, 4
You can think about what would happen if one or both of the sequences contain duplicities.
This was a small problem the teacher gave us at school. We were asked to make a program which keeps asking the user to input test scores until he inputs -99 to stop the program. The values are stored in an array and the highest, lowest and average scores are displayed.
The problem I have with my code is that whenever I run it it always gives me a value of 0 for lowest scores even though there are no zeros in the input. Can anyone please point out the mistake in my code?
Code:
static void Main(string[] args)
{
int[] za = new int[100];
scores(za, 0);
}
public static void scores(int[] ar, int x)
{
Console.Write("Please enter homework score [0 to 100] (-99 to exit): ");
int a = Convert.ToInt16(Console.ReadLine());
if (a != -99)
{
ar[x] = a;
x++;
scores(ar, x);
}
else
{
Console.Clear();
Console.WriteLine("Homework App");
int[] arr = new int[x];
foreach (int l in arr)
{
arr[l] = ar[l];
}
int lowest = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (lowest > arr[i]) { lowest = arr[i]; }
}
int highest = arr[0];
for (int j = 1; j < arr.Length; j++)
{
if (highest < arr[j]) { highest = arr[j]; }
}
double sum = 0;
double nums = 0;
for (int k = 0; k < arr.Length; k++)
{
sum = sum + arr[k];
nums++;
}
double average = sum / nums;
Console.WriteLine("Highest Score: {0}", highest);
Console.WriteLine("Lowest Score: {0}", lowest);
Console.WriteLine("Average Score: {0}", average);
Console.ReadLine();
}
}
When you're copying items, don't use a foreach loop and then the element stored in the array as the index that you're inserting to. Instead, use a for loop with a counter variable.
You should change this:
int[] arr = new int[x];
foreach (int l in arr)
{
// You're using the wrong value for the index here.
// l represents the value of the item stored in `arr`, which is `0`
arr[l] = ar[l];
}
To this:
int[] arr = new int[x];
for (var counter = 0; counter < x; counter++)
{
arr[counter] = ar[counter];
}
Let's say I want to insert values into an array while at the same time sorting it.
This was my solution:
int[] arr = new int[5];
int k;
arr[0] = int.Parse(Console.ReadLine());
for (int i = 1; i < arr.Length; i++)
{
int num = int.Parse(Console.ReadLine());
for (k = i; k > 0 && num < arr[k - 1];--k) arr[k] = arr[k - 1];
arr[k] = num;
}
I know I didn't handle exceptions, I'm just talking about the code itself.
Is there a better way of doing this?
You can use a SortedSet<>, that gets automatically sorted as you add items.
var numbers = new SortedSet<int>()
{
4,
9,
6,
3
};
foreach (var number in numbers)
{
Console.WriteLine(number);
}
If it doesn't have to be array you could do this:
static void Main(string[] args)
{
List<int> list = new List<int>
{
1,
2,
7,
10
};
int k = int.Parse(Console.ReadLine());
list.Add(k);
list.Sort();
}
Edit: if you want to sort when inserting you could do this:
int k = int.Parse(Console.ReadLine());
int i = list.Where(x => x > k).Min();
int index = list.IndexOf(i);
list.Insert(index, k);
You can use a List and convert it into an array. When you maintain your list ordered at all time you can use the list's BinarySearch method to get the insert index:
const int length = 5;
List<int> result = new List<int>(length);
for (int i = 0; i < length; i++) {
int num = int.Parse(Console.ReadLine());
int insertIndex = result.BinarySearch(num);
if (insertIndex < 0) {
insertIndex = ~insertIndex;
}
result.Insert(insertIndex, num);
}
int[] arr = result.ToArray();
The binary search is much faster than the linear search you are currently performing. You won't see that with your current 5 values. You would defenitely see it with larger lists (hundrets or thousands of values).
I am trying to create a column to count how much a number is generated. Here is an example of the output I would like:
Number 1 has been generated 5 times.
Number 2 has been generated 2 times.
etc.
Here is my current code:
Random r = new Random();
int plus = 0;
for (int a = 0; a < 10; a++)
{
plus++;
Console.Write("Week {0}: ", plus );
for (int i = 0; i < 7; i++)
{
Console.Write(r.Next(1, 11));
Console.Write(", ");
}
Console.WriteLine();
}
Use a Dictionary<int,int>, where the key is the random number and the value is the count:
var count = new Dictionary<int, int>();
for (int i = 0; i < 7; i++)
{
var rndValue = r.Next(1, 11);
if (count.ContainsKey(rndValue))
count[rndValue]++;
else
count.Add(rndValue, 1);
Console.Write(rndValue);
Console.Write(", ");
}
foreach (var c in count)
Console.WriteLine("Number {0} has been generated {1} time(s).", c.Key, c.Value);
If you want to print the results for any numbers that are generated 0 times, you'll have to add some additional code to make sure a value of 0 is stored in the Dictionary for those values.
Something like this before the foreach statement should work for you:
for (var i = 1; i < 11; i++)
if (!count.ContainsKey(i))
count.Add(i, 0);
An alternate solution, using a single-dimensional array, as suggested in the comments. A Dictionary is pretty straight-forward, but this may be even easier to understand.
var count = new int[10];
for (int i = 0; i < 7; i++)
{
var nextRnd = r.Next(1, 11);
count[nextRnd - 1]++;
Console.Write(nextRnd);
Console.Write(", ");
}
for (var i = 0; i < count.Length; i++)
Console.WriteLine("Number {0} has been generated {1} time(s).", i + 1, count[i]);
I'd like to using a Dictionary to implement this function:
Dictionary<int,int> rand_count_list = new Dictionary<int,int>();
Random r = new Random();
int plus = 0;
for (int a = 0; a < 10; a++)
{
plus++;
Console.Write("Week {0}: ", plus);
for (int i = 0; i < 7; i++)
{
int rand = r.Next(1, 11);
if (rand_count_list.ContainsKey(rand))
rand_count_list[rand]++;
else
rand_count_list[rand] = 1;
Console.Write(rand);
Console.Write(", ");
}
Console.WriteLine();
}
foreach (int key in rand_count_list.Keys)
{
Console.Write("Number {0} has been generated {1} times. ", key, rand_count_list[key]);
}
var r = new Random();
var weeks = new List<List<int>>(
Enumerable.Range(0, 10)
.Select(w => new List<int>(Enumerable.Range(0, 7)
.Select(i => r.Next(1, 11)))));
foreach (var week in weeks)
{
Console.WriteLine("Week {0}: {1}", weeks.IndexOf(week), string.Join(",", week));
}
var allNumbers = weeks.SelectMany(n => n);
foreach (var number in allNumbers.Distinct().OrderBy(n => n))
{
Console.WriteLine("{0} was generated {1} times",
number,
allNumbers.Count(n => n == number));
}