How to find substrings of length m that contain ith element(C#) - c#

We have a string length of n, I want to find all substrings of length m that contain ith element.
For example string s = "abcde"; I want to get all substrings of length 3 that contain 2nd element i.e. "b", in this case
abc, bcd
that is 2. But how we can code this for a general situation, i.e. substrings of length m, from a string of length n, that contain ith element
It would be good if substrings are stored in List<string>(not just Console.WriteLine())

public static List<string> GetSubStrings_i(string inputString, int mainIndex, int sbstrLength)
{
List<string> substringsList = new List<string>();
for (int i = mainIndex - sbstrLength + 1; i <= mainIndex; i++)
{
if (i < 0)
i = 0;
if (i + sbstrLength <= inputString.Length)
substringsList.Add(inputString.Substring(i, sbstrLength));
}
return substringsList;
}
"*" is a symbol that all substrings should contain
Input
String = fsaf*faj;aijefaejsk
substrLength = 5
Index = 4
Output
substring = fsaf*
substring = saf*f
substring = af*fa
substring = f*faj
substring = *faj;

Try This:
First you call getAllSubstrings, return list of all substrings of length m that contain i th element
List<String> matchsubstring = getAllSubstrings("abcde","b");
public static List<String> getAllSubstrings(String inputString, String stringmatch)
{
List<String> resultList = new List<String>();
for(int j = 0; j < inputString.Length; j++)
{
for(int i = 0; i < inputString.Length - j + 1 ;i++)
{
if(inputString.Substring(i,j).Contains(stringmatch))
{
resultList.Add(inputString.Substring(i,j));
Console.WriteLine("Substring Length : "+j +
", Substring :" + inputString.Substring(i,j) +
", Index of string match :"+ inputString.Substring(i,j).IndexOf(stringmatch.ToCharArray()[0]));
}
}
}
return resultList;
}
Then you call getAllMatchSubstringByIndexing , return list of all substrings of length m that contain i th element at x index
List<String> outputList = getAllMatchSubstringByIndexing (matchsubstring ,"b",1)
matchsubstring is output of getAllSubstrings function
public static List<String> getAllMatchSubstringByIndexing(List<string> substring, String stringmatch, int index)
{
List<String> substringWithIndex = new List<String>();
foreach(var substringData in substring)
{
if(substringData.IndexOf(stringmatch.ToCharArray()[0]) == index)
{
substringWithIndex.Add(substringData);
Console.WriteLine("Output : "+substringData);
}
}
return substringWithIndex;
}

Related

Get Last Four word after splitting a string

I have two string like below
var str1 = '20180215.20150215.3.1.0.0';
var str2 = '20180215.3.1.0.0';
I need to get the last four word after splitting these string with .
var str1Arr = str1.split('.')
What i need is a generic method to get last four words 3.1.0.0.
Thanks
var lastFour = str1Arr.Reverse().Take(4).Reverse().ToArray();
public static class SplitExtension
{
public static string LastNItems(this string str, int nItem, char separator = '.')
{
return string.Join(separator.ToString(), str.Split(separator).Reverse().Take(nItem).Reverse());
}
public static string[] LastNItems(this string[] strArray, int nItem)
{
return strArray.Reverse().Take(nItem).Reverse().ToArray();
}
}
This will enable you to do
var str1 = "20180215.20150215.3.1.0.0";
var str1Last4 = str1.LastNItems(4); // "3.1.0.0"
var str1Last4Items = str1.Split('.').LastNItems(4); // ["3","1","0","0"]
or for completion
var str1Last4Items = str1.LastNItems(4).Split('.'); // ["3","1","0","0"]
You can use it by extension methods.
public static class CommonExtension
{
public static List<string> LastNItem(this string str, int nItem, string separator = ".")
{
var splittedWords = str.Split(new [] { separator }, StringSplitOptions.None);
var res = splittedWords.Reverse().Take(nItem).Reverse().ToList();
return res;
}
}
Then you can call it everywhere you want.
var str1 = "1.0.0";
var str2 = "20180215.3.1.0.0";
var str1Last4 = str1.LastNItem(4);
var str2Last4 = str2.LastNItem(4);
Why not just Skip top Length - 4 items?
string str1 = "20180215.20150215.3.1.0.0";
string[] str1Arr = str1.Split('.');
var result = str1Arr
.Skip(str1Arr.Length - 4)
.ToArray(); // if you want an array materialization
This code will do even when str1Arr.Length < 4 (in this case the entire str1Arr copy will be returned). In case you want a string as the result you can just try Substring (without creating any arrays)
string str1 = "20180215.20150215.3.1.0.0";
string result = str1;
int index = result.Length;
for (int i = 0; i < 4; ++i) {
index = str1.LastIndexOf('.', index - 1);
if (index < 0)
break;
}
result = index < 0 ? result : result.Substring(index + 1);
public static string GetLastFour(string str)
{
string[] arr = str.Split('.');
System.Text.StringBuilder lastFour = new System.Text.StringBuilder();
if (arr.Length >= 4)
{
for (int k = arr.Length - 4; k < arr.Length; k++)
{
if (k == arr.Length - 1)
{
lastFour.Append(arr[k]);
}
else
{
lastFour.Append(arr[k] + ".");
}
}
}
return lastFour.ToString();
}
This would be faster than double reverse answer.
var str1 = "20180215.20150215.3.1.0.0";
var str2 = "20180215.3.1.0.0";
var words = str1.Split('.');
var toSkip = words.Length - 4;
var result = string.Join(".", words.Skip(toSkip));
A bit of testing showed that is is just slightly faster than double reverse.
What is 10 times faster than this one?
Well avoiding memory allocations and enumerations will be.
Here are the results of comparing 3 different extension methods for 10M iterations:
double reverse: 6463ms
split + skip: 5269ms
straight: 492ms
void Main()
{
var str1 = "20180215.20150215.3.1.0.0";
var numIterations = 10000000;
var timer = new Stopwatch();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsDoubleReverse(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("double reverse");
timer.Reset();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsSplitNSkip(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("split + skip");
timer.Reset();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsStraight(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("straight");
}
public static class ext
{
public static string LastNItemsDoubleReverse(this string str, int nItem, char separator = '.')
{
return string.Join(separator.ToString(), str.Split(separator).Reverse().Take(nItem).Reverse());
}
public static string LastNItemsSplitNSkip(this string str, int nItem, char separator = '.')
{
var words = str.Split(separator);
var toSkip = words.Length - nItem;
return string.Join($"{separator}", words.Skip(toSkip));
}
public static string LastNItemsStraight(this string str, int nItem, char separator = '.')
{
int j=1,i=str.Length-1;
for (;i>=0 && j<nItem;i--){
if(str[i]==separator) j++;
}
return str.Substring(i);
}
}
Try the following :
List<string> GetLastFourWords()
{
List<string> lastFour = new List<string>();
try
{
string[] arr = str1.split('.');
for(int i = 3; i >= 0; i-- )
{
lastFour.Add(arr[str1.length - 1 - i]);
}
}
catch(Exception ex)
{
}
return lastFour;
}

how to split string into two strings when it finds a number

So basically if I have string a = "asd333"; I want to split this string into two strings
string b = "asd" and string c = "333"
for example string a = "aaa 555";string[]b = a.Split(' '); will make
b[0]="aaa" and b[1] = "555"
But this is not what i want i want to split string into two string withouth loosing characters and split it before a number
This is my code so far
string text = textBox4.Text.ToString();
char[] whitespace = new char[] { ' ','\t' };
string[] temp = text.Split(whitespace);
But i want to change it so string[] temp equals two string first is letters and second is numbers
I think it's not the best method, but it works
string a = "aaa333aaa333aaa22bb22bb1c1c1c";
List<string> result = new List<string>();
int lastSplitInedx = 0;
for (int i = 0; i < a.Length-1; i++)
{
if (char.IsLetter(a[i]) != char.IsLetter(a[i + 1]))
{
result.Add(a.Substring(lastSplitInedx, (i + 1) - lastSplitInedx));
lastSplitInedx = i+1;
}
if (i+1 == a.Length-1)
{
result.Add(a.Substring(lastSplitInedx));
}
}
foreach (string s in result)
{
Console.WriteLine(s);
}
Get the matched group from index 1 and 2.
String literals for use in programs:
C#
#"(\D+)\s*(\d+)"
Search for the integer in the string and split the string at that position
string a = "str123";
string b = string.Empty;
int val;
for (int i=0; i< a.Length; i++)
{
if (Char.IsDigit(a[i]))
b += a[i];
}
if (b.Length>0)
val = int.Parse(b);

How to check if file contains strings, which will double repeat sign?

I would like to check if file containing some strings, separated with # contains double repeat sign. Example:
I have a file like this:
1234#224859#123567
I am reading this file and putting strings separated with # it into array.
I would like to find which strings have a digit repeated next to each other (in this case 224859) and return position of first digit that repeats in this string?
This is what I have so far:
ArrayList list = new ArrayList();
OpenFileDialog openFile1 = new OpenFileDialog();
int size = -1;
DialogResult dr = openFile1.ShowDialog();
string file = openFile1.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
string temp = "";
for (int i = 0; i < text.Length; i++)
{
if (text[i] != '#')
{
temp += text[i].ToString();
}
else
{
list.Add(temp);
temp = "";
}
}
}
catch (IOException)
{
}
string all_values = "";
foreach (Object obj in list)
{
all_values += obj.ToString() + " => ";
Console.WriteLine(" => ", obj);
}
textBox1.Text = (all_values);
This regex should do the trick.
var subject = "1234#224859#123567";
foreach(var item in subject.Split('#'))
{
var regex = new Regex(#"(?<grp>\d)\k<grp>");
var match =regex.Match(item);
if(match.Success)
{
Console.WriteLine("Index : {0}, Item:{1}", match.Index, item);
//prints Index : 0, Item:224859
}
}
This is a more procedural approach than Sriram's, but the main benefit is remembering your results in order to use them later in your program.
Basically, the string is split based on the # delimiter, which returns a string[] which holds each number inside. Then, for each string you iterate through the characters and check to see if the current character at i matches the next character at i + 1. If so, the earliest appearance of a duplicate digit is at i, so i is remembered and we break out of the loop that processes chars.
Since int is a non-nullable type, I decided to use -1 to indicate that a match was not found in a string.
Dictionary<string, int> results = new Dictionary<string, int>();
string text = "1234#224859#123567#11#4322#43#155";
string[] list = text.Split('#');
foreach (string s in list)
{
int tempResult = -1;
for (int i = 0; i < s.Length - 1; i++)
{
if(s.ElementAt(i) == s.ElementAt(i + 1))
{
tempResult = i;
break;
}
}
results.Add(s, tempResult);
}
foreach (KeyValuePair<string, int> pair in results)
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
Output:
1234: -1
224859: 0
123567: -1
11: 0
4322: 2
43: -1
155: 1
here's another Regex that works
int indexof = -1;
String input = "3492883#32280948093284#990303294";
string[] numbers = input.Split('#');
foreach(string n in numbers)
{
Match m=Regex.Match(n, #"(\d)\1+");
if (m.Success)
{
indexof = m.Index;
}
}
Would this do what you are looking for?
string text = File.ReadAllText(file);
string[] list = text.Split(new char[] { '#' });
Then, after you have the strings separated:
foreach (string s in list)
{
int pos = HasDoubleCharacter(s);
if (pos > -1)
{
// do something
}
}
private static int HasDoubleCharacter(string text)
{
int pos = 0;
char[] c3 = text.ToCharArray();
char lastChar = (char)0;
foreach (char c in c3)
{
if (lastChar == c)
return pos;
lastChar = c;
pos++;
}
return -1;
}
Or are you just looking for the list of positions of all doubles in the original text. If so (and you don't need to act on the various strings separately, you might try this:
private static List<int> FindAllDoublePositions(string text)
{
List<int> positions = new List<int>();
char[] ca = text.ToCharArray();
char lastChar = (char)0;
for (int pos = 0; pos < ca.Length; pos++)
{
if (Char.IsNumber(ca[pos]) && lastChar == ca[pos])
positions.Add(pos);
lastChar = ca[pos];
}
return positions;
}
If your looking for a specific string pattern, Regex is most likely to be your best friend :
string text = "1234#224859#123567asdashjehqwjk4234#244859#123567asdhajksdhqjkw1434#244859#123567";
var results = Regex.Matches(text, #"\d{4}#(?<Value>\d{6})#\d{4}");
var allValues = "";
foreach (Match result in results)
{
allValues = result.Groups["Value"].Value + " => ";
Console.WriteLine(" => ", result.Value);
}

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;
}

Function that generates strings according to input

I need a C# function that takes 2 strings as an input and return an array of all possible combinations of strings.
private string[] FunctionName(string string1, string string2)
{
//code
}
The strings input will be in the following format:
string1: basement
string2: a*fa
Now what I need is all combinations of possible strings using the characters in String2 (ignoring the * symbols), and keeping them in the same character position like this:
baaement, baaefent, baaefena, basefent, basemena, etc.
EDIT:
This is not homework. I need this function for a piece of a program I am doing.
The following is the code I have so far but it has some bugs.
static List<string> combinations = new List<string>();
static void Main(string[] args)
{
//include trimming of input string
string FoundRes = "incoming";
string AltRes = "*2*45*78";
List<int> loc = new List<int>();
string word = "";
for (int i = 0; i < AltRes.Length; i++)
{
if (AltRes[i] != '*')
{
loc.Add(i);
word += AltRes[i];
}
}
generate(word);
string[] aaa = InsertSymbol(FoundRes, loc.ToArray(), AltRes, combinations);
Console.WriteLine("input string: " + FoundRes);
Console.WriteLine("Substitute string: " + AltRes);
Console.WriteLine("============Output============");
for (int j = 0; j < aaa.Length; j++)
{
Console.WriteLine(aaa[j]);
}
Console.ReadKey();
}//
private static void generate(string word)
{
// Add this word to combination results set
if (!combinations.Contains(word))
combinations.Add(word);
// If the word has only one character, break the recursion
if (word.Length == 1)
{
if (!combinations.Contains(word))
combinations.Add(word);
return;
}
// Go through every position of the word
for (int i = 0; i < word.Length; i++)
{
// Remove the character at the current position
// call this method with the String
generate(word.Substring(0, i) + word.Substring(i + 1));
}
}//
private static string[] InsertSymbol(string orig, int[] loc, string alternative, List<string> Chars)
{
List<string> CombinationsList = new List<string>();
string temp = "";
for (int i = 0; i < Chars.Count; i++)
{
temp = orig;
for (int j = 0; j < Chars[i].Length; j++)
{
string token = Chars[i];
if (alternative.IndexOf(token[j]) == loc[j])
{
temp = temp.Remove(loc[j], 1);
temp = temp.Insert(loc[j], token[j].ToString());
// int pos = sourceSubst.IndexOf(token[j]);
// sourceSubst = sourceSubst.Remove(pos, 1);
// sourceSubst = sourceSubst.Insert(pos, ".");
}
else
{
temp = temp.Remove(alternative.IndexOf(token[j]), 1);
temp = temp.Insert(alternative.IndexOf(token[j]), token[j].ToString());
}
}
CombinationsList.Add(temp);
}
return CombinationsList.ToArray();
}//
It does sound like homework. As a suggestion, I would ignore the first parameter and focus on getting all possible permutations of the second string. What's turned off, what's turned on, etc. From that list, you can easily come up with a method of swapping out characters of the first string.
On that note, I'm in the uncomfortable position of having a function ready to go but not wanting to post it because of the homework implication. I'd sure love for somebody to review it, though! And technically, there's two functions involved because I just happened to already have a generic function to generate subsets lying around.
Edit: OP says it isn't homework, so here is what I came up with. It has been refactored a bit since the claim of two functions, and I'm more than open to criticism.
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main()
{
string original = "phenomenal";
string pattern = "*xo**q*t**";
string[] replacements = StringUtility.GetReplacementStrings(original, pattern, true);
foreach (string replacement in replacements)
Console.WriteLine(replacement);
Console.Read();
}
public static class StringUtility
{
public static string[] GetReplacementStrings(string original, string pattern, bool includeOriginal)
{
// pattern and original might not be same length
int maxIndex = Math.Max(original.Length, pattern.Length);
List<int> positions = GetPatternPositions(pattern, maxIndex, '*');
List<int[]> subsets = ArrayUtility.CreateSubsets(positions.ToArray());
List<string> replacements = GenerateReplacements(original, pattern, subsets);
if (includeOriginal)
replacements.Insert(0, original);
return replacements.ToArray();
}
private static List<string> GenerateReplacements(string original, string pattern, List<int[]> subsets)
{
List<string> replacements = new List<string>();
char[] temp = new char[original.Length];
foreach (int[] subset in subsets)
{
original.CopyTo(0, temp, 0, original.Length);
foreach (int index in subset)
{
temp[index] = pattern[index];
}
replacements.Add(new string(temp));
}
return replacements;
}
private static List<int> GetPatternPositions(string pattern, int maxIndex, char excludeCharacter)
{
List<int> positions = new List<int>();
for (int i = 0; i < maxIndex; i++)
{
if (pattern[i] != excludeCharacter)
positions.Add(i);
}
return positions;
}
}
public static class ArrayUtility
{
public static List<T[]> CreateSubsets<T>(T[] originalArray)
{
List<T[]> subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] { originalArray[i] });
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
}
}
since it's hopw work I'd only suggest some way to solve the problem rather than writing the code.
if you loop the second parameter every time you hit a letter you'll have to options either use the letter from the first argument or the letter from the second. collect all these optins together with the index. keep a list of the parts from the first argument that will never change. iterate thorugh those two lists to created all the possible permutations
Decimal to Binary converted code is stolon copied from here.
static void Main()
{
string string1 = "basement";
string string2 = "**a*f**a";
string[] result = GetCombinations(string1, string2);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
private static string[] GetCombinations(string string1, string string2)
{
var list = new List<List<char>> { new List<char>(), new List<char>() };
var cl = new List<char>();
List<string> result = new List<string>();
for (int i = 0; i < string1.Length; i++)
{
if (string2[i] == '*')
{
cl.Add(string1[i]);
}
else
{
list[0].Add(string1[i]);
list[1].Add(string2[i]);
}
}
int l = list[0].Count;
for (int i = 0; i < (Int64)Math.Pow(2.0,l); i++)
{
string s = ToBinary(i, l);
string ss = "";
int x = 0;
int y = 0;
for (int I = 0; I < string1.Length; I++)
{
if (string2[I] == '*')
{
ss += cl[x].ToString();
x++;
}
else
{
ss += (list[int.Parse(s[y].ToString())][y]);
y++;
}
}
result.Add(ss);
}
return result.ToArray<string>();
}
public static string ToBinary(Int64 Decimal, int width)
{
Int64 BinaryHolder;
char[] BinaryArray;
string BinaryResult = "";
while (Decimal > 0)
{
BinaryHolder = Decimal % 2;
BinaryResult += BinaryHolder;
Decimal = Decimal / 2;
}
BinaryArray = BinaryResult.ToCharArray();
Array.Reverse(BinaryArray);
BinaryResult = new string(BinaryArray);
var d = width - BinaryResult.Length;
if (d != 0) for (int i = 0; i < d; i++) BinaryResult = "0" + BinaryResult;
return BinaryResult;
}
which password cracker do you want to program? :)
how about
if string2 contains '*'
foreach(char ch in string1)
replace first * with ch,
execute FunctionName
else
print string2

Categories

Resources