Programming C# array multiplication - c#

I have a function that takes a string and returns a string. In it, I convert the string into an integer array and later try to multiply every other number like this:
private string addEveryOther(string x)
{
int[] d = x.Select(n => Convert.ToInt32(n)).ToArray();
for(int i = 0; i < 10; i++)
{
d[i] = d[i] * 2;
MessageBox.Show(d[i].ToString()); //Display the result?
i++;
}
// And later returning a string:
StringBuilder g = new StringBuilder();
foreach (int n in d)
{
g.Append(Convert.ToChar(n));
}
return g.ToString();
}
This works with addition, but not with multiplication as it returns strange values. If I input "3434343434" i expect it to return "6464646464". Now it returns: "f4f4f4f4f4" and I don't know why? Any suggestions how to go about it?

Based on the discussions above, I suppose your method should use ToString instead of Convert.ToChar.
private string addEveryOther(string x)
{
int[] d = x.Select(n => Convert.ToInt32(n.ToString())).ToArray();
for(int i = 0; i < d.Length; i += 2)
{
d[i] = d[i] * 2;
MessageBox.Show(d[i].ToString()); //Display the result?
}
// And later returning a string:
return String.Concat(d.Select(n => n.ToString()));
}
EDIT: Using #Kirill's Concat solution and #Reniuz comment in the addEveryOther method should hopefully solve the problem.

As I wrote in comment Convert.ToInt32(char)
Converts the value of the specified Unicode character to the
equivalent 32-bit signed integer.
So when you converting "0" result will be 48, when "1" result 50 and so on.
Here's changed code:
private string addEveryOther(string x)
{
//1. Convert string to int, not char to int
int[] d = x.Select(n => Convert.ToInt32(n.ToString())).ToArray();
//2. start from second number
for (int i = 1; i < 10; i++)
{
d[i] = d[i] * 2;
MessageBox.Show(d[i].ToString()); //Display the result?
i++;
}
string s = d.ToString();
// And later returning a string:
StringBuilder g = new StringBuilder();
foreach (int n in d)
{
//3. Convert int to string, not to char
g.Append(n.ToString());
}
return g.ToString();
}

Try this:
int[] d = x.Select(n => int.Parse(n.ToString())).ToArray();
for(int i = 0; i < 10; i++)
{
d[i] = (i%2 == 0? d[i] * 2 : d[i]);
}
StringBuilder g = new StringBuilder();
foreach (int n in d)
{
g.Append(n);
}
return g.ToString();
hope it helps

When you use
Convert.ToInt32(n.ToString())
There is redundant conversion. I think the simplest way is
var d = x.Select(n => Char.IsDigit(n) ? n - '0' : 0).ToArray();

Related

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.

Converting string[] to double[]

I have a text file that is being read in and then stored in a string[] which I then then convert into an int[], my bubblesort then should sort it but it doesn't because the values from the text files are decimals. So my question is how do I convert either the string[] or int[] to something that can accept decimal values, such as a double[] if there is such a thing. Thanks.
Code:
string[] sh1OpenData = File.ReadAllLines("SH1_Open.txt");
...
else if(input2.ToLower() == "open") //----
{
int[] intSh1OpenData = new int[sh1OpenData.Length];
for (int x = 0; x < sh1OpenData.Length; x++)
{
intSh1OpenData[x] = Convert.ToInt32(sh1OpenData[x]);
}
Console.WriteLine("\n");
Console.WriteLine("Unsorted");
for (int i = 0; i < intSh1OpenData.Length; i++)
{
Console.Write(intSh1OpenData[i] + " ");
Console.WriteLine(" ");
}
int temp = 0;
for (int write = 0; write < intSh1OpenData.Length; write++)
{
for (int sort = 0; sort < intSh1OpenData.Length - 1; sort++)
{
if (intSh1OpenData[sort] > intSh1OpenData[sort + 1])
{
temp = intSh1OpenData[sort + 1];
intSh1OpenData[sort + 1] = intSh1OpenData[sort];
intSh1OpenData[sort] = temp;
}
}
}
Console.WriteLine("\n\n\nSORTED");
for (int i = 0; i < intSh1OpenData.Length; i++)
Console.Write(intSh1OpenData[i] + "\n");
}
You should not be using int to do comparisons on string. Use String.Compare(return 0 if equal, -1 if less than, or 1 if greater than) or List.Sort() to sort string array
Pretty simple with LINQ
var asDouble = sh1OpenData.Select(x => Double.Parse(x)).OrderBy(x => x).ToArray();
This will give you a sorted (ascending order) array of Double.
Note: this assumes that all of sh1OpenData can be parsed as a Double, and will throw an exception if not.
The only changes that you will need to make are listed below:
double[] intSh1OpenData = new double[sh1OpenData.Length]; // double[] instead of int[]
for (int x = 0; x < sh1OpenData.Length; x++)
{
intSh1OpenData[x] = Convert.ToDouble(sh1OpenData[x]); // Convert to Double
}
also change the declaration of your temp variable to double temp;
Something that you could read through since you mentioned that you are new to programming:
C# Sort Arrays and Lists Examples
MSDN: List.Sort Method

Intersect two lists and return the similarity with the preserved order of the original first string value

I'm facing a problem I don't even know what to search in Google/Stack Overflow.
So comment if you feel the need for further explanation, questions.
Basically I want to intersect two lists and return the similarity with the preserved order of the original first string value.
Example:
I have two strings, that I convert to a CharArray.
I want to Intersect these two arrays and return the values that are similar, including/with the order of the first string (s1).
As you can see the first string contains E15 (in that specific order), and so does the seconds one.
So these two strings will return : { 'E', '1', '5' }
string s1 = "E15QD(A)";
string s2 = "NHE15H";
The problem I am facing is that if i replace "s2" with:
string s2 = "NQE18H" // Will return {'Q', 'E', '1' }
My operation will return : {'Q', 'E', '1' }
The result should be : {'E', '1' } because Q don't follow the letter 1
Currently my operation is not the greatest effort, because i don't know which methods to use in .NET to be able to do this.
Current code:
List<char> cA1 = s1.ToList();
List<char> cA2 = s2.ToList();
var result = cA1.Where(x => cA2.Contains(x)).ToList();
Feel free to help me out, pointers in the right direction is acceptable as well as a full solution.
This is a "longest common substring" problem.
You can use this extension to get all substrings lazily:
public static class StringExtensions
{
public static IEnumerable<string> GetSubstrings(this string str)
{
if (string.IsNullOrEmpty(str))
throw new ArgumentException("str must not be null or empty", "str");
for (int c = 0; c < str.Length - 1; c++)
{
for (int cc = 1; c + cc <= str.Length; cc++)
{
yield return str.Substring(c, cc);
}
}
}
}
Then it's easy and readable with this LINQ query:
string longestIntersection = "E15QD(A)".GetSubstrings()
.Intersect("NQE18H".GetSubstrings())
.OrderByDescending(s => s.Length)
.FirstOrDefault(); // E1
Enumerable.Intersect is also quite efficient since it's using a set. One note: if one both strings is larger than the other then it's more efficient(in terms of memory) to use it first:
longString.GetSubstrings().Intersect(shortString.GetSubstrings())
I think this should do it:
string similar = null;
for (int i = 0; i < s1.Length; i++)
{
string s = s1.Substring(0, i + 1);
if (s2.Contains(s))
{
similar = s;
}
}
char[] result = similar.ToCharArray();
#TimSchmelter provided the link to this answer in the comments of the original post.
public int LongestCommonSubstring(string str1, string str2, out string sequence)
{
sequence = string.Empty;
if (String.IsNullOrEmpty(str1) || String.IsNullOrEmpty(str2))
return 0;
int[,] num = new int[str1.Length, str2.Length];
int maxlen = 0;
int lastSubsBegin = 0;
StringBuilder sequenceBuilder = new StringBuilder();
for (int i = 0; i < str1.Length; i++)
{
for (int j = 0; j < str2.Length; j++)
{
if (str1[i] != str2[j])
num[i, j] = 0;
else
{
if ((i == 0) || (j == 0))
num[i, j] = 1;
else
num[i, j] = 1 + num[i - 1, j - 1];
if (num[i, j] > maxlen)
{
maxlen = num[i, j];
int thisSubsBegin = i - num[i, j] + 1;
if (lastSubsBegin == thisSubsBegin)
{//if the current LCS is the same as the last time this block ran
sequenceBuilder.Append(str1[i]);
}
else //this block resets the string builder if a different LCS is found
{
lastSubsBegin = thisSubsBegin;
sequenceBuilder.Length = 0; //clear it
sequenceBuilder.Append(str1.Substring(lastSubsBegin, (i + 1) - lastSubsBegin));
}
}
}
}
}
sequence = sequenceBuilder.ToString();
return maxlen;
}

How can I calculate similarity between two strings in C#?

I'm looking to assess similarity (including case) between two strings and give a value between 0 and 1.
I tried the Levenshtein distance implementation but it only gives integers and does not compare inner alphabets.
For e.g. comparing "ABCD" and "Abcd" gives distance of 3 and "AOOO" also gives a distance of 3 but clearly "Abcd" is better match than "AOOO".
So compared to "ABCD" I want "ABcd" to be most similar then "Abcd" then "AOOO" then "AOOOO"
I've also looked here but I am not looking for a variable length algorithm.
Thanks
Try something like this
double d = (LevenshteinDist(s, t) + LevenshteinDist(s.ToLower(), t.ToLower())) /
2.0 * Math.Max(s.Length, t.Length);
If you want to give less importance to case differences than letter differences, you can give different weights to the terms
double d = (0.15*LevenshteinDist(s, t) +
0.35*LevenshteinDist(s.ToLower(), t.ToLower())) /
Math.Max(s.Length, t.Length);
Note that the weights sum up to 0.5, thus makting the division by 2.0 obsolete.
Adapt Levenshtein Distance with a custom table T. Let the cost of insertion = 1. The cost of deletion also 1. Let T(c,d) denote the penalty of replacing c with d. T(c,c) should be = 0. T(c,d) should be <= 2.
Define Max(n,m) be the maximum theoretical distance of strings of length n and m. Obviously, Max(n,m) = n+m.
Define Distance(s,t) be the cost of changing s to t divided by Max(s,t). There you go.
Be careful in defining T so that the definition obeys distance axioms:
Distance(s,s) = 0
Distance(s,t) = Distance(t,s)
Distance(s,t) <= Distance(s,u) + Distance(u,t)
Then it will be more useful in more situations.
bool check(string[] a, string s)
{
for (int i = 0; i < a.Length; i++)
if (s == a[i])
return true;
return false;
}
public double simi(string string1, string string2)
{
int sub1 = 0;
int sub2 = 0;
string[] sp1 = new string[string1.Length - 1];
string[] sp2 = new string[string2.Length - 1];
string[] sp3 = new string[string1.Length - 1];
string[] sp4 = new string[string2.Length - 1];
for (int i = 0; i < string1.Length - 1; i++)
{
string x = "";
x = string1.Substring(i, 2);
sp1[sub1] = x;
++sub1;
}
for (int i = 0; i < string2.Length - 1; i++)
{
string x = "";
x = string2.Substring(i, 2);
sp2[sub2] = x;
++sub2;
}
int j = 0, k = 0;
for (int i = 0; i < sp1.Length; i++)
if (check(sp3, sp1[i]) == true)
{
continue;
}
else
{
sp3[j] = sp1[i];
j++;
}
for (int i = 0; i < sp2.Length; i++)
if (check(sp4, sp2[i]) == true)
{
continue;
}
else
{
sp4[k] = sp2[i];
k++;
}
Array.Resize(ref sp3, j);
Array.Resize(ref sp4, k);
Array.Sort<string>(sp3);
Array.Sort<string>(sp4);
int n = 0;
for (int i = 0; i < sp3.Length; i++)
{
if (check(sp4, sp3[i]))
{
n++;
}
}
double resulte;
int l1 = sp3.Length;
int l2 = sp4.Length;
resulte = ((2.0 * Convert.ToDouble(n)) / Convert.ToDouble(l1 + l2)) * 100;
return resulte;
}

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