Get the letters (ABCDE) between two letters (AE) using C# - c#

I need to get the letters as an array on passing two letters using C#
For ex.: When i pass "AE", i need to get the {A,B,C,D,E} as an array. and passing "FJ" should return {F,G,H,I,J}.

The Enumerable class can create a range, which makes the looping simple:
public static char[] CharactersBetween(char start, char end) {
return Enumerable.Range(start, end - start + 1).Select(c => (char)c).ToArray();
}
Note: A char value converts implicitly into int, so there is no conversion needed in that direction. You only have to convert the integers back to char.
Edit:
If you want to send in the alphabet to use (to handle language differences), you can use Substring to get a part of that string:
public static char[] CharactersBetween(char start, char end, string alphabet) {
int idx = alphabet.IndexOf(start);
return alphabet.Substring(idx, alphabet.IndexOf(end) - idx + 1).ToCharArray();
}

Do you mean something like
char[] CharactersBetween(char start, char end)
{
List<char> result = new List<char>();
for (char i = start; i <= end; i++)
{
result.Add(i);
}
return result.ToArray();
}

This should work out well
string startandend = "AG";
string result= "";
for( char i = startandend[0]; i <= startandend[1]; i++){
result += i;
}
result will now contain ABCDEFG.
You should probably add some logic to check if startandend actually have a Length of 2 and so on, but this should be a good starting block for you.
If you want the char[] instead of the string representation, simply call result.ToCharArray() at the end.

Use a loop with integer conversion
with
System.Convert.ToInt32(Char);
and
System.Convert.ToChar(Int32);
see http://msdn.microsoft.com/en-us/library/system.convert_methods.aspx

Pretty simple if you use a fixed alphabet,
public static string ALPHABET = "ABCDEFGHIJKLMNOPWRSTUVWXYZ";
public static List<char> GetLetters(string firstLast)
{
List<char> letters = new List<char>();
int start = ALPHABET.IndexOf(firstLast[0]);
int end = ALPHABET.IndexOf(firstLast[1]);
for (int i = start; i <= end; i++)
{
letters.Add(ALPHABET[i]);
}
return letters;
}
Obviously add in your checks for various things, but it does the basic job.

You're going to have to reference whichever alphabet you want to use. English is easy enough as the letters happen to correspond to code-point order, French treats Œ and Æ as letters in their own right sometimes, and not others. Danish and Norwegian place "Æ, Ø, Å" after Z and Swedish does the same with "Å, Ä, Ö". Irish uses "ABCDEFGHILMNOPRSTU" as the alphabet, but does also use J, K, Q, V, W, X, Y & Z in loan words.
And those are relatively easy cases. So there's no one-size-fits-all.
The easiest way to pass an alphabet is to have a string that contains it. So, e.g. the Danish alphabet would have the string "ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" while French could either include the ligatures or not as you wish (but do you need to deal with the possibility of receiving them while not using them?).
This done:
public static IEnumerable<char> AlphabetRange(string alphabet, string alphaRange)
{
if(alphaRange == null)
throw new ArgumentNullException();
if(alphaRange.Length < 2)
throw new ArgumentException();
int startIdx = alphabet.IndexOf(alphaRange[0]);
int endIdx = alphabet.IndexOf(alphaRange[1]) + 1;
if(startIdx == -1 || endIdx == 0)
throw new ArgumentException();
while(startIdx < endIdx)
yield return alphabet[startIdx++];
}

Related

I want to use the Element at , length and substring method to remove something from string in c#

Problem statement:
Using just the ElementAt, Length, and Substring string methods and the + (concatenate)
operator, write a function that accepts a string s, a start position p, and a length l, and returns s with the characters starting in position p for a length of l removed. Don’t forget that strings start at position 0. Thus (“abcdefghijk”, 2, 4) returns “abghijk”. Don’t use any “remove” or similar built-in string gadget.
I tried to do this
static string rstring(string str, int p, int l)
{
string end= "";
for (int i=0 ; i<p; i++){
end+= str[i];
}
for (int i=p+l ; i<str.length i++){
end+= str[i];
}
return end;
}
I tried to do this but i couldn't figure out to use ElementAT and substring. Any help will be appricated.
You're using [] which is essentially the same thing as ElementAt, and if you look at your loops they're basically doing the same thing as Substring, albeit less efficiently because you're building up and throwing away a bunch of intermediate strings.
That said, I don't see why you'd use both -- you'd just use one or the other.
If you don't want to use Substring() or Remove() or any other string maninpulation I would use a simple loop (this doesn't include, but should include error handling).
for (int i=0; i < str.Length; i++)
{
if (i < p || i > l+1) end += str[i];
}
This basically just accepts a string, a start and an end and then returns a new string according to those parameters.
This is probably the easiest way to explain Substrings. They accept a start and end and then give you back a new string according to your start and end.
public string ReturnSubstring(string str, int start, int end)
{
return str.Substring(start, end);
}
var firstHalf = ReturnSubstring(myString, 0, 3);
var secondHalf = ReturnSubstring(myString, 6, myString.Length);
var newString = firstHalf + secondHalf;

Checking two conditions while iterating over an array of characters

Having learned the basics/fundamentals of the C# programming language, I am now trying to tackle my first real-world problem: Write a program that, given a string, finds its longest sub-string that contains at least one upper-case letter but no digits (and then displays the length of this longest sub-string). This could be two qualifying conditions for an acceptable password, for example...
I have written the code below all by myself, which means there is probably performance issues, but that is for later consideration. I am stuck at the point where I have to make sure there is no digit in the sub-string. The comments in my code show my thinking while writing the program...
I thought first I should check to see if there is an upper-case letter in an extracted sub-string, and if there was, then I can store that qualifying sub-string in a list and then break out of the loop. But now I wonder how to check the no-digit condition at the same time in the same sub-string?
I am trying to keep it neat and simple (as I said I have only just started writing programs longer than a few lines!) so I thought doing a nested loop to check every character against !char.IsNumber(letter) might not be optimal. Or should I first check to see if there is no digit, then see if there is at least a capital character?
I feel confused how to achieve both restrictions, so I would appreciate some help in resolving this issue. I would also appreciate any observations or suggestions you might have. For example, is it OK to store my sub-strings in a list? Should I make a dictionary of some sort? Is my all-possible-sub-string extraction nested-loop optimal?
p.s. Some bits are still unfinished; for example I am still to implement the last step to find the longest sub-string and display to the user its length...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PasswordRestriction
{
class Program /// Write a program that, given a string, finds the longest substring that is a valid password and returns its length.
{
static void Main(string[] args)
{
// Ask the user for an alphanumeric string.
Console.WriteLine("Enter a string of alphanumeric values:");
// Receive the user input as string.
string password = Console.ReadLine();
// Print the length of the longest qualifying substring of the user string.
Console.WriteLine("Length of the longest qualifying substring:\n" + Solution(password).Length );
// Prevent the console window from closing.
Console.ReadLine();
}
/// The method that exracts the longest substring that is a valid password.
/// Note that a substring is a 'contiguous' segment of a string.
public static string Solution(string str)
{
// Only allow non-empty strings.
if ( String.IsNullOrEmpty(str) )
{
return "";
}
else
{
// Only allow letters and digits.
if ( str.All(char.IsLetterOrDigit) )
{
// A list for containing qualifying substrings.
List<string> passwordList = new List<string>();
// Generate all possible substrings. Note that
// string itself is not a substring of itself!
for (int i = 1; i < str.Length; i++)
{
for (int j = 0; j <= (str.Length-i); j++)
{
string subStr = str.Substring(j, i);
Console.WriteLine(subStr);
bool containsNum = false;
bool containsUpper = false;
// Convert the substrings to arrays of characters with ToCharArray.
// This method is called on a string and returns a new character array.
// You can manipulate this array in-place, which you cannot do with a string.
char[] subStrArray = subStr.ToCharArray();
// Go through every character in each substring.
// If there is at least one uppercase letter and
// no digits, put the qualifying substring in a list.
for (int k = 0; k < subStrArray.Length; k++)
{
char letter = subStrArray[k];
if ( char.IsNumber(letter) )
{
containsNum = true;
break;
}
if ( char.IsUpper(letter) )
{
containsUpper = true;
}
if ( containsUpper && (containsNum == false) && (k == subStrArray.Length - 1) )
{
Console.WriteLine("Found the above legit password!");
passwordList.Add(subStr);
}
}
}
}
//Find the longest stored string in the list.
//if (passwordList.Count != 0)
//{
string maxLength = passwordList[0];
foreach (string s in passwordList)
{
if (s.Length > maxLength.Length)
{
maxLength = s;
}
}
//}
// Return the qualifying substring.
return maxLength;
}
else
{
return "aaaaaaaaaa";
}
}
}
}
}
A good problem for Linq
contains no digits - Split on digits
at least one upper-case letter - Where + Any
longest (not shortest) OrderByDescending
longest (just one) - FirstOrDefault
Implementation
string source = ....
var result = source
.Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
.Where(line => line.Any(c => c >= 'A' && c <= 'Z')) // or char.IsUpper(c)
.OrderByDescending(line => line.Length)
.FirstOrDefault(); // null if there're no such substrings at all
As an alternative to the Linq answer, and if I understand you correctly, this is what I'd do, replacing the content of the str.All condition:
string qualifier;
string tempQualifier;
bool containsUpper = false;
for (int i = 0; i < str.Length(); i++) {
tempQualifier += str[i];
if (char.IsNumber(str[i])) {
if (containsUpper) {
if (tempQualifier.Length > qualifier.Length && tempQualifier.Length != str.Length) {
qualifier = tempQualifier;
}
containsUpper = false;
}
tempQualifier = "";
} else if (char.IsUpper(str[i])) {
containsUpper = true;
}
}
return qualifier;
This would go through the string, building up the substring until it comes across a number. If the substring contains an uppercase letter and is longer than any previous qualifier, it is stored as the new qualifier (also assuming that it isn't the length of the string provided). Apologies if I've made any mistakes (I'm not well versed in C#).
It's much longer than the Linq answer, but I thought it'd be handy for you to see the process broken down so you can understand it better.

I'm trying to find a specific word within a char array

Using C# I'm trying to find a specific word within a char array. Also, I don't want the same letter used more than once i.e. the word is 'hello' and I'm trying to find it within a random array of letters, so if the letter 'l' is used out of the random array of letters, I don't want it to be used again. There should be another 'l' within the array of letters to be used as the second 'l' in "hello". Just trying to be precise. A simple answer would be very helpful. Thank you.
Here is my attempt so far.
public static char [] Note = "hello".ToCharArray();
public static char [] Newspaper = "ahrenlxlpoz".ToCharArray();
static void main(string[] args)
{
Array.Sort(Note);
Array.Sort(Newspaper);
if(Newspaper.Contains<Note>)
{
Console.Write("It should display the letters of Note found within Newspaper");
}
}
I assume by "contains" you mean Newspaper has enough number of letters from each letter to make up Note. For example, you need at least two l's to make up the word "hello". If so, you need to basically count the number of each letter in both strings, and make sure the number of each letter in Note is less than or equal to the number of that letter in Newspaper.
var dictNote = Note.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count());
var dictNews = Newspaper.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count());
bool contains = dictNote.All(x =>
dictNews.ContainsKey(x.Key) && x.Value <= dictNews[x.Key]);
In fact, a string is a char array. And the most "classic" way to do this would be:
string Note = "hello";
char[] Newspaper = "ahrenlxlpoz".ToCharArray();
string res = "";
for (int i = 0; i < Note.Length; i++)
for (int j = 0; j < Newspaper.Length; j++)
if (Note[i] == Newspaper[j])
{
res += Newspaper[j];
Newspaper[j] = ' ';
break;
}
//This prints the remaining characters in Newspaper. I avoid repeating chars.
for (int i = 0; i < Newspaper.Length; i++ )
Console.Write(Newspaper[i]+"\n");
Console.Write("\n\n");
if (Note.Equals(res)) Console.Write("Word found");
else Console.Write("Word NOT found");
Console.Read();
At the end, res will be "hello". Print res in the console. I added the ' ' to avoid repeated characters as someone said in the answer up. So at the end it will compare the result with the word and will tell you if it found the word in the string. Try changing Newspaper to this: "ahrenlxlpaz" and it will tell you the word is NOT found :)
Try this:
public static char[] Note = "hello".ToCharArray();
public static char[] Newspaper = "ahrenlxlpoz".ToCharArray();
foreach (char c in Note) //check each character of Note
{
if (Newspaper.Contains(c))
{
Console.Write(c); //it will display hello
}
}

Best way to remove characters from string in c# win. form

i have a string of length 98975333 and i need to remove first 5 letters in it. Can anyone suggest the best way to do this keeping performance in mind?
I tried
str.Substring(5,str.Length);
str.Remove(0,5);
which gives me result in 0.29 sec
but i want something even faster than the above.
Problem Using StringBuilder
-> i need to substring a part of the string and to do this i need to write
StringBuilder2.ToString().Substring(anyvaluehere)"
here the conversion of StringBuilder to string by ".ToString()" takes time and in this case i cant use StringBuilder
If you are working with long strings, always use StringBuilder. This class provides you fast adding and removing characters, faster than String.Concat or it's syntactic sugar "a" + "b". Moreover StringBuilder.ToString() method has special implementation for best performance as possible.
Sorry, c# strings are not arrays; they are immutable so extracting a (possibly very long) substring involves a copy.
However, most [string utilities] accept start and end indices, for instance IndexOf and CompareInfo.Compare all take a startIndexoverload.
Perhaps if you tell us what you want to do afterward we could suggest alternatives?
Update
Here are some ways you can write performant string parsing with the immutable strings in c#. Say for instance that you need to deserialize XML data inside the string, and need to skip the first N characters. You could do something like this:
public static object XmlDeserializeFromString<T>(this string objectData, int skip)
{
var serializer = new XmlSerializer(typeof(T));
using (var reader = new StringReader(objectData))
{
for (; skip > 0 && reader.Read() != -1; skip--)
;
return (T)serializer.Deserialize(reader);
}
}
As you can see from the source. StringReader.Read() does not make a copy of the unread portion of the string, it keeps an internal index to the remaining unread portion.
Or say you want to skip the first N characters of a string, then parse the string by splitting it at every "," character. You could write something like this:
public static IEnumerable<Pair<int>> WalkSplits(this string str, int startIndex, int count, params char[] separator)
{
if (string.IsNullOrEmpty(str))
yield break;
var length = str.Length;
int endIndex;
if (count < 0)
endIndex = length;
else
{
endIndex = startIndex + count;
if (endIndex > length)
endIndex = length;
}
while (true)
{
int nextIndex = str.IndexOfAny(separator, startIndex, endIndex - startIndex);
if (nextIndex == startIndex)
{
startIndex = nextIndex + 1;
}
else if (nextIndex == -1)
{
if (startIndex < endIndex)
yield return new Pair<int>(startIndex, endIndex - 1);
yield break;
}
else
{
yield return new Pair<int>(startIndex, nextIndex - 1);
startIndex = nextIndex + 1;
}
}
}
And then use the start and end indices of the Pair to further parse the string, or extract small substrings to feed to further parsing methods.
(Pair<T> is a small struct I created similar to KeyValuePair<TKey, TValue> but with identically typed first and second values. I can provide if needed.)
Using a StringBuilder to produce and manipulate the string will help you save on resources:
StringBuilder sb = new StringBuilder();
sb.Append("text"); //to add text in front
sb.Insert(50,"text"); // to insert text
sb.Remove(50,4); // to remove text
sb.ToString(); // to produce the string
If you have a fixed length of string that you wish to store elsewhere, you can make a char array and use StringBuilder's CopyTo() method:
e.g.
char[] firstfive = new char[5];
sb.CopyTo(0,firstfive,0,5);
Edit:
Actually, the OP figured this out himself, but I'm including it on the post for reference:
To get a portion of the StringBuilder as string:
sb.ToString(intStart,intLength)
Use String.Remove() i.e
String newStr = "";
newStr = str.Remove(0,5); //This will delete 5 characters starting from 0 index
Or
newStr = str.Remove(5); //Assumes the starting position as 0 and will ddelete 5 chars from that
Read more Here

A good way to check a chars 'integrity'

I'm working on making my own password generator; and I want it to create passwords that contain numbers, lowercase-letters, and uppercase-letters.
I am writing the program in C#, using Visual Studio.
Say I use the code below:
Random Rand = new Random();
Char C = Convert.ToChar(Rand.Next(0x30, 0x5A));
How could I make my program check whether (C) is equal to a number or a uppercase-letter?
Use Char.IsDigit (for decimal digits), or Char.IsNumber and Char.IsUpper.
These are all static methods defined on the Char structure.
An example, as requested:
if(Char.IsNumber(C))
{
// Character is marked as a unicode number
}
you can check if:
int ordinal = (int)C;
if(( ordinal >= 65 && ordinal <= 90 ) || (ordinal >= 48 && ordinal <= 57))
{
Console.WriteLine( C + " is an uppercase A-Z or 0-9!" );
}
A better (and standard) way, is to create an 'alphabet' string of allowable characters and then generate a random index into the string, to select an allowable character.
Much better than first generating a random character and then checking if it is allowable.
"0123456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
Note the removed lowercase 'l' (looks like 1). You should remove any others such as zero versus 'O' possibly...or whatever your password rules allow)
Here's an example of using this technique to generate random strings:
public static class RandomUtils
{
private static readonly Random random = new Random();
public static string GenerateRandomAlphaNumericString(int length)
{
const string alpha =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return GenerateRandomString(length, alpha);
}
public static string GenerateRandomString(int length, string alphabet)
{
int maxlen = alphabet.Length;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
sb.Append(alphabet[random.Next(0, maxlen)]);
}
return sb.ToString();
}
}
Probably just use Char.IsNumber and Char.IsUpper methods:
see:
http://msdn.microsoft.com/en-us/library/9s91f3by.aspx
http://msdn.microsoft.com/en-us/library/yk2b3t2y.aspx
if (C.IsNumber || C.IsUpper)
{
// password code!
}
(don't write your own password generator, unless it's just for fun though).

Categories

Resources