Related
I have an array of integers where each value will have distinct meanings.The first value means the length of permutation, the second value represent the length of initial prefix and rest of integers are single integer that make up prefix of all permutations.
For e.g. if the array has elements {5,2,1,4}
where 5 is the number of elements in the permutation array.
and 2 is the length of the integer that will makeup the first 2 elements prefix in the array permutation. 1,4 are the prefix integers i.e. length 2 in 5 element permutation combination so missing elements are 2,3,5 where 1&4 being common prefix across all permutations as below
[14235][14253][14325][14352][14523][14532] where input array is {5,2,1,4}
How to achieve this?
I have below code to get the permutation of one missing elements 2,3 & 5 but I am not getting how to program the entire the solution
static void Main(string[] args)
{
int output;
int ip1;
ip1 = Convert.ToInt32(Console.ReadLine());
int ip2_size = 0;
ip2_size = Convert.ToInt32(Console.ReadLine());
int[] ip2 = new int[ip2_size];
int ip2_item;
for (int ip2_i = 0; ip2_i < ip2_size; ip2_i++)
{
ip2_item = Convert.ToInt32(Console.ReadLine());
ip2[ip2_i] = ip2_item;
}
output = correctResult(ip1, ip2);
Console.WriteLine(output);
}
static int correctResult(int n, int[] arr)
{
int permLength = 0;
int prefLength = 0;
int result = 0;
permLength = n;
prefLength = arr.Length;
int[] permArray = new int[permLength];
int len = 0;
var missingNum = Enumerable.Range(1,
permLength).Except(arr).ToArray<int>();
if (permLength < (missingNum.Length + len))
{
result = -1;
}
else
{
for (int i = 0; i < missingNum.Length; i++)
{
permArray[prefLength + i] = missingNum[i];
}
result = permute(missingNum, 0, missingNum.Length - 1);
}
return result;
}
static int permute(int[] arry, int i, int n)
{
int j;
if (i == n)
{
int s1, s2;
s1 = s2 = 0;
for (int a = 0; a < n - 1; a++)
{
for (int b = a + 1; b < n; b++)
{
if (arry[a] > arry[b])
{
s1++;
}
}
s2 = s2 + Math.Max(0, a + 1 - arry[a]);
}
int count = 0;
if (s1 == s2)
count++;
return count;
}
else
{
int count = 0;
for (j = i; j <= n; j++)
{
swap(ref arry[i], ref arry[j]);
count += permute(arry, i + 1, n);
swap(ref arry[i], ref arry[j]);
}
return count;
}
}
static void swap(ref int a, ref int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
Try solving this with immutable types, its easier to reason about them. If, after solving the problem, you have a performance goal you haven't met then you can start trying to optimize the code.
Consider the following approach with an immutable stack that keeps track of the current permutation:
static IEnumerable<IEnumerable<int>> GetPermutations(IList<int> input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
if (input.Count < 2)
throw new ArgumentException("Input does not have a valid format.");
var setSize = input[0];
var prefixSize = input[1];
if (prefixSize != input.Count - 2)
throw new ArgumentException("Input does not have a valid format.");
if (input.Skip(2).Any(i => i > setSize)) //we are assuming, per example, that valid range starts at 1.
throw new ArgumentException("Input does not have a valid format.");
//Ok, we've got a valid input, interesting stuff starts here.
var prefix = input.Skip(2).ToArray();
var initialSet = Enumerable.Range(1, setSize)
.Except(prefix)
.ToArray();
foreach (var p in getPermutations(ImmutableStack<int>.Empty, initialSet))
{
yield return prefix.Concat(p);
}
IEnumerable<IEnumerable<int>> getPermutations(ImmutableStack<int> permutation, IEnumerable<int> set)
{
if (permutation.Count == setSize - prefixSize)
{
yield return permutation;
}
else
{
foreach (var i in set)
{
foreach (var p in getPermutations(permutation.Push(i), set.Except(new[] { i })))
{
yield return p;
}
}
}
}
}
And that is it, solving your problem was about 10-12 lines of real code (not considering input validation). Note that I am using some c#7 features here, but its easily translatable to previous versions of the language. Also I'd like to underline the argument validation we are doing upfront; make sure you have a valid input before trying out anything.
For ImmutableStack<T> you can use the one in System.Collections.Immutable (you have to download the NuGet package) or implement your own, its simple:
private class ImmutableStack<T>: IEnumerable<T>
{
public static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
private readonly T head;
private readonly ImmutableStack<T> tail;
private ImmutableStack() { }
private ImmutableStack(T head, ImmutableStack<T> tail)
{
Debug.Assert(tail != null);
this.head = head;
this.tail = tail;
Count = tail.Count + 1;
}
public int Count { get; }
public T Peek() =>
this != Empty ? head : throw new InvalidOperationException("Empty stack.");
public ImmutableStack<T> Pop() =>
this != Empty ? tail : throw new InvalidOperationException("Empty stack.");
public ImmutableStack<T> Push(T item) => new ImmutableStack<T>(item, this);
public IEnumerator<T> GetEnumerator()
{
var current = this;
while (current != Empty)
{
yield return current.head;
current = current.tail;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
If you use the collections in System.Collections.Immutable, then you'll probably want to use some kind of immutable set for initalSet and set.
You can rewrite your permute method (based on this answer):
private static IEnumerable<IEnumerable<T>> Permute<T>(List<T> prefix, List<T> suffix)
{
for (var i = 0; i < suffix.Count; ++i)
{
var newPrefix = new List<T>(prefix) {suffix[i]};
var newSuffix = new List<T>(suffix.Take(i).Concat(suffix.Skip(i + 1)));
if (newSuffix.Count == 0)
{
yield return newPrefix;
continue;
}
foreach (var permutation in Permute(newPrefix, newSuffix))
yield return permutation;
}
}
And use it like this:
public static void PrintAllPermutations()
{
var input = new[] {5, 2, 1, 4};
var prefix = input.Skip(2).Take(input[1]).ToList();
var suffx = Enumerable.Range(1, input[0]).Except(prefix).ToList();
foreach (var permutation in Permute(prefix, suffx))
Console.WriteLine(string.Join(", ", permutation));
}
Reult would be:
1, 4, 2, 3, 5
1, 4, 2, 5, 3
1, 4, 3, 2, 5
1, 4, 3, 5, 2
1, 4, 5, 2, 3
1, 4, 5, 3, 2
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.
Recently I wondered what might be the smallest implementation of an IEumerable which returns a given number of prime numbers. It should fit in this program:
static int Main(string[] args)
{
while(true)
{
Console.WriteLine("How many Primes?");
string line = Console.ReadLine();
if (line.Trim() == "") break;
int numPrimes;
if(!int.TryParse(line.Trim(), out numPrimes)) continue;
int i = 1;
foreach(int p in PrimeNumbers(numPrimes))
{
Console.WriteLine("{0}: {1}", i++, p);
}
}
return 0;
}
My attempt looks like this:
static IEnumerable<int> PrimeNumbers(int numPrimes)
{
yield return 2; // first prime number
for(int n=1, p = 3; n < numPrimes; p+=2)
{
if (!checkIfPrime(p)) continue;
n++;
yield return p;
}
}
// p > 2, odd
private static bool checkIfPrime(int p)
{
for (int t = 3; t <= Math.Sqrt(p); t += 2)
{
if (p % t == 0) return false;
}
return true;
}
It is an Iterator which yield returns all the prime numbers.
Yet another example of smallest C# program:
static IEnumerable<int> PrimeNumbers(int n)
{
return Enumerable.Range(2, int.MaxValue - 2)
.Where(i => ParallelEnumerable.Range(2, Math.Max(0, (int)Math.Sqrt(i) - 1))
.All(j => i % j != 0))
.Take(n);
}
public static IEnumerable<int> PrimeNumbers(int NumberPrimes)
{
yield return 2;
for (int i = 3; i < NumberPrimes; i = i + 2)
{
bool IsPrime = true;
System.Threading.Tasks.Parallel.For(2, i, (o, state) =>
{
if (i % o == 0)
{
IsPrime = false;
state.Break();
}
});
if (IsPrime)
{
yield return i;
}
}
}
I have a list of Offers, from which I want to create "chains" (e.g. permutations) with limited chain lengths.
I've gotten as far as creating the permutations using the Kw.Combinatorics project.
However, the default behavior creates permutations in the length of the list count. I'm not sure how to limit the chain lengths to 'n'.
Here's my current code:
private static List<List<Offers>> GetPerms(List<Offers> list, int chainLength)
{
List<List<Offers>> response = new List<List<Offers>>();
foreach (var row in new Permutation(list.Count).GetRows())
{
List<Offers> innerList = new List<Offers>();
foreach (var mix in Permutation.Permute(row, list))
{
innerList.Add(mix);
}
response.Add(innerList);
innerList = new List<Offers>();
}
return response;
}
Implemented by:
List<List<AdServer.Offers>> lst = GetPerms(offers, 2);
I'm not locked in KWCombinatorics if someone has a better solution to offer.
Here's another implementation which I think should be faster than the accepted answer (and it's definitely less code).
public static IEnumerable<IEnumerable<T>> GetVariationsWithoutDuplicates<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items.Distinct()
from permutation in GetVariationsWithoutDuplicates(items.Where(i => !EqualityComparer<T>.Default.Equals(i, item)).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<IEnumerable<T>> GetVariations<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items
from permutation in GetVariations(Remove(item, items).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<T> Prepend<T>(T first, IEnumerable<T> rest)
{
yield return first;
foreach (var item in rest) yield return item;
}
public static IEnumerable<T> Remove<T>(T item, IEnumerable<T> from)
{
var isRemoved = false;
foreach (var i in from)
{
if (!EqualityComparer<T>.Default.Equals(item, i) || isRemoved) yield return i;
else isRemoved = true;
}
}
On my 3.1 GHz Core 2 Duo, I tested with this:
public static void Test(Func<IList<int>, int, IEnumerable<IEnumerable<int>>> getVariations)
{
var max = 11;
var timer = System.Diagnostics.Stopwatch.StartNew();
for (int i = 1; i < max; ++i)
for (int j = 1; j < i; ++j)
getVariations(MakeList(i), j).Count();
timer.Stop();
Console.WriteLine("{0,40}{1} ms", getVariations.Method.Name, timer.ElapsedMilliseconds);
}
// Make a list that repeats to guarantee we have duplicates
public static IList<int> MakeList(int size)
{
return Enumerable.Range(0, size/2).Concat(Enumerable.Range(0, size - size/2)).ToList();
}
Unoptimized
GetVariations 11894 ms
GetVariationsWithoutDuplicates 9 ms
OtherAnswerGetVariations 22485 ms
OtherAnswerGetVariationsWithDuplicates 243415 ms
With compiler optimizations
GetVariations 9667 ms
GetVariationsWithoutDuplicates 8 ms
OtherAnswerGetVariations 19739 ms
OtherAnswerGetVariationsWithDuplicates 228802 ms
You're not looking for a permutation, but for a variation. Here is a possible algorithm. I prefer iterator methods for functions that can potentially return very many elements. This way, the caller can decide if he really needs all elements:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
var variationElements = new HashSet<T>(); //for duplicate detection
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
var valid = true;
for (int i = 0; i < length; ++i)
{
var element = offers[startIndices[i]];
if (variationElements.Contains(element))
{
valid = false;
break;
}
variation.Add(element);
variationElements.Add(element);
}
if (valid)
yield return variation;
//Count up the indices
startIndices[length - 1]++;
for (int i = length - 1; i > 0; --i)
{
if (startIndices[i] >= offers.Count)
{
startIndices[i] = 0;
startIndices[i - 1]++;
}
else
break;
}
variationElements.Clear();
}
}
The idea for this algorithm is to use a number in offers.Count base. For three offers, all digits are in the range 0-2. We then basically increment this number step by step and return the offers that reside at the specified indices. If you want to allow duplicates, you can remove the check and the HashSet<T>.
Update
Here is an optimized variant that does the duplicate check on the index level. In my tests it is a lot faster than the previous variant:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
for (int i = 0; i < length; ++i)
startIndices[i] = i;
var indices = new HashSet<int>(); // for duplicate check
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
for (int i = 0; i < length; ++i)
{
variation.Add(offers[startIndices[i]]);
}
yield return variation;
//Count up the indices
AddOne(startIndices, length - 1, offers.Count - 1);
//duplicate check
var check = true;
while (check)
{
indices.Clear();
for (int i = 0; i <= length; ++i)
{
if (i == length)
{
check = false;
break;
}
if (indices.Contains(startIndices[i]))
{
var unchangedUpTo = AddOne(startIndices, i, offers.Count - 1);
indices.Clear();
for (int j = 0; j <= unchangedUpTo; ++j )
{
indices.Add(startIndices[j]);
}
int nextIndex = 0;
for(int j = unchangedUpTo + 1; j < length; ++j)
{
while (indices.Contains(nextIndex))
nextIndex++;
startIndices[j] = nextIndex++;
}
break;
}
indices.Add(startIndices[i]);
}
}
}
}
int AddOne(int[] indices, int position, int maxElement)
{
//returns the index of the last element that has not been changed
indices[position]++;
for (int i = position; i > 0; --i)
{
if (indices[i] > maxElement)
{
indices[i] = 0;
indices[i - 1]++;
}
else
return i;
}
return 0;
}
If I got you correct here is what you need
this will create permutations based on the specified chain limit
public static List<List<T>> GetPerms<T>(List<T> list, int chainLimit)
{
if (list.Count() == 1)
return new List<List<T>> { list };
return list
.Select((outer, outerIndex) =>
GetPerms(list.Where((inner, innerIndex) => innerIndex != outerIndex).ToList(), chainLimit)
.Select(perms => (new List<T> { outer }).Union(perms).Take(chainLimit)))
.SelectMany<IEnumerable<IEnumerable<T>>, List<T>>(sub => sub.Select<IEnumerable<T>, List<T>>(s => s.ToList()))
.Distinct(new PermComparer<T>()).ToList();
}
class PermComparer<T> : IEqualityComparer<List<T>>
{
public bool Equals(List<T> x, List<T> y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(List<T> obj)
{
return (int)obj.Average(o => o.GetHashCode());
}
}
and you'll call it like this
List<List<AdServer.Offers>> lst = GetPerms<AdServer.Offers>(offers, 2);
I made this function is pretty generic so you may use it for other purpose too
eg
List<string> list = new List<string>(new[] { "apple", "banana", "orange", "cherry" });
List<List<string>> perms = GetPerms<string>(list, 2);
result
I have a large string I need to parse, and I need to find all the instances of extract"(me,i-have lots. of]punctuation, and store the index of each to a list.
So say this piece of string was in the beginning and middle of the larger string, both of them would be found, and their indexes would be added to the List. and the List would contain 0 and the other index whatever it would be.
I've been playing around, and the string.IndexOf does almost what I'm looking for, and I've written some code - but it's not working and I've been unable to figure out exactly what is wrong:
List<int> inst = new List<int>();
int index = 0;
while (index < source.LastIndexOf("extract\"(me,i-have lots. of]punctuation", 0) + 39)
{
int src = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
inst.Add(src);
index = src + 40;
}
inst = The list
source = The large string
Any better ideas?
Here's an example extension method for it:
public static List<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
List<int> indexes = new List<int>();
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
return indexes;
indexes.Add(index);
}
}
If you put this into a static class and import the namespace with using, it appears as a method on any string, and you can just do:
List<int> indexes = "fooStringfooBar".AllIndexesOf("foo");
For more information on extension methods, http://msdn.microsoft.com/en-us/library/bb383977.aspx
Also the same using an iterator:
public static IEnumerable<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
break;
yield return index;
}
}
Why don't you use the built in RegEx class:
public static IEnumerable<int> GetAllIndexes(this string source, string matchString)
{
matchString = Regex.Escape(matchString);
foreach (Match match in Regex.Matches(source, matchString))
{
yield return match.Index;
}
}
If you do need to reuse the expression then compile it and cache it somewhere. Change the matchString param to a Regex matchExpression in another overload for the reuse case.
using LINQ
public static IEnumerable<int> IndexOfAll(this string sourceString, string subString)
{
return Regex.Matches(sourceString, subString).Cast<Match>().Select(m => m.Index);
}
Polished version + case ignoring support:
public static int[] AllIndexesOf(string str, string substr, bool ignoreCase = false)
{
if (string.IsNullOrWhiteSpace(str) ||
string.IsNullOrWhiteSpace(substr))
{
throw new ArgumentException("String or substring is not specified.");
}
var indexes = new List<int>();
int index = 0;
while ((index = str.IndexOf(substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) != -1)
{
indexes.Add(index++);
}
return indexes.ToArray();
}
It could be done in efficient time complexity using KMP algorithm in O(N + M) where N is the length of text and M is the length of the pattern.
This is the implementation and usage:
static class StringExtensions
{
public static IEnumerable<int> AllIndicesOf(this string text, string pattern)
{
if (string.IsNullOrEmpty(pattern))
{
throw new ArgumentNullException(nameof(pattern));
}
return Kmp(text, pattern);
}
private static IEnumerable<int> Kmp(string text, string pattern)
{
int M = pattern.Length;
int N = text.Length;
int[] lps = LongestPrefixSuffix(pattern);
int i = 0, j = 0;
while (i < N)
{
if (pattern[j] == text[i])
{
j++;
i++;
}
if (j == M)
{
yield return i - j;
j = lps[j - 1];
}
else if (i < N && pattern[j] != text[i])
{
if (j != 0)
{
j = lps[j - 1];
}
else
{
i++;
}
}
}
}
private static int[] LongestPrefixSuffix(string pattern)
{
int[] lps = new int[pattern.Length];
int length = 0;
int i = 1;
while (i < pattern.Length)
{
if (pattern[i] == pattern[length])
{
length++;
lps[i] = length;
i++;
}
else
{
if (length != 0)
{
length = lps[length - 1];
}
else
{
lps[i] = length;
i++;
}
}
}
return lps;
}
and this is an example of how to use it:
static void Main(string[] args)
{
string text = "this is a test";
string pattern = "is";
foreach (var index in text.AllIndicesOf(pattern))
{
Console.WriteLine(index); // 2 5
}
}
Without Regex, using string comparison type:
string search = "123aa456AA789bb9991AACAA";
string pattern = "AA";
Enumerable.Range(0, search.Length)
.Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
.Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length),StringComparison.OrdinalIgnoreCase))
.Select(searchbit => searchbit.Index)
This returns {3,8,19,22}. Empty pattern would match all positions.
For multiple patterns:
string search = "123aa456AA789bb9991AACAA";
string[] patterns = new string[] { "aa", "99" };
patterns.SelectMany(pattern => Enumerable.Range(0, search.Length)
.Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
.Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length), StringComparison.OrdinalIgnoreCase))
.Select(searchbit => searchbit.Index))
This returns {3, 8, 19, 22, 15, 16}
I noticed that at least two proposed solutions don't handle overlapping search hits. I didn't check the one marked with the green checkmark. Here is one that handles overlapping search hits:
public static List<int> GetPositions(this string source, string searchString)
{
List<int> ret = new List<int>();
int len = searchString.Length;
int start = -1;
while (true)
{
start = source.IndexOf(searchString, start +1);
if (start == -1)
{
break;
}
else
{
ret.Add(start);
}
}
return ret;
}
public List<int> GetPositions(string source, string searchString)
{
List<int> ret = new List<int>();
int len = searchString.Length;
int start = -len;
while (true)
{
start = source.IndexOf(searchString, start + len);
if (start == -1)
{
break;
}
else
{
ret.Add(start);
}
}
return ret;
}
Call it like this:
List<int> list = GetPositions("bob is a chowder head bob bob sldfjl", "bob");
// list will contain 0, 22, 26
Hi nice answer by #Matti Virkkunen
public static List<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
List<int> indexes = new List<int>();
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
return indexes;
indexes.Add(index);
index--;
}
}
But this covers tests cases like AOOAOOA
where substring
are AOOA and AOOA
Output 0 and 3
#csam is correct in theory, although his code will not complie and can be refractored to
public static IEnumerable<int> IndexOfAll(this string sourceString, string matchString)
{
matchString = Regex.Escape(matchString);
return from Match match in Regex.Matches(sourceString, matchString) select match.Index;
}
public static Dictionary<string, IEnumerable<int>> GetWordsPositions(this string input, string[] Susbtrings)
{
Dictionary<string, IEnumerable<int>> WordsPositions = new Dictionary<string, IEnumerable<int>>();
IEnumerable<int> IndexOfAll = null;
foreach (string st in Susbtrings)
{
IndexOfAll = Regex.Matches(input, st).Cast<Match>().Select(m => m.Index);
WordsPositions.Add(st, IndexOfAll);
}
return WordsPositions;
}
Based on the code I've used for finding multiple instances of a string within a larger string, your code would look like:
List<int> inst = new List<int>();
int index = 0;
while (index >=0)
{
index = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
inst.Add(index);
index++;
}
I found this example and incorporated it into a function:
public static int solution1(int A, int B)
{
// Check if A and B are in [0...999,999,999]
if ( (A >= 0 && A <= 999999999) && (B >= 0 && B <= 999999999))
{
if (A == 0 && B == 0)
{
return 0;
}
// Make sure A < B
if (A < B)
{
// Convert A and B to strings
string a = A.ToString();
string b = B.ToString();
int index = 0;
// See if A is a substring of B
if (b.Contains(a))
{
// Find index where A is
if (b.IndexOf(a) != -1)
{
while ((index = b.IndexOf(a, index)) != -1)
{
Console.WriteLine(A + " found at position " + index);
index++;
}
Console.ReadLine();
return b.IndexOf(a);
}
else
return -1;
}
else
{
Console.WriteLine(A + " is not in " + B + ".");
Console.ReadLine();
return -1;
}
}
else
{
Console.WriteLine(A + " must be less than " + B + ".");
// Console.ReadLine();
return -1;
}
}
else
{
Console.WriteLine("A or B is out of range.");
//Console.ReadLine();
return -1;
}
}
static void Main(string[] args)
{
int A = 53, B = 1953786;
int C = 78, D = 195378678;
int E = 57, F = 153786;
solution1(A, B);
solution1(C, D);
solution1(E, F);
Console.WriteLine();
}
Returns:
53 found at position 2
78 found at position 4
78 found at position 7
57 is not in 153786
How is this alternative implementation?
public static class MyExtensions
{
public static int HowMany(this string str, char needle)
{
int counter = 0;
int nextIndex = 0;
for (; nextIndex != -1; )
{
nextIndex = str.IndexOf(needle, nextIndex);
if (nextIndex != -1)
{
counter++;
//step over to the next char
nextIndex++;
}
}
return counter;
}
}
you can use linq to select and enumerate all elements, then find by any string:
I've created a class:
class Pontos
{
//index on string
public int Pos { get; set; }
//caractere
public string Caractere { get; set; }
}
And use like this:
int count = 0;
var pontos = texto.Select(y => new Pontos { Pos = count++, Caractere = y.ToString() }).Where(x=>x.Caractere == ".").ToList();
then:
input string:
output list:
PS: SeForNumero is another field of my class, I need this for my own purposes, but is not necessary to this use.