How to slice string on substrings that contain n characters c#? - c#

The function gets a string of numbers (e.g. "23559009") and the length of substrings value (e.g. 2), I need to implement the function so that it will slice the string of numbers by the value (e.g. "23", "35", "55", "59", "90", "00", "09") AND will return this data as array.
For now I have initial code for tests:
using System;
public static class Series
{
public static string[] Slices(string numbers, int sliceLength)
{
int digits = numbers.Length;
if(digits != null || digits > sliceLength || sliceLength < 1)
throw new ArgumentException();
else
{
string[] dgts = {"1", "2"};
return dgts;
}
}
}

Using Linq:
public static string[] Slices(string numbers, int sliceLength) =>
Enumerable.Range(0, numbers.Length - sliceLength + 1).
Select(i => numbers.Substring(i, sliceLength)).
ToArray();
Note that the single character last entry will be ignored + you may want to validate the parameters (numbers not null and sliceLength > 0).
Fiddle

substring code for this will have major redundancy. send the string to a char array, then do a loop
char[] charray = inputstring.toCharArray();
List<string> deuces= new List<string>();
for(int i=0;i<charray.length;i++){
string holder = charray[i]+charray[i+1];
deuces.Add(holder)
}
keep in mind this is pseudo, everything you need is here, you will just have to create the variables, and make sure syntax is correct.
in the line : for(int i=0;i
the two represents the value you want to slice by,
in the line : string holder = charray[i]+charray[i+1];
you will need to add another char, for the amount of your split. i.e 3 would be:
string holder = charray[i].toString()+charray[i+1].toString+charray[i+2];
keep in mind if your split value ( in your case two) changes regularly you can nest another for loop

You have some errors in your evaluation of incorrect inputs, then getting your result in using normal for loop isn't difficult
public string[] Slices(string numbers, int sliceLength)
{
int digits = numbers.Length;
string[] result = new string[numbers.Length + 1 - sliceLength];
if (digits < sliceLength || sliceLength < 1)
throw new ArgumentException();
else
{
for(int x = 0; x < numbers.Length + 1 - sliceLength; x++)
result[x] = numbers.Substring(x, sliceLength);
return result;
}
}

Related

assigning numbers entered in a row to an array 3 6 23 12 4 a[0]=3 a[1]=6 a[2]=23 a[3]=12 a[4]=10

string[] n = Console.ReadLine().Split();
for (int i = 1; i <6; i++)
{
int[] a = long.Parse(n[i]);
}
If each number in a row separated with whitespace - you can use your Split more efficiently:
int[] array = Console.ReadLine().Split().Select(int.Parse).ToArray(); // Improved according to #Caius Jard comment
If need array of longs - replace int.Parse with long.Parse and declare variable as long[] array.
You need to add using System.Linq to get access to ToArray extension method.
EDIT.
Insprired by #Caius Jard, non-LINQ version:
// Read input line and split it by whitespace (default)
string[] values = Console.ReadLine().Split();
// Declare arrays for Int or Long values.
// Arrays sizes equals to size of array of input values
int[] arrayOfInts = new int[values.Length];
long[] arrayOfLongs = new long[values.Length];
// Iterate with for loop over amount of input values.
for (int i = 0; i < values.Length; i++)
{
// Convert trimmed input value to Int32
arrayOfInts[i] = int.Parse(values[i].Trim());
// Or to Int64
arrayOfLongs[i] = long.Parse(values[i].Trim());
}
int.Parse and long.Parse may be replaced with Convert.ToInt32 and Convert.ToInt64 if needed.
Please, don't use magic constants: i < 6. Here 6 doesn't necessary equal to n.Length.
You can put it as
string[] n = Console.ReadLine().Split();
List<int> list = new List<int>();
for (int i = 0; i < n.Length; ++i) {
if (int.TryParse(n[i], out int value))
list.Add(value);
else {
// Invalid item within user input, say "bla-bla-bla"
//TODO: either reject the input or ignore the item (here we ignore)
}
}
if (list.Count == a.Length) {
// We have exactly a.Length - 6 valid integer items
for (int i = 0; i < a.Length; ++i)
a[i] = list[i];
}
else {
//TODO: erroneous input: we have too few or too many items
}

How can I search strings inside an array using wild cards? C#

The parameter is a string that has a number in each word. I need to search that word for the number. My solution so far is to split the string up into a string array, and use Array.IndexOf to find the matching index of my search. However I haven't been able to find a way to successfully use wildcards. Using string.Contains seems to work, but searching with Array.IndexOf doesn't.
How can I search a string array element for a word that contains a number and return it's index? 1-9.
public static string Order(string words)
{
string[] wordArr = words.Split(' ');
string[] wordsOrdered = new string[words.Length];
int k;
for (int i = 0, j = 1; i < wordsOrdered.Length; i++, j++)
{
if (words.Contains($"{j}"))
{
k = Array.IndexOf(wordArr, $"{j}");
if (k != -1)
wordsOrdered[i] = wordArr[k];
}
}
return words = wordsOrdered.ToString();
}
A Regular Expression that looks for the presence of digits in your words seems the most simple solution
public static string Order(string words)
{
string[] wordArr = words.Split(' ');
string[] wordsOrdered = new string[wordArr.Length];
Regex r = new Regex(#"\d+");
for (int i = 0; i < wordArr.Length; i++)
{
var m = r.Match(wordArr[i]);
if(m.Success)
{
int index = Convert.ToInt32(m.Value);
wordsOrdered[index-1] = wordArr[i];
}
}
return string.Join(" ", wordsOrdered);
}
This code assumes that all your words have at least one number internally and the lowest number start at 1. (A 0 will result in an index out of range exception) and also you shouldn't have numbers that are greater than then count of the input words.

Creating strings from a template by replacing placeholders by all permutations of an input set

I want to make a simple generator of strings.
User inputs a "template" for string. Template can have placeholders in any place in it.
Then he inputs possible characters that can fit into any placeholder in string.
How it should work:
INPUT:
a.b.
123
OUTPUT:
[
"a1b1", "a1b2", "a1b3",
"a2b1", "a2b2", "a2b3",
"a3b1", "a3b2", "a3b3"
]
I found some of my old python code, but i don't understand it at all.
I split the input string to array of strings and array of dots.
Then I tried to increment just dots and each time just concat those two arrays in the right way.
But I found a new trouble.
string[] splitted = kt_NonCur.Split('.'); // array of constant strings
char[] nch = new char[splitted.Length - 1]; // array of new chars (generated)
char lgc = goodLetters.Last( ); // last good char
for( int i = 0; i < nch.Length - 1; i++ ) // set up all nch to first letter
nch[i] = goodLetters[0];
while( nch.Last( ) != lgc ) { // until last nch is set to last good char
outputData.Add($"{concatsplit(splitted, nch)}"); // concatsplit(s,n) concatenates two arrays into string
nch[0] = up(nch[0]); // up(char) gets next character from goodLetters. If there is no next, it returns first letter.
if( nch[0] == goodLetters[0] ) {
nch[1] = up(nch[1]);
if(nch[1] == goodLetters[0]){
nch[2] = up(nch[2]);
// .
// .
// .
}
}
}
And the problem is: I am facing a dilemma. Either find better way, or limit number of placeholders so that the code ladder is not too long. Of course I would add then some code that checks if it is the last and stop executing code for others, but I still would have to make
You can look at your problem this way: if you have P placeholders in your input string and the number of replacement characters is R, to construct every possibe output string you need at each step P numbers [0...R-1] (which can then serve as index into the replacement character list). Well, this is the definition of an integer with P digits in base R.
So let's write a helper class representing such integers:
class NDigitNumber
{
int[] _digits;
int _base;
// construct an integer with the specified numer of digits in the specified base
public NDigitNumber(int digits, int #base)
{
_digits = new int[digits];
_base = #base;
}
// get the digit at the specified position
public int this[int index] => _digits[index];
// increment the number, returns false on overflow
public bool Increment()
{
for (var pos = 0; pos < _digits.Length; pos++)
{
if (++_digits[pos] < _base)
break;
if (pos == _digits.Length-1)
return false;
for (var i = 0; i <= pos; i++)
_digits[i] = 0;
}
return true;
}
}
The Increment methods works like these mechanical counter devices where each digit wheel, when rotated from its maximum digit to the next, resets itself and all lower wheels to 0 and increments the next higher wheel.
Then we only have to iterate over all possible such integers to get the desired output:
var input = "a.b.";
var placeholder = '.';
var replacements = new[] { '1', '2', '3' };
// determine positions of placeholder in string
var placeholderPositions = new List<int>();
for (var i = 0; i < input.Length; i++)
{
if (input[i] == placeholder)
placeholderPositions.Add(i);
}
// iterate over all possible integers with
// placeholderPositions.Count digits
// in base replacements.Length
var number = new NDigitNumber(placeholderPositions.Count, replacements.Length);
do
{
var result = new StringBuilder(input);
for (var i = 0; i < placeholderPositions.Count; i++)
result[placeholderPositions[i]] = replacements[number[i]];
Console.WriteLine(result.ToString());
} while(number.Increment());
Output:
a1b1
a2b1
a3b1
a1b2
a2b2
a3b2
a1b3
a2b3
a3b3
Based on accepted answer of this post:
public static IEnumerable<string> Combinations(string template, string str, char placeholder)
{
int firstPlaceHolder = template.IndexOf(placeholder);
if (firstPlaceHolder == -1)
return new string[] { template };
string prefix = template.Substring(0, firstPlaceHolder);
string suffix = template.Substring(firstPlaceHolder + 1);
var recursiveCombinations = Combinations(suffix, str, placeholder);
return
from chr in str
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
Usage:
List<string> combinations = Combinations("a.b.", "123", '.').ToList();

Skipping a range of values in for loop C#

I'm trying to cycle through chars in a string.
string cycleMe = "Hi StackOverflow! Here is my string."
However, I want to skip over certain ranges of indexes. The ranges I want to skip over are stored in a List of objects, delims.
List<Delim> delims = delimCreator();
To retrieve each starting index and ending index for a range, I have to write a loop that accesses each "delim":
delims[0].getFirstIndex() //results in, say, index 2
delims[0].getLastIndex() //results in, say, index 4
delims[1].getFirstIndex() //results in, say, index 5
delims[1].getLastIndex() //results in, say, index 7
(there can be infinitely many "delim" objects in play)
If the above were my list, I'd want to print the string cycleMe, but skip all the chars between 2 and 4 (inclusive) and 5 and 7 (inclusive).
Expected output using the numbers above:
HiOverflow! Here is my string.
Here is the code I have written so far. It loops far more often than I'd expect (it loops ~x2 the number of characters in the string). Thanks in advance! =)
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
Debug.Log("test");
}
}
I assume that by skipping you meant you want to omit those characters from the original string. If that is the case, you can try Aggregate extension method like below.
string result = delims.Aggregate<Delim, string>(cycleMe, (str, d) => cycleMe = cycleMe.Remove(d.FirstIndex, (d.LastIndex - d.FirstIndex) + 1));
Make sure that the delim list is in the proper order.
Solution might be converting the string to char array, replacing the desired parts to spaces, and converting the output back to string.
Here is the modified version of your code:
string cycleMe = "Hi StackOverflow! Here is my string."
var charArray = cycleMe.ToCharArray(); // Converting to char array
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
// ORIGINAL: if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
if (x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex()){
Debug.Log("test");
charArray[x] = ' '; // Replacing the item with space
}
}
string output = new string(charArray); // Converting back to string
P.S. This is probably not the most optimal solution but at least it should work.
You should use LINQ for that
struct Delim
{
public int First { get; set; }
public int Last { get; set; }
}
static void Main(string[] args)
{
string cycleMe = "Hi StackOverflow! Here is my string.";
var delimns = new List<Delim> { new Delim { First=2, Last=4}, new Delim { First = 5, Last = 7 } };
var cut = cycleMe.Where((c, i) =>
!delimns.Any(d => i >= d.First && i <= d.Last));
Console.WriteLine(new string(cut.ToArray());
}
That means I am basically only selecting letters, at positions which are not part of any cutting range.
Also: Fix your naming. A delimiter is a character, not a position (numeric)

String Combinations With Character Replacement

I am trying to work through a scenario I haven't seen before and am struggling to come up with an algorithm to implement this properly. Part of my problem is a hazy recollection of the proper terminology. I believe what I am needing is a variation of the standard "combination" problem, but I could well be off there.
The Scenario
Given an example string "100" (let's call it x), produce all combinations of x that swap out one of those 0 (zero) characters for a o (lower-case o). So, for the simple example of "100", I would expect this output:
"100"
"10o"
"1o0"
"1oo"
This would need to support varying length strings with varying numbers of 0 characters, but assume there would never be more than 5 instances of 0.
I have this very simple algorithm that works for my sample of "100" but falls apart for anything longer/more complicated:
public IEnumerable<string> Combinations(string input)
{
char[] buffer = new char[input.Length];
for(int i = 0; i != buffer.Length; ++i)
{
buffer[i] = input[i];
}
//return the original input
yield return new string(buffer);
//look for 0's and replace them
for(int i = 0; i != buffer.Length; ++i)
{
if (input[i] == '0')
{
buffer[i] = 'o';
yield return new string(buffer);
buffer[i] = '0';
}
}
//handle the replace-all scenario
yield return input.Replace("0", "o");
}
I have a nagging feeling that recursion could be my friend here, but I am struggling to figure out how to incorporate the conditional logic I need here.
Your guess was correct; recursion is your friend for this challenge. Here is a simple solution:
public static IEnumerable<string> Combinations(string input)
{
int firstZero = input.IndexOf('0'); // Get index of first '0'
if (firstZero == -1) // Base case: no further combinations
return new string[] { input };
string prefix = input.Substring(0, firstZero); // Substring preceding '0'
string suffix = input.Substring(firstZero + 1); // Substring succeeding '0'
// e.g. Suppose input was "fr0d00"
// Prefix is "fr"; suffix is "d00"
// Recursion: Generate all combinations of suffix
// e.g. "d00", "d0o", "do0", "doo"
var recursiveCombinations = Combinations(suffix);
// Return sequence in which each string is a concatenation of the
// prefix, either '0' or 'o', and one of the recursively-found suffixes
return
from chr in "0o" // char sequence equivalent to: new [] { '0', 'o' }
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
This works for me:
public IEnumerable<string> Combinations(string input)
{
var head = input[0] == '0' //Do I have a `0`?
? new [] { "0", "o" } //If so output both `"0"` & `"o"`
: new [] { input[0].ToString() }; //Otherwise output the current character
var tails = input.Length > 1 //Is there any more string?
? Combinations(input.Substring(1)) //Yes, recursively compute
: new[] { "" }; //Otherwise, output empty string
//Now, join it up and return
return
from h in head
from t in tails
select h + t;
}
You don't need recursion here, you can enumerate your patterns and treat them as binary numbers. For example, if you have three zeros in your string, you get:
0 000 ....0..0....0...
1 001 ....0..0....o...
2 010 ....0..o....0...
3 011 ....0..o....o...
4 100 ....o..0....0...
5 101 ....o..0....o...
6 110 ....o..o....0...
7 111 ....o..o....o...
You can implement that with bitwise operators or by treating the chars that you want to replace like an odometer.
Below is an implementation in C. I'm not familiar with C# and from the other answers I see that C# already has suitable standard classes to implement what you want. (Although I'm surprised that so many peolpe propose recursion here.)
So this is more an explanation or illustration of my comment to the question than an implementation advice for your problem.
int binrep(char str[])
{
int zero[40]; // indices of zeros
int nzero = 0; // number of zeros in string
int ncombo = 1; // number of result strings
int i, j;
for (i = 0; str[i]; i++) {
if (str[i] == '0') {
zero[nzero++] = i;
ncombo <<= 1;
}
}
for (i = 0; i < ncombo; i++) {
for (j = 0; j < nzero; j++) {
str[zero[j]] = ((i >> j) & 1) ? 'o' : '0';
}
printf("%s\n", str); // should yield here
}
return ncombo;
}
Here's a solution using recursion, and your buffer array:
private static void Main(string[] args)
{
var a = Combinations("100");
var b = Combinations("10000");
}
public static IEnumerable<string> Combinations(string input)
{
var combinations = new List<string>();
combinations.Add(input);
for (int i = 0; i < input.Length; i++)
{
char[] buffer= input.ToArray();
if (buffer[i] == '0')
{
buffer[i] = 'o';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
}
return combinations.Distinct();
}
The method adds the raw input as the first result. After that, we replace in a loop the 0s we see as a o and call our method back with that new input, which will cover the case of multiple 0s.
Finally, we end up with a couple duplicates, so we use Distinct.
I know that the earlier answers are better. But I don't want my code to go to waste. :)
My approach for this combinatorics problem would be to take advantage of how binary numbers work. My algorithm would be as follows:
List<string> ZeroCombiner(string str)
{
// Get number of zeros.
var n = str.Count(c => c == '0');
var limit = (int)Math.Pow(2, n);
// Create strings of '0' and 'o' based on binary numbers from 0 to 2^n.
var binaryStrings = new List<string>();
for (int i = 0; i < limit; ++i )
{
binaryStrings.Add(Binary(i, n + 1));
}
// Replace each zero with respect to each binary string.
var result = new List<string>();
foreach (var binaryString in binaryStrings)
{
var zeroCounter = 0;
var combinedString = string.Empty;
for (int i = 0; i < str.Length; ++i )
{
if (str[i] == '0')
{
combinedString += binaryString[zeroCounter];
++zeroCounter;
}
else
combinedString += str[i];
}
result.Add(combinedString);
}
return result;
}
string Binary(int i, int n)
{
string result = string.Empty;
while (n != 0)
{
result = result + (i % 2 == 0 ? '0' : 'o');
i = i / 2;
--n;
}
return result;
}

Categories