Print repeated numbers only one time in c# - c#

I have an array with "n" numbers and I need to print all repeated numbers only one time
i made this code, but something is wrong
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 1; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j] && i!=j)
{
Console.WriteLine(numbers[i]);
break;
}
}
}
then if my array have the elements {2,3,1,5,2,3}
the program prints :
2
3
3
what can I do?

You can use:
using System.Linq;
…
foreach(var number in numbers.Distinct()) Console.WriteLine(number);
edit
I may have misunderstood the requirement. If you only want to output the numbers that appear more than once, then you can use:
foreach(var group in numbers.GroupBy(n => n).Where(g => g.Count() > 1))
Console.WriteLine(group.Key);

var query = numbers.GroupBy(x => x)
.Where(g => g.Skip(1).Any())
.Select(g => g.Key);
foreach (int n in query)
{
Console.WriteLine(n);
}
Or, alternatively...
var dict = new Dictionary<int, int>();
foreach (int n in numbers)
{
int count;
dict.TryGetValue(n, out count);
if (count == 1)
{
Console.WriteLine(n);
}
dict[n] = count + 1;
}

The problem in your code: you get 3 repeated because when i is 1 (looking at the first 3) there's another 3 in the list at the end, and when i is 5 (looking at the last 3) there's another three in the list near the beginning.
Instead you should look at only those numbers which come after your current position - change to int j = i; so that you only look at the positions after your current position, and you won't get repeated results.
for (int i = 0; i < numbers.Length; i++)
{
for (int j = i; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j] && i!=j)
{
Console.WriteLine(numbers[i]);
break;
}
}
}
Having said that, your algorithm is not as efficient as using a built in algorithm. Try GroupBy
var duplicates = numbers.GroupBy(n => n)
.Where(group => group.Count() > 1);
foreach (var group in duplicates)
{
Console.WriteLine("{0} appears {1} times", group.Key, group.Count());
}

One way to get distinct numbers is
var uniqueNumbers = numbers.Distinct().ToArray()
and then iterate over uniqueNumbers like you have in your snippet with numbers.

You can add the number to a HashSet as you loop and then only print if not in hash set.
That allows you to do it in one pass.
The algorithm above is n^2 which should be avoided.

// deletes an integer if it appears double
#include <iostream.h>
#include <conio.h>
int main ()
{
int count=0;
int ar[10]={1,2,3,3,3,4,5,6,7,7};
for (int i=0; i<10; i++)
{
if (ar[i]==ar[i+1])
count++;
else
cout << ar[i];
}
getch();
return 0;
}

Related

Trying to find Frequency of elements in array

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.

How do we count the number of occurrence from left to right and continue until we have consecutive numbers?

So the code that I wrote, is for the number of occurrence. Suppose in the sample part which is mentioned, if I give an input Array of {2,1,1,1,3}, it will give me the count of Number 2 occurrence as 1. Now, I'm struggling to write the code in a manner so that it gives me the count only if it's continuous from left to right. Suppose, if my array is {1,1,1,2,0}, only then it will give me the total occurrence of 1 as 3, but not if it's {1,0,1,2,1} or {0,0,1,1,1} or {1,1,2,2,1}
static void Evaluate_V5B(int[] window, int[] PayCombos,)
{
int[] Counters1 = new int[3];
for (int index0 = 0; index0 < 5; index0++)
{
Console.Write("{0} ", window[index0]);
int symbol = window[index0];
Counters1[symbol]++;
}
Console.WriteLine();
for (int indexJ = 0; indexJ < Counters1.Length; indexJ++)
{
Console.WriteLine("{0}", Counters1[indexJ]);
}
}
This will take the 1st element in the array and return continuous occurrences from left to right. If that element found anywhere else it will return 0 as count:
static void Evaluate(int[] array)
{
var count = 1;
var first = array[0];
for (int i = 1; i < array.Length; i++)
{
if(array[i] == first)
{
count++;
}
else{
for (int j = i + 1; j < array.Length; j++)
{
if(first == array[j]) {
count = 0;
break;
}
}
break;
}
}
Console.WriteLine($"Count of Number {first} occurrence is {count}");
}
This function will find the number of continuous occurrences of a specific number num in the array nums, if it is the first number.
static int ContinuousOccurrences(int[] nums, int num)
{
if (nums[0] == num)
{
int continuousOccurrences =
nums.TakeWhile(x => x == num).Count();
int totalOccurrences =
nums.Where(x => x == num).Count();
if(continuousOccurrences == totalOccurrences)
{
return continuousOccurrences;
}
else
{
return 0;
}
}
return 0;
}
If you want to know the number of continuous occurrences of the first number, call the function this way:
ContinuousOccurrences(nums, nums[0])

How to check how many specific digits appear in an array of numbers

I want to check how many specific digits appear in an array of numbers. For example, digit 2 appears:
input from 1 to 20
output
3 times
another example:
input from 1 to 100
output
19 times
this is my code
int count = 0;
string x = "";
string y = "";
string[] arr2 = new string[100000000];
for (int i = 1; i < arr2.Length; i++)
{
arr2[i - 1] = i.ToString();
}
foreach (var item in arr2)
{
for (int digit = 0;digit<item.Length;digit++)
{
if (digit == 2)
count++;
}
}
Console.WriteLine(count);
My code doesn't work but i don't know where the problem is.
Note : This must be done with for / foreach loops only, not using Dictionary or LINQ or DivRem.
An efficient and concise method is to use Aggregate to sum the counts as you go, rather than counting then summing or similar (this approach only requires one pass through the array):
arr2.Aggregate(0, (total, s) => total + s.Count(c => c == '2'))
This is functionally equivalent to:
int total = 0;
foreach (string s in arr2)
total += s.Count(c => c == '2');
If you don't want to use Linq or extension methods, then you can take the above code and just expand the remaining extension method:
int total = 0;
foreach (string s in arr2)
{
foreach (char c in s)
{
if (c == '2')
total++;
}
}
Note that converting your numbers to strings before processing them is a bit wasteful - you can do this using the modulus and division operators % and / to inspect the digits directly (note that this code requires a minor tweak to work with negative numbers):
int total = 0;
foreach (int i in somearrayofnumbers)
{
while (i != 0)
{
if (i % 10 == 2)
total++;
i /= 10;
}
}
Alright, for the sake of completion - the nicest way I can think of to do this is a hybrid of the above:
int CountDigits(int in, int val)
{
int total = 0;
while (in != 0)
{
if (in % 10 == val)
total++;
in /= 10;
}
return total;
}
...
int digitCount = numbers.Aggregate((total, i) => total + CountDigits(i, 2));
Using Math.DivRem is pretty unreadable, hence sticking to % and / above.
If you want to just use loops without the string array:
long count =0;
string x = "";
string y = "";
foreach (var i in Enumerable.Range(1, 100000000))
{
var s = i.ToString();
foreach (char t in s)
{
if (t == '2')
count++;
}
}
Console.WriteLine(count);
If you want to just use loops and the string array:
long count = 0;
string x = "";
string y = "";
string[] arr2 = new string[100000000];
for (var i = 1; i <= arr2.Length; i++)
{
arr2[i - 1] = i.ToString();
}
for (var i = 0; i < arr2.Length; i++)
{
var s = arr2[i];
if (s == null)
continue;
for (var j = 0; j < s.Length; j++)
{
if (s[j] == '2')
count++;
}
}
Console.WriteLine(count);
If you are willing to use LINQ
Either of these solutions will work. The latter will likely be more efficient.
var count = string.Join("", arr2).LongCount(z => z == '2');
var count = arr2.Select(z => z.LongCount(y => y == '2')).Sum();
The former joins all the values into a huge string, and then counts all the 2s in it.
The latter counts the number of 2s in each individual string and then adds them up at the end.

Improving performance of a Nested Loop

This logic is to find the number n in the array in which the range between n and n + 5 will include the most numbers in the array. I came up with a solution but it requires a nested loop, therefore it is kind of slow. Is there any way to improve its performance? Thanks in advance.
The array is guaranteed to sorted.
int[] myArray = new int[]{1,2,4,5,7,9,15,19};
int bestNumber = 0;
int MaxMatchFound = 0;
for (int o = 0; o < myArray.Length; o++)
{
int TempMatchFound = 0;
for (int i = 0; i < myArray.Length; i++)
{
if (myArray[i] >= myArray[o] && myArray[i] <= (myArray[o] + 5))
{
TempMatchFound++;
}
}
if (TempMatchFound > MaxMatchFound)
{
bestNumber = myArray[o];
MaxMatchFound = TempMatchFound;
}
}
return bestNumber;
Bucket the values, then loop over the values v and sum the associated counts for all values w that satisfy v <= w <= v + 5, then find the max count:
var buckets = myArray.GroupBy(n => n)
.ToDictionary(g => g.Key, g => g.Count());
var rangeCounts =
buckets.Keys
.Select(v =>
new {
Value = v,
Count = Enumerable.Range(0, 6)
.Sum(i => buckets.ContainsKey(v + i) ?
buckets[v + i] :
0
)
}
);
var bestRange = rangeCounts.MaxBy(x => x.Count);
Now, bestRange.Value is the starting point for your best range and bestRange.Count is the number of elements falling into the range [bestRange.Value, bestRange.Value + 5]. Here, I've used MaxBy.
Think this gets you linear performance. Building dictionary is linear, building rangeCounts is linear, MaxBy is linear. Even works on non-sorted.
Here you go: This runs in O(N) time, and O(1) memory. This forms the buckets described in other solutions, then discards them as you move through the array. The Queue is used to track which buckets are 'active' in the sense that they can be added to. The Dictionary will never have more than 6 entries in it, neither will the Queue.
int[] myArray = new int[]{1,2,4,5,7,9,15,19};
Dictionary<int, int> counts = new Dictionary<int, int>();
Queue<int> q = new Queue<int>();
int n = 0;
int currentMaxCount = 0;
for(int i = 0; i < myArray.Length; i++)
{
var currentNum = myArray[i];
if(counts.ContainsKey(currentNum))
{
counts[currentNum]++;
}
else
{
counts[currentNum] = 1;
q.Enqueue(currentNum);
}
for(int j = 1; j <= 5; j++)
{
if(counts.ContainsKey(currentNum - j))
counts[currentNum - j]++;
}
if(q.Peek() + 5 < currentNum)
{
if(counts[q.Peek()] > currentMaxCount)
{
currentMaxCount = counts[q.Peek()];
n = q.Peek();
}
counts.Remove(q.Dequeue());
}
}
while(q.Count > 0)
{
if(counts[q.Peek()] > currentMaxCount)
{
currentMaxCount = counts[q.Peek()];
n = q.Peek();
}
counts.Remove(q.Dequeue());
}
Console.WriteLine("There are {0} matches between {1} and {2}", currentMaxCount, n, n + 5);
Here's a solution that is O(n) and uses O(1) extra space regardless of the range.
It does a single pass through the array, always making 2N comparisons. I don't see any way to improve on this algorithm, although there are certainly micro optimizations that could squeeze a little more speed out of the implementation.
private int FindRange(int[] myArray)
{
const int range = 5;
int start = 0;
int maxMatchFound = 0;
int maxIndex = 0;
for (int i = 0; i < myArray.Length; ++i)
{
if (myArray[i] > myArray[start] + range)
{
int matchLength = i - start;
if (matchLength > maxMatchFound)
{
maxMatchFound = matchLength;
maxIndex = start;
}
// move forward until within range
do
{
++start;
} while (myArray[i] > myArray[start] + range);
}
}
// Final check, from myArray[start] to end of array
int len = myArray.Length - start;
if (len > maxMatchFound)
{
maxMatchFound = len;
maxIndex = start;
}
return maxIndex;
The idea here is that if a particular number a[x] falls within the range for a[i] then it will fall within the range for a[i+1], assuming that x > i. (So in your original array, the value at a[3] falls within the range of a[0], so it will also fall within the range of a[1] and a[2]).
So the index i is incremented until the value it references falls out of the range of a[start]. Then, start is incremented until a[i] is in range again. The two indexes move forward through the array in that alternating fashion.
Here's a one-line LINQ option. Not the best in terms of performance (it iterates multiple times). Still worth noting.
var result = myArray
.OrderByDescending(i => myArray.Count(i2 => i2 >= i && i2 <= i + 5))
.First();

C# program that replaces even numbers with the word even

I am trying to write a program that replaces even numbers with the word "EVEN". So far, I have:
List<int> num = new List<int>();
for (int num1 = 0; num < 101; num++)
{
num.add(num1)
}
foreach(int n in num1)
{
if (n/3)
{
num.Replace("EVEN")
}
}
Is this close or am I far off?
var list = new List<string>();
for (int i = 0; i < 101; i++)
{
string value = (i % 2 == 0) ? "EVEN" : i.ToString();
list.Add(value);
}
In one line:
var list = Enumerable.Range(1, 100).Select(i => (i % 2 == 0) ? "EVEN" : i.ToString()).ToList();
not sure why you are trying to do this, but this should work..:
var num = new List<string>();
for (int n = 0; n < 101; n++)
{
num.Add(n % 2 == 0 ? "EVEN" : n.ToString());
}
Solutions have been provided for constructing a list of strings where each element of the list will be the number if it's odd or "EVEN" if it's even.
If, for some reason, you actually need to take an existing list of int and perform such a replacement, make sure you understand a fundamental problem: You can't insert the string "EVEN" into a strongly-typed list of int.
If you do start with a List<int>, you'll have to iterate over it and insert the results into a new List<string>, replacing even numbers with "EVEN" as per #CMP or #Can Gencer's answers.
Enumerable.Range(1, 100)
.Select(n => (n % 2) == 0 ? "EVEN" : n.ToString())
.ToList();
The list of numbers probably should be string if you want to replace with "even".
List<string> numbers = new List<string>();
numbers.Add("1");
numbers.Add("2");
numbers.Add("3");
for (int i = 0; i < numbers.Count; i++)
{
int n = 0;
bool success = int.TryParse(numbers[i], out n);
if (success && n % 2 == 0)
{
numbers[i] = "Even";
}
}
//Output Test Results
foreach (string number in numbers)
{
Console.WriteLine(number);
}

Categories

Resources