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)
Related
⦁ Replace and/or re-arrange characters of this given string to get the lexicographically smallest string possible. For this, you can perform the following two operations any number of times.
⦁ Swap any two characters in the string. This operation costs 1 point. (any two, need not be adjacent)
⦁ Replace a character in the string with any other lower case English letter. This operation costs 2 points.
Obtain the lexicographically smallest string possible, by using at most P points.
Input:
⦁ Two lines of input, first-line containing two integers N, P.
⦁ The second line contains a string S consisting of N characters.
Output:
Lexicographically smallest string obtained.
for e.g
Sample Input:
3 3
bba
Sample Output:
aab
Ive tried this but it doesnt contain P points i dont know how to do that can you guys please help me with that:
namespace Lexicographical
{
class GFG
{
// Function to return the lexicographically
// smallest String that can be formed by
// swapping at most one character.
// The characters might not necessarily
// be adjacent.
static String findSmallest(char[] s)
{
int len = s.Length;
// Store last occurrence of every character
int[] loccur = new int[26];
// Set -1 as default for every character.
for (int i = 0; i < 26; i++)
loccur[i] = -1;
for (int i = len - 1; i >= 0; --i)
{
// char index to fill
// in the last occurrence array
int chI = s[i] - 'a';
if (loccur[chI] == -1)
{
// If this is true then this
// character is being visited
// for the first time from the last
// Thus last occurrence of this
// character is stored in this index
loccur[chI] = i;
}
}
char[] sorted_s = s;
Array.Sort(sorted_s);
for (int i = 0; i < len; ++i)
{
if (s[i] != sorted_s[i])
{
// char to replace
int chI = sorted_s[i] - 'a';
// Find the last occurrence
// of this character.
int last_occ = loccur[chI];
// Swap this with the last occurrence
char temp = s[last_occ];
s[last_occ] = s[i];
s[i] = temp;
break;
}
}
return String.Join("", s);
}
// Driver code
public static void Main(String[] args)
{
String s = "abb";
Console.Write(findSmallest(s.ToCharArray()));
}
}
}
The output for this is abb but it should be aab...
I want to know how i can use above Question in this
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();
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;
}
}
Let's say I have a text and I want to locate the positions of each comma. The string, a shorter version, would look like this:
string s = "A lot, of text, with commas, here and,there";
Ideally, I would use something like:
int[] i = s.indexOf(',');
but since indexOf only returns the first comma, I instead do:
List<int> list = new List<int>();
for (int i = 0; i < s.Length; i++)
{
if (s[i] == ',')
list.Add(i);
}
Is there an alternative, more optimized way of doing this?
Here I got a extension method for that, for the same use as IndexOf:
public static IEnumerable<int> AllIndexesOf(this string str, string searchstring)
{
int minIndex = str.IndexOf(searchstring);
while (minIndex != -1)
{
yield return minIndex;
minIndex = str.IndexOf(searchstring, minIndex + searchstring.Length);
}
}
so you can use
s.AllIndexesOf(","); // 5 14 27 37
https://dotnetfiddle.net/DZdQ0L
You could use Regex.Matches(string, string) method. This will return a MatchCollection and then you could determine the Match.Index. MSDN has a good example,
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = #"\b\w+es\b";
string sentence = "Who writes these notes?";
foreach (Match match in Regex.Matches(sentence, pattern))
Console.WriteLine("Found '{0}' at position {1}",
match.Value, match.Index);
}
}
// The example displays the following output:
// Found 'writes' at position 4
// Found 'notes' at position 17
IndexOf also allows you to add another parameter for where to start looking. You can set that parameter to be the last known comma location +1. For example:
string s = "A lot, of text, with commas, here and, there";
int loc = s.IndexOf(',');
while (loc != -1) {
Console.WriteLine(loc);
loc = s.IndexOf(',', loc + 1);
}
You could use the overload of the IndexOf method that also takes a start index to get the following comma, but you would still have to do that in a loop, and it would perform pretty much the same as the code that you have.
You could use a regular expression to find all commas, but that produces quite some overhead, so that's not more optimised than what you have.
You could write a LINQ query to do it in a different way, but that also has some overhead so it's not more optimised than what you have.
So, there are many alternative ways, but not any way that is more optimised.
A bit unorthodox, but why not use a split? Might be less aggressive than iterating over the entire string
string longString = "Some, string, with, commas.";
string[] splitString = longString.Split(",");
int numSplits = splitString.Length - 1;
Debug.Log("number of commas "+numSplits);
Debug.Log("first comma index = "+GetIndex(splitString, 0)+" second comma index = "+GetIndex(splitString, 1));
public int GetIndex(string[] stringArray, int num)
{
int charIndex = 0;
for (int n = num; n >= 0; n--)
{
charIndex+=stringArray[n].Length;
}
return charIndex + num;
}
I am having the numbers follows taken as strings
My actual number is 1234567890123456789
from this i have to separate it as s=12 s1=6789 s3=3456789012345
remaining as i said
I would like to add as follows
11+3, 2+4, 6+5, 7+6, 8+7, 9+8 such that the output should be as follows
4613579012345
Any help please
public static string CombineNumbers(string number1, string number2)
{
int length = number1.Length > number2.Length ? number1.Length : number2.Length;
string returnValue = string.Empty;
for (int i = 0; i < length; i++)
{
int n1 = i >= number1.Length ? 0 : int.Parse(number1.Substring(i,1));
int n2 = i >= number2.Length ? 0 : int.Parse(number2.Substring(i,1));
int sum = n1 + n2;
returnValue += sum < 10 ? sum : sum - 10;
}
return returnValue;
}
This sounds an awful lot like a homework problem, so I'm not giving code. Just think about what you need to do. You are saying that you need to take the first character off the front of two strings, parse them to ints, and add them together. Finally, take the result of the addition and append them to the end of a new string. If you write code that follows that path, it should work out fine.
EDIT: As Ralph pointed out, you'll also need to check for overflows. I didn't notice that when I started typing. Although, that shouldn't be too hard, since you're starting with a two one digit numbers. If the number is greater than 9, then you can just subtract 10 to bring it down to the proper one digit number.
How about this LINQish solution:
private string SumIt(string first, string second)
{
IEnumerable<char> left = first;
IEnumerable<char> right = second;
var sb = new StringBuilder();
var query = left.Zip(right, (l, r) => new { Left = l, Right = r })
.Select(chars => new { Left = int.Parse(chars.Left.ToString()),
Right = int.Parse(chars.Right.ToString()) })
.Select(numbers => (numbers.Left + numbers.Right) % 10);
foreach (var number in query)
{
sb.Append(number);
}
return sb.ToString();
}
Tried something:
public static string NumAdd(int iOne, int iTwo)
{
char[] strOne = iOne.ToString().ToCharArray();
char[] strTwo = iTwo.ToString().ToCharArray();
string strReturn = string.Empty;
for (int i = 0; i < strOne.Length; i++)
{
int iFirst = 0;
if (int.TryParse(strOne[i].ToString(), out iFirst))
{
int iSecond = 0;
if (int.TryParse(strTwo[i].ToString(), out iSecond))
{
strReturn += ((int)(iFirst + iSecond)).ToString();
}
}
// last one, add the remaining string
if (i + 1 == strOne.Length)
{
strReturn += iTwo.ToString().Substring(i+1);
break;
}
}
return strReturn;
}
You should call it like this:
string strBla = NumAdd(12345, 123456789);
This function works only if the first number is smaller than the second one. But this will help you to know how it is about.
In other words, you want to add two numbers treating the lesser number like it had zeroes to its right until it had the same amount of digits as the greater number.
Sounds like the problem at this point is simply a matter of finding out how much you need to multiply the smaller number by in order to reach the number of digits of the larger number.