C# Filling Third Array With Items From First Two. Leaving Out Duplicates - c#

Looking for some help in figuring this out. I have two arrays of names. What I need to do is bubble sort them (which I have done, see code below), and populate the third array with the values from the first two array, leaving out duplicates, and not sorting the third array. Below is my example code, which completely works for what I am doing, except I need to use a loop to fill in the third array (logical exercise).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MergeArray
{
class Program
{
static void Main(string[] args)
{
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = new string[names1.Length + names2.Length];
string temp;
foreach (string i in names1)
{
for (int j = 0; j < names1.Length - 1; j++)
{
if (String.Compare(names1[j], names1[j+1]) > 0)
{
temp = names1[j];
names1[j] = names1[j + 1];
names1[j + 1] = temp;
}
}
}
foreach (string i in names2)
{
for (int j = 0; j < names2.Length - 1; j++)
{
if (String.Compare(names2[j], names2[j + 1]) > 0)
{
temp = names2[j];
names2[j] = names2[j + 1];
names2[j + 1] = temp;
}
}
}
names1.CopyTo(names3, 0);
names2.CopyTo(names3, names1.Length);
Console.WriteLine(String.Join(Environment.NewLine, names3.Distinct().ToArray()));
Console.ReadLine();
}
}
}
In the end, this code does what I need it to do, which is populate the third array with "Bart, Betty, Bill, Bob, John, Patty, Sandy, Andy, Chris, Walter". It doesn't fill in the duplicate "Bill" and it just adds the two arrays together, without sorting the third (which is what I need to do). What I need help with is turning the part where I fill in the third array into a loop instead of the:
names1.CopyTo(names3, 0);
names2.CopyTo(names3, names1.Length);
Console.WriteLine(String.Join(Environment.NewLine, names3.Distinct().ToArray()));
Please help me out to understand what I need to do here.

Assuming that your bubble sort successfully sorts you elements, you can use a modified merge operation to put together the final array. Basically a merge takes two sorted arrays and puts them together by comparing the "top" elements of each array and moving that one to the composite array.
You would just have to check for duplicate while you are doing this. And since your arrays are both sorted, all duplicates will clump together into groups, so you would only need to keep track of the most recent duplicate.
Something like this (which is very verbose and heavily commented) could work:
public static string[] MergeNoDuplicates(string[] left, string[] right)
{
var mergedArray = new string[left.Length + right.Length];
//since the arrays are sorted, we only need to keep track of the most recent duplicate
string duplicateChecker = null;
int mergeIndex = 0;
int l = 0; //index for left array
int r = 0; //index for right array
//while there are more element in at least one of the two arrays
bool leftHasElements = l < left.Length;
bool rightHasElements = r < right.Length;
while (leftHasElements && rightHasElements)
{
string leftString = left[l];
string rightString = right[r];
int comparisonResult = leftString.CompareTo(rightString);
if (comparisonResult < 0) //left string comes before right string
{
//not a duplicate
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
//regardless of whether it's a duplicate move onto the next element
l++;
}
else if (comparisonResult > 0) //right string comes before left
{
if (rightString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = rightString;
mergeIndex++;
duplicateChecker = rightString;
}
r++;
}
else //comparisonResult by default == 0
{
//since they are the same string, just insert one (if needed), but increment both arrays
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
l++;
r++;
}
leftHasElements = l < left.Length;
rightHasElements = r < right.Length;
}
//now at least one of the arrays is empty, so add all of the remaining
//non-duplicate elements of the other to the array
//if either is false, the loop won't execute in the first place
while (leftHasElements)
{
string leftString = left[l];
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
l++;
leftHasElements = l < left.Length;
}
while (rightHasElements)
{
string rightString = right[r];
if (rightString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = rightString;
mergeIndex++;
duplicateChecker = rightString;
}
r++;
rightHasElements = r < right.Length;
}
//now remove null elements (if needed) and return
//alternatively, just use LINQ's TakeWhile and ToArray
if (mergeIndex == mergedArray.Length)
return mergedArray;
var returnedArray = new string[mergeIndex];
Array.Copy(mergedArray, returnedArray, mergeIndex);
return returnedArray;
}
Demo

Ohh the power of linq!
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = names1.Union(names2).Distinct().ToArray();

As ryanyuyu suggested, use a modified merge operation.
This will come after you have already sorted them.
int m = 0;
int n = 0;
while ((m < names1.Count) && (n < names1.Count))
{
int comparison = String.Compare(names1[m], names2[n]);
if (comparison < 0) // names1[m] is before names2[n]
{
names3.Add(names1[m]);
m = m + 1;
}
else if (comparison > 1) //names2[n] is before names1[m]
{
names3.Add(names2[n]);
n = n + 1;
}
else //names1[m] is equal to names2[n], only add one.
{
names3.Add(names1[m]);
m = m + 1;
n = n + 1;
}
}
//either names1 or names2 ran out of entries. fill names3 with whatever is left
while (m < names1.Count)
{
names3.Add(names1[m]);
m = m + 1;
}
while (n < names2.Count)
{
names3.Add(names2[n]);
n = n + 1;
}
If it is possible the original arrays might themselves contain duplicates, you can track which values have been added using a HashSet.
List<string> names1 = new List<string>();
List<string> names2 = new List<string>();
List<string> names3 = new List<string>();
var included = new HashSet<string>();
int m = 0;
int n = 0;
while ((m < names1.Count) && (n < names1.Count))
{
int comparison = String.Compare(names1[m], names2[n]);
if (comparison < 0)
{
if(included.Add(names1[m]))
{
names3.Add(names1[m]);
}
m = m + 1;
}
else if (comparison > 1)
{
if (included.Add(names2[n]))
{
names3.Add(names2[n]);
}
n = n + 1;
}
else
{
names3.Add(names1[m]);
m = m + 1;
n = n + 1;
}
}
while (m < names1.Count)
{
if (included.Add(names1[m]))
{
names3.Add(names1[m]);
}
m = m + 1;
}
while (n < names2.Count)
{
if (included.Add(names2[n]))
{
names3.Add(names2[n]);
}
n = n + 1;
}
Of course at this point you might as well make names3 a HashSet and skip the extra checks. The only benefit we have for keeping included separate is that names3 retains the sorted order. There is no guarantee this will be true if names3 itself were the HashSet and you did names3.ToArray() at the end.

Why not:
List<string> names = new List<string>();
names.AddRange(names1);
names.AddRange(names2);
names.Sort();
string[] names3 = names.Distinct().ToArray();

You could just use .Union:
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = names1.Union(names2).ToArray();

I'd suggest copying to a List<>, using "Distinct":
Use "AddRange()" to add the second array.
Use "Distinct()" to eliminate the duplicates,
Finally, convert the list back to an array.
EXAMPLE:
List<string> myList = myArray.Cast<string>().ToList();
myList.AddRange(mySecondArray);
string[] myNewArray = myList.Distinct().toArray();

I would use a loop like this:
int names1I = 0;
int names2I = 0;
for(int i = 0; names1I < names1.Length && names2I < names2.Length; i++)
{
while(names1I < names1.Length && names3.Contains(names1[names1I]))
names1I++;
while(names2I < names2.Length && names3.Contains(names2[names2I]))
names2I++;
if(names1I == names1.Length) //if you have already reached the end of array 1, you have to use array 2
names3[i] = names2[names2I++];
else if(names2I == names2.Length) //if you have already reached the end of array 2, you have to use array 1
names3[i] = names1[names1I++];
else //else take the smaller of the 2 possible values
names3[i] = (names1[names1I] <= names2[names2I]) ? names1[names1I++] : names2[names2I++];
}

Related

Compare chars in two strings of different length in C#

In C#, Im trying to compare two strings and find out how many chars are different.
I Tried this:
static void Main(String[] args)
{
var strOne = "abcd";
var strTwo = "bcd";
var arrayOne = strOne.ToCharArray();
var arrayTwo = strTwo.ToCharArray();
var differentChars = arrayOne.Except(arrayTwo);
foreach (var character in differentChars)
Console.WriteLine(character); //Will print a
}
but there are problems with this:
if the strings contain same chars but on different positions within the string
it removes the duplicate occurences
If the strings would be the same length I would compare the chars one by one but if one is bigger than the other the positions are different
You may want to have a look at the Leventshtein Distance Algorithm.
As the article says
the Levenshtein distance between two words is the minimum number of
single-character edits (insertions, deletions or substitutions)
required to change one word into the other
You can find many reference implementations in the internet, like here or here.
public static int LevenshteinDistance(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
}
How about this? Append two strings into one and group them, you will have the count of the chars, > 1 will give the repeatings and = 0 will give the unique ones.
var strOne = "abcd";
var strTwo = "bcd";
var arrayOne = strOne.Concat(strTwo).GroupBy(x => x).Select(x => new { Key = x.Key, Count = x.Count() });
foreach (var character in arrayOne) {
if (character.Count > 1)
{
Console.WriteLine(character.Key); // the repeating chars
}
}
If the same character appears twice in the same string,
var strOne = "abbcdd";
var strTwo = "cd";
var arrayTwo = strOne.Select(x => new { Key = x, IsExists = strTwo.Any(y => y == x) });
foreach (var character in arrayTwo) {
if (character.IsExists)
{
Console.WriteLine(character.Key);
}
}

How to prevent "index out of range" when I need the items around the index position?

I have an array of strings which represents the lines of a textfile. Now I want to search the line where my given argument occurs and return this line plus the four adjacent lines.
The problem occurs when my searched string is found in the last or first two indexes. Obviously this is because I want the index[i+2] when there is none.
Ideally, if the last line is the prime one, it should return only this and the two lines before it because there aren't two after it.
So is there a Best Practice how to solve this issue other then adding an if-statement in front of every of the five line inside the "contains"-if-statement?
ReadAsString converts the content of the textfile into the array of strings _textAsString
public string[] GetNearestInstructions(string foo)
{
try
{
string[] stringsToReturn = new string[5];
if (!this.ReadAsString())
return null;
else if (foo == null)
return null;
else
{
for (int i = 0; i < _textAsString.Length; i++)
{
if (_textAsString[i].Contains(foo))
{
stringsToReturn[0] = _textAsString[i - 2];
stringsToReturn[1] = _textAsString[i - 1];
stringsToReturn[2] = _textAsString[i];
stringsToReturn[3] = _textAsString[i + 1];
stringsToReturn[4] = _textAsString[i + 2];
}
}
if (stringsToReturn != null)
return stringsToReturn;
else
return null;
}
}
catch (Exception)
{
throw;
}
}
You might do something like
...
if (_textAsString[i].Contains(foo))
{
int rangoLow = Math.Max(i - 2, 0);
int rangeHigh = Math.Min(i + 2, _textAsString.Length - 1);
for (int i = rangeLow; i <= rangeHigh; i++)
{
stringsToReturn[i - rangeLow] = _textAsString[i];
}
Assuming that you need the result as array in the exact same format as you are returning it right now, that is with null items at begin or end, this would be the way I would do it:
public static string[] GetNearestInstructions(string foo)
{
if (foo != null && this.ReadAsString())
{
int index = Array.IndexOf(_textAsString, foo);
if (index >= 0)
{
string[] stringsToReturn = new string[5];
stringsToReturn[0] = index > 1 ? _textAsString[index - 2] : null;
stringsToReturn[1] = index > 0 ? _textAsString[index - 1] : null;
stringsToReturn[2] = _textAsString[index];
stringsToReturn[3] = index < _textAsString.Length - 1 ? _textAsString[index + 1] : null;
stringsToReturn[4] = index < _textAsString.Length - 2 ? _textAsString[index + 2] : null;
return stringsToReturn;
}
}
return null;
}
Things get easier if you are fine with changing the number of returned items, see the other answers then.
You need to adjust the first + last indices as needed. See code below. Also I changed stringsToReturn to a List because it is more convenient, and because there is no point in always returning an array of 5 items if there are fewer than 5.
List<string> stringsToReturn = new List<string>();
for (int i = 0; i < _textAsString.Length; i++)
{
if (_textAsString[i].Contains(foo))
{
var firstIndex = Math.Max(0, i - 2);
var lastIndex = Math.Min(_textAsString.Length - 1, i + 2);
for (int j = firstIndex; j <= lastIndex; j++)
stringsToReturn.Add(_textAsString[j]);
return stringsToReturn.ToArray();
}
}
// foo not found
return null;
Note, that if _textAsString is string (not collection of strings), then this function should take char as parameter, and return collection of chars (or single string).

Hackerrank: Climbing the Leaderboard

i have a deal with a hackerrank algorithm problem.
It works at all cases, except 6-7-8-9. It gives timeout error. I had spent so much time at this level. Someone saw where is problem?
static long[] climbingLeaderboard(long[] scores, long[] alice)
{
//long[] ranks = new long[scores.Length];
long[] aliceRanks = new long[alice.Length]; // same length with alice length
long lastPoint = 0;
long lastRank;
for (long i = 0; i < alice.Length; i++)
{
lastPoint = scores[0];
lastRank = 1;
bool isIn = false; // if never drop in if statement
for (long j = 0; j < scores.Length; j++)
{
if (lastPoint != scores[j]) //if score is not same, raise the variable
{
lastPoint = scores[j];
lastRank++;
}
if (alice[i] >= scores[j])
{
aliceRanks[i] = lastRank;
isIn = true;
break;
}
aliceRanks[i] = !isIn & j + 1 == scores.Length ? ++lastRank : aliceRanks[i]; //drop in here
}
}
return aliceRanks;
}
This problem can be solved in O(n) time, no binary search needed at all. First, we need to extract the most useful piece of data given in the problem statement, which is,
The existing leaderboard, scores, is in descending order.
Alice's scores, alice, are in ascending order.
An approach that makes this useful is to create two pointers, one at the start of alice array, let's call it "i", and the second is at the end of scores array, let's call it "j". We then loop until i reaches the end of alice array and at each iteration, we check for three main conditions. We increment i by one if alice[i] is less than scores[j] because the next element of alice may be also less than the current element of scores, or we decrement j if alice[i] is greater than scores[j] because we are sure that the next elements of alice are also greater than those elements discarded in scores. The last condition is that if alice[i] == scores[j], we only increment i.
I solved this question in C++, my goal here is to make you understand the algorithm, I think you can easily convert it to C# if you understand it. If there are any confusions, please tell me. Here is the code:
// Complete the climbingLeaderboard function below.
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice) {
int j = 1, i = 1;
// this is to remove duplicates from the scores vector
for(i =1; i < scores.size(); i++){
if(scores[i] != scores[i-1]){
scores[j++] = scores[i];
}
}
int size = scores.size();
for(i = 0; i < size-j; i++){
scores.pop_back();
}
vector<int> ranks;
i = 0;
j = scores.size()-1;
while(i < alice.size()){
if(j < 0){
ranks.push_back(1);
i++;
continue;
}
if(alice[i] < scores[j]){
ranks.push_back(j+2);
i++;
} else if(alice[i] > scores[j]){
j--;
} else {
ranks.push_back(j+1);
i++;
}
}
return ranks;
}
I think this may help you too:
vector is like an array list that resizes itself.
push_back() is inserting at the end of the vector.
pop_back() is removing from the end of the vector.
Here is my solution with c#
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> result = new List<int>();
ranked = ranked.Distinct().ToList();
var pLength = player.Count;
var rLength = ranked.Count-1;
int j = rLength;
for (int i = 0; i < pLength; i++)
{
for (; j >= 0; j--)
{
if (player[i] == ranked[j])
{
result.Add(j + 1);
break;
}
else if(player[i] < ranked[j])
{
result.Add(j + 2);
break;
}
else if(player[i] > ranked[j]&&j==0)
{
result.Add(1);
break;
}enter code here
}
}
return result;
}
Here is a solution that utilizes BinarySearch. This method returns the index of the searched number in the array, or if the number is not found then it returns a negative number that is the bitwise complement of the index of the next element in the array. Binary search only works in sorted arrays.
public static int[] GetRanks(long[] scores, long[] person)
{
var defaultComparer = Comparer<long>.Default;
var reverseComparer = Comparer<long>.Create((x, y) => -defaultComparer.Compare(x, y));
var distinctOrderedScores = scores.Distinct().OrderBy(i => i, reverseComparer).ToArray();
return person
.Select(i => Array.BinarySearch(distinctOrderedScores, i, reverseComparer))
.Select(pos => (pos >= 0 ? pos : ~pos) + 1)
.ToArray();
}
Usage example:
var scores = new long[] { 100, 100, 50, 40, 40, 20, 10 };
var alice = new long[] { 5, 25, 50, 120 };
var ranks = GetRanks(scores, alice);
Console.WriteLine($"Ranks: {String.Join(", ", ranks)}");
Output:
Ranks: 6, 4, 2, 1
I was bored so i gave this a go with Linq and heavily commented it for you,
Given
public static IEnumerable<int> GetRanks(long[] scores, long[] person)
// Convert scores to a tuple
=> scores.Select(s => (scores: s, isPerson: false))
// convert persons score to a tuple and concat
.Concat(person.Select(s => (scores: s, isPerson: true)))
// Group by scores
.GroupBy(x => x.scores)
// order by score
.OrderBy(x => x.Key)
// select into an indexable tuple so we know everyones rank
.Select((groups, i) => (rank: i, groups))
// Filter the person
.Where(x => x.groups.Any(y => y.isPerson))
// select the rank
.Select(x => x.rank);
Usage
static void Main(string[] args)
{
var scores = new long[]{1, 34, 565, 43, 44, 56, 67};
var alice = new long[]{578, 40, 50, 67, 6};
var ranks = GetRanks(scores, alice);
foreach (var rank in ranks)
Console.WriteLine(rank);
}
Output
1
3
6
8
10
Based on the given constraint brute-force solution will not be efficient for the problem.
you have to optimize your code and the key part here is to look up for exact place which can be effectively done by using binary search.
Here is the solution using binary search:-
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int n = scores.length;
int m = alice.length;
int res[] = new int[m];
int[] rank = new int[n];
rank[0] = 1;
for (int i = 1; i < n; i++) {
if (scores[i] == scores[i - 1]) {
rank[i] = rank[i - 1];
} else {
rank[i] = rank[i - 1] + 1;
}
}
for (int i = 0; i < m; i++) {
int aliceScore = alice[i];
if (aliceScore > scores[0]) {
res[i] = 1;
} else if (aliceScore < scores[n - 1]) {
res[i] = rank[n - 1] + 1;
} else {
int index = binarySearch(scores, aliceScore);
res[i] = rank[index];
}
}
return res;
}
private static int binarySearch(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] == key) {
return mid;
} else if (a[mid] < key && key < a[mid - 1]) {
return mid;
} else if (a[mid] > key && key >= a[mid + 1]) {
return mid + 1;
} else if (a[mid] < key) {
hi = mid - 1;
} else if (a[mid] > key) {
lo = mid + 1;
}
}
return -1;
}
You can refer to this link for a more detailed video explanation.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int[] uniqueScores = IntStream.of(scores).distinct().toArray();
int [] rank = new int [alice.length];
int startIndex=0;
for(int j=alice.length-1; j>=0;j--) {
for(int i=startIndex; i<=uniqueScores.length-1;i++) {
if (alice[j]<uniqueScores[uniqueScores.length-1]){
rank[j]=uniqueScores.length+1;
break;
}
else if(alice[j]>=uniqueScores[i]) {
rank[j]=i+1;
startIndex=i;
break;
}
else{continue;}
}
}
return rank;
}
My solution in javascript for climbing the Leaderboard Hackerrank problem. The time complexity of the problem can be O(i+j), i is the length of scores and j is the length of alice. The space complexity is O(1).
// Complete the climbingLeaderboard function below.
function climbingLeaderboard(scores, alice) {
const ans = [];
let count = 0;
// the alice array is arranged in ascending order
let j = alice.length - 1;
for (let i = 0 ; i < scores.length ; i++) {
const score = scores[i];
for (; j >= 0 ; j--) {
if (alice[j] >= score) {
// if higher than score
ans.unshift(count+1);
} else if (i === scores.length - 1) {
// if smallest
ans.unshift(count+2);
} else {
break;
}
}
// actual rank of the score in leaderboard
if (score !== scores[i-1]) {
count++;
}
}
return ans;
}
Here is my solution
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
for (int i = 0; i < distinct.Count; i++)
{
if (item == distinct[i])
{
rank.Add(i + 1);
break;
}
}
}
return rank;
This can be modified by removing the inner for loop also
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
var index = ranked.FindIndex(x => x == item);
rank.Add(index + 1);
}
return rank;
This is my solution in c# for Hackerrank Climbing the Leaderboard based on C++ answer here.
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> _ranked = new List<int>();
_ranked.Add(ranked[0]);
for(int a=1; a < ranked.Count(); a++)
if(_ranked[_ranked.Count()-1] != ranked[a])
_ranked.Add(ranked[a]);
int j = _ranked.Count()-1;
int i = 0;
while(i < player.Count())
{
if(j < 0)
{
player[i] = 1;
i++;
continue;
}
if(player[i] < _ranked[j])
{
player[i] = j+2;
i++;
}
else
if(player[i] == _ranked[j])
{
player[i] = j+1;
i++;
}
else
{
j--;
}
}
return player;
}
My solution in Java for climbing the Leaderboard Hackerrank problem.
// Complete the climbingLeaderboard function below.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
Arrays.sort(scores);
HashSet<Integer> set = new HashSet<Integer>();
int[] ar = new int[alice.length];
int sc = 0;
for(int i=0; i<alice.length; i++){
sc = 1;
set.clear();
for(int j=0; j<scores.length; j++){
if(alice[i] < scores[j] && !set.contains(scores[j])){
sc++;
set.add(scores[j]);
}
}
ar[i] = sc;
}return ar;
}

How to make the variable of an if statement dynamic

Hi I am trying to loop through a set of int variables and do an if on each one. I.e.
int a0, a1, a2,a3;
for (int I=0; I < 3; I++)
{
if("a" + I > 10)
{
// do something
}
}
Is this possible?
If you want to iterate you need a collection
IEnumerable<int> numbers = new List<int> { 1, 2, 3, 10 };
foreach (var item in numbers)
{
if(item > 10)
{
// do something
}
}
When you write "a" + I all you are doing is create a string that is a concatenation of the two pieces and is not the parameter you defined before
You can then proceed and use linq:
var filtered = numbers.Where(item => item > 10)
You can use array as variable so you can iterate that :
int[] a = new int[3];
a[0] = 5;
a[1] = 10;
a[2] = 15;
for (int I = 0; I < 3; I++)
{
if (a[I] > 10)
{
// do something, example:
Console.WriteLine(a[I])
}
}
Result :
15

Implementation of an anagram function in C#

Possible Duplicate:
What is an easy way to tell if a list of words are anagrams of each other?
What is the best way (performance wide) to write a function in C# that takes two strings and returns true when the strings are anagrams of each other and otherwise returns false. Example of anagrams are:
abet beat beta bate
abides biased
anagrams link
In implementing this, is it possible that there is space in each string?
Any idea would be very much appreciated!
A simple (naïve?) way, using LINQ:
"abides".OrderBy(c=>c).SequenceEqual("biased".OrderBy(c=>c))
An easy solution would be to sort the characters alphabetically and compare them to one another.
public static class AnagramExtensions
{
public static bool IsAnagramOf(this string word1, string word2)
{
return word1.OrderBy(x => x).SequenceEqual(word2.OrderBy(x => x));
}
}
Then, to use it:
static void Main()
{
string word1 = "cat";
string word2 = "tac";
Console.WriteLine(word1.IsAnagramOf(word2));
string word3 = "cat";
string word4 = "dog";
Console.WriteLine(word3.IsAnagramOf(word4));
}
The output in this case would be
True
False
How not to do this: Remove all whitespace from each of the strings. Use one of the algorithms at Algorithm to generate anagrams to generate all possible permutations of the first string. Finally, search the list of permuations for a match; if there is one, then the two are anagrams, otherwise, not.
I have a solution for a List of Strings (Not just two Strings).
If you are interested in it or any other one, you can use it.
Given an array of strings, remove each string that is an anagram of an earlier string, then return the remaining array in stored order.
private static List<string> GencoAnagrams(List<string> textList)
{
var listCount = textList.Count;
if (listCount == 1) return textList;
for (var j = 1; j < listCount; j++)
{
for (var i = 0; i < j; i++)
{
if (string.Concat(textList[j].OrderBy(x => x)).Equals(string.Concat(textList[i].OrderBy(y => y))))
{
textList.RemoveAt(j);
--listCount;
--j;
if (listCount == 1) break;
}
}
if (listCount == 1) break;
}
return textList;
}
and count all sceniro (n*n+1)/2
public static int sherlockAndAnagrams(string s)
{
int count = 0;
string[] stringList = new string[(s.Length * (s.Length + 1)) / 2];
int index = 0;
Dictionary<string, int> hash = new Dictionary<string, int>();
for (int i = 0; i < s.Length; i++)
{
for (int j = i; j < s.Length; j++)
{
stringList[index] = s.Substring(i, j - i + 1);
index++;
}
}
foreach (var str in stringList)
{
var keyString = string.Concat(str.OrderBy(x => x));
if (hash.ContainsKey(keyString))
{
hash[keyString]++;
}
else
{
hash[keyString] = 1;
}
}
foreach (var key in hash.Keys)
{
if (hash[key] <= 1)
{
continue;
}
else
{
count = count + ((hash[key] * (hash[key] - 1) )/ 2);
}
}
return count;
}

Categories

Resources