.NET C# Logic Function, recurrent function - c#

I have some string in format like that
XXXX-XXXX-X_X_
All "_" should be replaced with Letters and numberst to prodce sth like that:
XXXX-XXXX-XAXA
XXXX-XXXX-XAXB
XXXX-XXXX-XAXC
XXXX-XXXX-XAXD
XXXX-XXXX-XAXE
XXXX-XXXX-XAXF
XXXX-XXXX-XAXG
(...)
XXXX-XXXX-XZX8
XXXX-XXXX-XZX9
XXXX-XXXX-X0XA
(...)
XXXX-XXXX-X2XA
XXXX-XXXX-X2XB
I know hoe to make it with one "_".
string alphaLetters = "ABCDEFGHIJKLMNOPQRSTUWXYZ0123456789ABCDEF";
foreach (char letter in alphaLetters.ToCharArray())
{
Numbers.Add(number.Replace('_', letter)));
}
I want this code to be working with unknown number of "_".
Can you help?

IMHO it must be recursive. (Note: that does not mean it must use recursive method call, although I used recursive call in the following code, it can be easily converted to internal recursion stack. )
public static void RunSnippet()
{
var r = new List<string>();
Replace("asd_asd_asd_".ToCharArray(), 0, r);
foreach(var s in r) { Console.WriteLine(s); }
}
public static char[] possibilities = new char[] { 'A', 'B', 'C' };
public static void Replace(char[] chars, int startIndex, IList<string> result)
{
for (int i = startIndex; i < chars.Length; i++)
{
if (chars[i] != '_')
{
continue;
}
// we found first '_'
for (int j = 0; j < possibilities.Length; j++)
{
chars[i] = possibilities[j];
Replace(chars, i + 1, result);
}
chars[i] = '_'; // take back what we replaced
return; //we're done here
}
// we didn't find any '_', so all were replaced and we have result:
result.Add(new string(chars));
}

Try this one:
var alphaIndexes = new List<int>();
string alphaLetters = "ABCDEFGHIJKLMNOPQRSTUWXYZ0123456789ABCDEF";
for(int n = 0; n<Numbers.Count; n++) {
char[] numberLetters = Numbers[n].ToCharArray();
int position = 0;
for(int i = numberLetters.Length - 1; i>=0; i--) {
if(numberLetters[i] == '_') {
int alphaIndex = 0;
if(alphaIndexes.Count <= position)
alphaIndexes.Add(0);
else {
alphaIndex = alphaIndexes[position];
}
numberLetters[i] = alphaLetters[alphaIndex];
position++;
}
}
if(alphaIndexes.Count > 0) {
alphaIndexes[0]++;
for(int j = 0; j < alphaIndexes.Count; j++) {
if(alphaIndexes[j] >= alphaLetters.Length) {
alphaIndexes[j] = 0;
if (j < alphaIndexes.Count)
alphaIndexes[j+1]++;
}
}
}
Numbers[n] = new String(numberLetters);
Numbers[n].Dump();
}

Related

Are there any functions similar to .Contains that will work with "char"?

So I am creating a hangman-type game in C# and I want the user's input to be recognized as a variable. So I am trying to use this variable(user input) and see if it is found in the word chosen. However, there is no .Contain function that works with "char" variables. Is there any way to make this work? (The part in asterisks is the portion I want to add this code to)
using System;
namespace Hangman
{
class WordChoice
{
static void Main(string[] args)
{
Random rand = new Random();
int numword = rand.Next(2);
string word = "";
char[] ltrlist = { ' ' };
char ltrchce = ' ';
int strlength = 0;
**void ltrcheck()
{
if
{
Console.WriteLine("Great you got a letter");
}
}**
if (numword == 1)
{
word = "Shrek";
strlength = word.Length;
ltrlist = new char[strlength];
for (int a = 0; a < strlength; a++)
{
ltrlist[a] = word[a];
}
}
if (numword == 2)
{
word = "Venom";
strlength = word.Length;
ltrlist = new char[strlength];
for (int a = 0; a < strlength; a++)
{
ltrlist[a] = word[a];
}
}
if (numword == 3)
{
word = "Avengers";
strlength = word.Length;
ltrlist = new char[strlength];
for (int a = 0; a < strlength; a++)
{
ltrlist[a] = word[a];
}
}
if (numword == 4)
{
word = "Inception";
strlength = word.Length;
ltrlist = new char[strlength];
for (int a = 0; a < strlength; a++)
{
ltrlist[a] = word[a];
}
}
if (numword == 5)
{
word = "Batman";
strlength = word.Length;
ltrlist = new char[strlength];
for (int a = 0; a < strlength; a++)
{
ltrlist[a] = word[a];
}
}
string undscr = "";
for (int i = 0; i < strlength; i++)
{
undscr = undscr + " _";
}
Console.WriteLine(undscr);
Console.WriteLine("");
Console.WriteLine("Pick a letter");
string ltrchcestr = Console.ReadLine();
ltrchce = Convert.ToChar(ltrchcestr);
ltrcheck();
}
}
}
You can do a function like this
static bool Contains(IEnumerable < char > items, char letter)
=> return items?.Any(c => c == letter) == true;
or just create a typeExtension, for Project wide use:
public static class CharExtensions {
public static bool Contains(this IEnumerable<char> items, char letter ){
return items?.Any(c => c == letter) == true;
}
}
this test will now work:
var chars = new []{'a','b','c'};
Console.WriteLine(chars.Contains('m'));
Console.WriteLine(chars.Contains('b'));

How to reduce the memory usage of a C# console application project?

This is program consumes 36.50 MB of memory but I want it to be less than 32 MB
public static void CreateText(string text)
{
if (Convert.ToInt32(text.Length) <= 80)
{
int n;
string str = "";
string count = "";
char[] mas = text.ToCharArray();
for (int i = 0; i < Convert.ToInt32(mas.Length); i++)
{
if (int.TryParse(mas[i].ToString(), out n))
{
count += mas[i].ToString();
}
else
{
if (String.IsNullOrEmpty(count))
{
str += mas[i].ToString();
}
else
{
for (int j = 0; j < Convert.ToInt32(count); j++)
{
str += mas[i].ToString();
}
count = "";
}
}
}
Console.WriteLine(str);
} else {
Console.WriteLine("Error");
}
}
To reduce memory footprint you need to get read of temporary string objects generated by applying operation += against a string. String is immutable object in C#, so += creates new string. StringBuilder is mutable, so use it instead of string. You also need to have count as an int, not string or StringBuilder.
public static void CreateText(string mas)
{
if (mas.Length <= 80)
{
StringBuilder str;
int count;
for (int i = 0; i < mas.Length; i++)
{
if (mas[i] >= '0' && mas[i] <= '9')
count = count * 10 + mas[i] - '0';
else
{
if (count == 0)
str.Append(mas[i]);
else
{
for (int j = 0; j < count; j++)
str.Append(mas[i]);
count = 0;
}
}
}
Console.WriteLine(str.ToString());
}
else
Console.WriteLine("Error");
}
This probably isn't possible. Most of the RAM in a 36MB program is just core framework libraries. 36MB is nothing.
But I do see some potential improvements, the biggest of which are maintaining count as an integer rather than a string and using a string constructor and StringBuilder instead of appending to a string all the time:
public static void CreateText(string text)
{
if (text != null && text.Length <= 80)
{
int n; int count = 0;
StringBuilder result = new StringBuilder();
char[] mas = text.ToCharArray();
foreach(char c in text)
{
if (int.TryParse(c.ToString(), out n))
{
count = (count * 10) + n;
}
else
{
if (count == 0)
{
result.Append(c);
}
else
{
result.Append(new string(c, count));
count = 0;
}
}
}
Console.WriteLine(result.ToString());
} else {
Console.WriteLine("Error");
}
}
There is a potential bug there if you want to be able to explicitly set 0 repetition in the input string. If that's the case, we'll need something that is slightly less efficient, but should still have a big improvement over the original:
public static void CreateText(string text)
{
if (text != null && text.Length <= 80)
{
int n; int count = -1;
StringBuilder result = new StringBuilder();
char[] mas = text.ToCharArray();
foreach(char c in text)
{
if (int.TryParse(c.ToString(), out n))
{
if (count == -1) count = 0;
count = (count * 10) + n;
}
else
{
if (count == -1)
{
result.Append(c);
}
else
{
result.Append(new string(c, count));
count = -1;
}
}
}
Console.WriteLine(result.ToString());
} else {
Console.WriteLine("Error");
}
}
Try this:
public static void CreateText(string text)
{
if (text.Length <= 80)
{
var str = new StringBuilder();
var count = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
int n;
if (int.TryParse(text[i].ToString(), out n))
{
count.Append(text[i]);
}
else
{
if (String.IsNullOrEmpty(count.ToString()))
{
str.Append(text[i]);
}
else
{
for (int j = 0; j < Convert.ToInt32(count.ToString()); j++)
{
str.Append(text[i].ToString());
}
count.Clear();
}
}
}
Console.WriteLine(str);
}
else
{
Console.WriteLine("Error");
}
}
What I did was:
Remove the string contetantions (since they are immutable) and used a StringBuilder instead.
No need to convert to a char[] since your can treat a String as one (it implements the indexer)
Moved the n closed to used to it's only allocated if needed

Index Of Longest Run C#

I am trying to solve this question:
Write a function that finds the zero-based index of the longest run in a string. A run is a consecutive sequence of the same character. If there is more than one run with the same length, return the index of the first one.
For example, IndexOfLongestRun("abbcccddddcccbba") should return 6 as the longest run is dddd and it first appears on index 6.
Following what i have done:
private static int IndexOfLongestRun(string str)
{
char[] array1 = str.ToCharArray();
//Array.Sort(array1);
Comparer comparer = new Comparer();
int counter =1;
int maxCount = 0;
int idenxOf = 0;
for (int i =0; i<array1.Length-1 ; i++)
{
if (comparer.Compare(array1[i],array1[i+1]) == 0)
{
counter++;
}
else {
if(maxCount < counter)
{
maxCount = counter;
idenxOf = i - counter + 1;
}
counter = 1;
}
}
return idenxOf ;
}
}
public class Comparer : IComparer<char>
{
public int Compare(char firstChar, char nextChar)
{
return firstChar.CompareTo(nextChar);
}
}
The problem is that when i get to the last index for example "abbccaaaaaaaaaa"
which is a in this case, and when i=14 (taking this string as example) and when i<array1.Length-1 statment is false, the for loop jumps directrly to return indexOf; and return the wrong index, I am trying to find out how to push the forloop to continue the implementation so idenxOf could be changed to the right index. Any help please?
You could check whether a new best score is achieved for each iteration when current == previous. Minimally slower, but it allows you to write shorter code by omitting an extra check after the loop:
int IndexOfLongestRun(string input)
{
int bestIndex = 0, bestScore = 0, currIndex = 0;
for (var i = 0; i < input.Length; ++i)
{
if (input[i] == input[currIndex])
{
if (bestScore < i - currIndex)
{
bestIndex = currIndex;
bestScore = i - currIndex;
}
}
else
{
currIndex = i;
}
}
return bestIndex;
}
Promote the loop variable i to method scope and repeat the conditional block if (maxCount < counter) { ... } right after the loop exit. Thus, it executes one more time after the loop completes
private static int IndexOfLongestRun(string str)
{
char[] array1 = str.ToCharArray();
//Array.Sort(array1);
Comparer comparer = new Comparer();
int counter = 1;
int maxCount = 0;
int idenxOf = 0;
int i;
for (i = 0; i < array1.Length - 1; i++)
{
if (comparer.Compare(array1[i], array1[i + 1]) == 0)
{
counter++;
}
else
{
if (maxCount < counter)
{
maxCount = counter;
idenxOf = i - counter + 1;
}
counter = 1;
}
}
if (maxCount < counter)
{
maxCount = counter;
idenxOf = i - counter + 1;
}
return idenxOf;
}
As usual late, but joining the party. A natural classic algorithm:
static int IndexOfLongestRun(string input)
{
int longestRunStart = -1, longestRunLength = 0;
for (int i = 0; i < input.Length; )
{
var runValue = input[i];
int runStart = i;
while (++i < input.Length && input[i] == runValue) { }
int runLength = i - runStart;
if (longestRunLength < runLength)
{
longestRunStart = runStart;
longestRunLength = runLength;
}
}
return longestRunStart;
}
At the end you have both longest run index and length.
public static int IndexOfLongestRun(string str)
{
var longestRunCount = 1;
var longestRunIndex = 0;
var isNew = false;
var dic = new Dictionary<int, int>();
for (var i = 0; i < str.Length - 1; i++)
{
if (str[i] == str[i + 1])
{
if (isNew) longestRunIndex = i;
longestRunCount++;
isNew = false;
}
else
{
isNew = true;
dic.Add(longestRunIndex, longestRunCount);
longestRunIndex = 0;
longestRunCount = 1;
}
}
return dic.OrderByDescending(x => x.Value).First().Key;
}
This will return -1 if the string is empty and you have the flexibility of returning the index and the count depending on your specification.
string myStr = "aaaabbbbccccccccccccdeeeeeeeee";
var longestIndexStart = -1;
var longestCount = 0;
var currentCount = 1;
var currentIndexStart = 0;
for (var idx = 1; idx < myStr.Length; idx++)
{
if (myStr[idx] == myStr[currentIndexStart])
currentCount++;
else
{
if (currentCount > longestCount)
{
longestIndexStart = currentIndexStart;
longestCount = currentCount;
}
currentIndexStart = idx;
currentCount = 1;
}
}
return longestIndexStart;
The accepted answer from Kvam works great for small strings, but as the length approaches 100,000 characters (and perhaps this isn't needed), its efficiency wains.
public static int IndexOfLongestRun(string str)
{
Dictionary<string, int> letterCount = new Dictionary<string, int>();
for (int i = 0; i < str.Length; i++)
{
string c = str.Substring(i, 1);
if (letterCount.ContainsKey(c))
letterCount[c]++;
else
letterCount.Add(c, 1);
}
return letterCount.Values.Max();
}
This solution is twice as fast as Kvam's with large strings. There are, perhaps, other optimizations.

csharp method that choose every second character from the word

I need a method that returns every other character in a string starting with the first character. For example, a method call with ("Java-language") returns "Jv-agae."
private static void NewMethod(string word)
{
// here comes the code
}
var str = "Java-language";
var xx = new string(str.Where((ch, index) => index % 2 == 0).ToArray());
Console.WriteLine(xx);
Or this one:
var xx = string.Join<char>("", str.Where((ch, index) => (index & 1) == 0));
probably little different then everybody else: :-)
protected static IEnumerable<char> EverySecondChar(string word)
{
for(int i = 0; i < word.Length; i += 2)
yield return word[i];
}
string result = new string(EverySecondChar("Java-language").ToArray());
Here is my suggestion for you:
private string TakeEverySecondChar(string input)
{
var result = string.Empty;
for (int i = 0; i < input.Length; i+=2)
{
result += input.Substring(i, 1);
}
return result;
}
Console.Clear();
string Lang = "Java-language";
string[] LangArr = new string[Lang.Length];
char LangChar;
for (int i = 0; i < Lang.Length; i++)
{
LangChar = Lang[i];
LangArr[i] = LangChar.ToString();
}
for (int i = 0; i < LangArr.Length; i++)
{
Console.Write(LangArr[i]);
i++;
}
Console.ReadLine();
public String strip2ndchar(string text)
{
string final="";
int i = 0;
foreach (char a in text.ToCharArray())
{
if (i % 2 == 0)
final += a;
i++;
}
return final;
}

How do I remove duplicates from a C# array?

I have been working with a string[] array in C# that gets returned from a function call. I could possibly cast to a Generic collection, but I was wondering if there was a better way to do it, possibly by using a temp array.
What is the best way to remove duplicates from a C# array?
You could possibly use a LINQ query to do this:
int[] s = { 1, 2, 3, 3, 4};
int[] q = s.Distinct().ToArray();
Here is the HashSet<string> approach:
public static string[] RemoveDuplicates(string[] s)
{
HashSet<string> set = new HashSet<string>(s);
string[] result = new string[set.Count];
set.CopyTo(result);
return result;
}
Unfortunately this solution also requires .NET framework 3.5 or later as HashSet was not added until that version. You could also use array.Distinct(), which is a feature of LINQ.
The following tested and working code will remove duplicates from an array. You must include the System.Collections namespace.
string[] sArray = {"a", "b", "b", "c", "c", "d", "e", "f", "f"};
var sList = new ArrayList();
for (int i = 0; i < sArray.Length; i++) {
if (sList.Contains(sArray[i]) == false) {
sList.Add(sArray[i]);
}
}
var sNew = sList.ToArray();
for (int i = 0; i < sNew.Length; i++) {
Console.Write(sNew[i]);
}
You could wrap this up into a function if you wanted to.
If you needed to sort it, then you could implement a sort that also removes duplicates.
Kills two birds with one stone, then.
This might depend on how much you want to engineer the solution - if the array is never going to be that big and you don't care about sorting the list you might want to try something similar to the following:
public string[] RemoveDuplicates(string[] myList) {
System.Collections.ArrayList newList = new System.Collections.ArrayList();
foreach (string str in myList)
if (!newList.Contains(str))
newList.Add(str);
return (string[])newList.ToArray(typeof(string));
}
List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
if (!myStringList.Contains(s))
{
myStringList.Add(s);
}
}
This is O(n^2), which won't matter for a short list which is going to be stuffed into a combo, but could be rapidly be a problem on a big collection.
-- This is Interview Question asked every time. Now i done its coding.
static void Main(string[] args)
{
int[] array = new int[] { 4, 8, 4, 1, 1, 4, 8 };
int numDups = 0, prevIndex = 0;
for (int i = 0; i < array.Length; i++)
{
bool foundDup = false;
for (int j = 0; j < i; j++)
{
if (array[i] == array[j])
{
foundDup = true;
numDups++; // Increment means Count for Duplicate found in array.
break;
}
}
if (foundDup == false)
{
array[prevIndex] = array[i];
prevIndex++;
}
}
// Just Duplicate records replce by zero.
for (int k = 1; k <= numDups; k++)
{
array[array.Length - k] = '\0';
}
Console.WriteLine("Console program for Remove duplicates from array.");
Console.Read();
}
Here is a O(n*n) approach that uses O(1) space.
void removeDuplicates(char* strIn)
{
int numDups = 0, prevIndex = 0;
if(NULL != strIn && *strIn != '\0')
{
int len = strlen(strIn);
for(int i = 0; i < len; i++)
{
bool foundDup = false;
for(int j = 0; j < i; j++)
{
if(strIn[j] == strIn[i])
{
foundDup = true;
numDups++;
break;
}
}
if(foundDup == false)
{
strIn[prevIndex] = strIn[i];
prevIndex++;
}
}
strIn[len-numDups] = '\0';
}
}
The hash/linq approaches above are what you would generally use in real life. However in interviews they usually want to put some constraints e.g. constant space which rules out hash or no internal api - which rules out using LINQ.
protected void Page_Load(object sender, EventArgs e)
{
string a = "a;b;c;d;e;v";
string[] b = a.Split(';');
string[] c = b.Distinct().ToArray();
if (b.Length != c.Length)
{
for (int i = 0; i < b.Length; i++)
{
try
{
if (b[i].ToString() != c[i].ToString())
{
Response.Write("Found duplicate " + b[i].ToString());
return;
}
}
catch (Exception ex)
{
Response.Write("Found duplicate " + b[i].ToString());
return;
}
}
}
else
{
Response.Write("No duplicate ");
}
}
Add all the strings to a dictionary and get the Keys property afterwards. This will produce each unique string, but not necessarily in the same order your original input had them in.
If you require the end result to have the same order as the original input, when you consider the first occurance of each string, use the following algorithm instead:
Have a list (final output) and a dictionary (to check for duplicates)
For each string in the input, check if it exists in the dictionary already
If not, add it both to the dictionary and to the list
At the end, the list contains the first occurance of each unique string.
Make sure you consider things like culture and such when constructing your dictionary, to make sure you handle duplicates with accented letters correctly.
The following piece of code attempts to remove duplicates from an ArrayList though this is not an optimal solution. I was asked this question during an interview to remove duplicates through recursion, and without using a second/temp arraylist:
private void RemoveDuplicate()
{
ArrayList dataArray = new ArrayList(5);
dataArray.Add("1");
dataArray.Add("1");
dataArray.Add("6");
dataArray.Add("6");
dataArray.Add("6");
dataArray.Add("3");
dataArray.Add("6");
dataArray.Add("4");
dataArray.Add("5");
dataArray.Add("4");
dataArray.Add("1");
dataArray.Sort();
GetDistinctArrayList(dataArray, 0);
}
private void GetDistinctArrayList(ArrayList arr, int idx)
{
int count = 0;
if (idx >= arr.Count) return;
string val = arr[idx].ToString();
foreach (String s in arr)
{
if (s.Equals(arr[idx]))
{
count++;
}
}
if (count > 1)
{
arr.Remove(val);
GetDistinctArrayList(arr, idx);
}
else
{
idx += 1;
GetDistinctArrayList(arr, idx);
}
}
Simple solution:
using System.Linq;
...
public static int[] Distinct(int[] handles)
{
return handles.ToList().Distinct().ToArray();
}
Maybe hashset which do not store duplicate elements and silently ignore requests to add
duplicates.
static void Main()
{
string textWithDuplicates = "aaabbcccggg";
Console.WriteLine(textWithDuplicates.Count());
var letters = new HashSet<char>(textWithDuplicates);
Console.WriteLine(letters.Count());
foreach (char c in letters) Console.Write(c);
Console.WriteLine("");
int[] array = new int[] { 12, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 };
Console.WriteLine(array.Count());
var distinctArray = new HashSet<int>(array);
Console.WriteLine(distinctArray.Count());
foreach (int i in distinctArray) Console.Write(i + ",");
}
NOTE : NOT tested!
string[] test(string[] myStringArray)
{
List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
if (!myStringList.Contains(s))
{
myStringList.Add(s);
}
}
return myStringList.ToString();
}
Might do what you need...
EDIT Argh!!! beaten to it by rob by under a minute!
Tested the below & it works. What's cool is that it does a culture sensitive search too
class RemoveDuplicatesInString
{
public static String RemoveDups(String origString)
{
String outString = null;
int readIndex = 0;
CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;
if(String.IsNullOrEmpty(origString))
{
return outString;
}
foreach (var ch in origString)
{
if (readIndex == 0)
{
outString = String.Concat(ch);
readIndex++;
continue;
}
if (ci.IndexOf(origString, ch.ToString().ToLower(), 0, readIndex) == -1)
{
//Unique char as this char wasn't found earlier.
outString = String.Concat(outString, ch);
}
readIndex++;
}
return outString;
}
static void Main(string[] args)
{
String inputString = "aAbcefc";
String outputString;
outputString = RemoveDups(inputString);
Console.WriteLine(outputString);
}
}
--AptSenSDET
This code 100% remove duplicate values from an array[as I used a[i]].....You can convert it in any OO language..... :)
for(int i=0;i<size;i++)
{
for(int j=i+1;j<size;j++)
{
if(a[i] == a[j])
{
for(int k=j;k<size;k++)
{
a[k]=a[k+1];
}
j--;
size--;
}
}
}
Generic Extension method :
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
HashSet<TSource> set = new HashSet<TSource>(comparer);
foreach (TSource item in source)
{
if (set.Add(item))
{
yield return item;
}
}
}
you can using This code when work with an ArrayList
ArrayList arrayList;
//Add some Members :)
arrayList.Add("ali");
arrayList.Add("hadi");
arrayList.Add("ali");
//Remove duplicates from array
for (int i = 0; i < arrayList.Count; i++)
{
for (int j = i + 1; j < arrayList.Count ; j++)
if (arrayList[i].ToString() == arrayList[j].ToString())
arrayList.Remove(arrayList[j]);
Below is an simple logic in java you traverse elements of array twice and if you see any same element you assign zero to it plus you don't touch the index of element you are comparing.
import java.util.*;
class removeDuplicate{
int [] y ;
public removeDuplicate(int[] array){
y=array;
for(int b=0;b<y.length;b++){
int temp = y[b];
for(int v=0;v<y.length;v++){
if( b!=v && temp==y[v]){
y[v]=0;
}
}
}
}
public static int RemoveDuplicates(ref int[] array)
{
int size = array.Length;
// if 0 or 1, return 0 or 1:
if (size < 2) {
return size;
}
int current = 0;
for (int candidate = 1; candidate < size; ++candidate) {
if (array[current] != array[candidate]) {
array[++current] = array[candidate];
}
}
// index to count conversion:
return ++current;
}
The best way? Hard to say, the HashSet approach looks fast,
but (depending on the data) using a sort algorithm (CountSort ?)
can be much faster.
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
Random r = new Random(0); int[] a, b = new int[1000000];
for (int i = b.Length - 1; i >= 0; i--) b[i] = r.Next(b.Length);
a = new int[b.Length]; Array.Copy(b, a, b.Length);
a = dedup0(a); Console.WriteLine(a.Length);
a = new int[b.Length]; Array.Copy(b, a, b.Length);
var w = System.Diagnostics.Stopwatch.StartNew();
a = dedup0(a); Console.WriteLine(w.Elapsed); Console.Read();
}
static int[] dedup0(int[] a) // 48 ms
{
return new HashSet<int>(a).ToArray();
}
static int[] dedup1(int[] a) // 68 ms
{
Array.Sort(a); int i = 0, j = 1, k = a.Length; if (k < 2) return a;
while (j < k) if (a[i] == a[j]) j++; else a[++i] = a[j++];
Array.Resize(ref a, i + 1); return a;
}
static int[] dedup2(int[] a) // 8 ms
{
var b = new byte[a.Length]; int c = 0;
for (int i = 0; i < a.Length; i++)
if (b[a[i]] == 0) { b[a[i]] = 1; c++; }
a = new int[c];
for (int j = 0, i = 0; i < b.Length; i++) if (b[i] > 0) a[j++] = i;
return a;
}
}
Almost branch free. How? Debug mode, Step Into (F11) with a small array: {1,3,1,1,0}
static int[] dedupf(int[] a) // 4 ms
{
if (a.Length < 2) return a;
var b = new byte[a.Length]; int c = 0, bi, ai, i, j;
for (i = 0; i < a.Length; i++)
{ ai = a[i]; bi = 1 ^ b[ai]; b[ai] |= (byte)bi; c += bi; }
a = new int[c]; i = 0; while (b[i] == 0) i++; a[0] = i++;
for (j = 0; i < b.Length; i++) a[j += bi = b[i]] += bi * i; return a;
}
A solution with two nested loops might take some time,
especially for larger arrays.
static int[] dedup(int[] a)
{
int i, j, k = a.Length - 1;
for (i = 0; i < k; i++)
for (j = i + 1; j <= k; j++) if (a[i] == a[j]) a[j--] = a[k--];
Array.Resize(ref a, k + 1); return a;
}
private static string[] distinct(string[] inputArray)
{
bool alreadyExists;
string[] outputArray = new string[] {};
for (int i = 0; i < inputArray.Length; i++)
{
alreadyExists = false;
for (int j = 0; j < outputArray.Length; j++)
{
if (inputArray[i] == outputArray[j])
alreadyExists = true;
}
if (alreadyExists==false)
{
Array.Resize<string>(ref outputArray, outputArray.Length + 1);
outputArray[outputArray.Length-1] = inputArray[i];
}
}
return outputArray;
}
int size = a.Length;
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (a[i] == a[j])
{
for (int k = j; k < size; k++)
{
if (k != size - 1)
{
int temp = a[k];
a[k] = a[k + 1];
a[k + 1] = temp;
}
}
j--;
size--;
}
}
}
So I was doing an interview session and got the same question to sort and distinct
static void Sort()
{
try
{
int[] number = new int[Convert.ToInt32(Console.ReadLine())];
for (int i = 0; i < number.Length; i++)
{
number[i] = Convert.ToInt32(Console.ReadLine());
}
Array.Sort(number);
int[] num = number.Distinct().ToArray();
for (int i = 0; i < num.Length; i++)
{
Console.WriteLine(num[i]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
List<int> listofint1 = new List<int> { 4, 8, 4, 1, 1, 4, 8 };
List<int> updatedlist= removeduplicate(listofint1);
foreach(int num in updatedlist)
Console.WriteLine(num);
}
public static List<int> removeduplicate(List<int> listofint)
{
List<int> listofintwithoutduplicate= new List<int>();
foreach(var num in listofint)
{
if(!listofintwithoutduplicate.Any(p=>p==num))
{
listofintwithoutduplicate.Add(num);
}
}
return listofintwithoutduplicate;
}
}
}
strINvalues = "1,1,2,2,3,3,4,4";
strINvalues = string.Join(",", strINvalues .Split(',').Distinct().ToArray());
Debug.Writeline(strINvalues);
Kkk Not sure if this is witchcraft or just beautiful code
1 strINvalues .Split(',').Distinct().ToArray()
2 string.Join(",", XXX);
1 Splitting the array and using Distinct [LINQ] to remove duplicates
2 Joining it back without the duplicates.
Sorry I never read the text on StackOverFlow just the code. it make more sense than the text ;)
Removing duplicate and ignore case sensitive using Distinct & StringComparer.InvariantCultureIgnoreCase
string[] array = new string[] { "A", "a", "b", "B", "a", "C", "c", "C", "A", "1" };
var r = array.Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
Console.WriteLine(r.Count); // return 4 items
Find answer below.
class Program
{
static void Main(string[] args)
{
var nums = new int[] { 1, 4, 3, 3, 3, 5, 5, 7, 7, 7, 7, 9, 9, 9 };
var result = removeDuplicates(nums);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
static int[] removeDuplicates(int[] nums)
{
nums = nums.ToList().OrderBy(c => c).ToArray();
int j = 1;
int i = 0;
int stop = 0;
while (j < nums.Length)
{
if (nums[i] != nums[j])
{
nums[i + 1] = nums[j];
stop = i + 2;
i++;
}
j++;
}
nums = nums.Take(stop).ToArray();
return nums;
}
}
Just a bit of contribution based on a test i just solved, maybe helpful and open to improvement by other top contributors here.
Here are the things i did:
I used OrderBy which allows me order or sort the items from smallest to the highest using LINQ
I then convert it to back to an array and then re-assign it back to the primary datasource
So i then initialize j which is my right hand side of the array to be 1 and i which is my left hand side of the array to be 0, i also initialize where i would i to stop to be 0.
I used a while loop to increment through the array by going from one position to the other left to right, for each increment the stop position is the current value of i + 2 which i will use later to truncate the duplicates from the array.
I then increment by moving from left to right from the if statement and from right to right outside of the if statement until i iterate through the entire values of the array.
I then pick from the first element to the stop position which becomes the last i index plus 2. that way i am able to remove all the duplicate items from the int array. which is then reassigned.

Categories