C# Simple encrypt/decrypt algorithm - c#

I was working on straightforward encryption and got stuck on one of its rules.
The rules are,
Encryption work by adding 5 to each character.
Only encrypt a-z and A-Z, all other characters will add to the encrypted string as it is.
If the character is z or Z, the adding starts from the character a.
By performing the above encryption in reverse, the description should also be present.
I was able to do the encryption, but the 3rd rule is where I got stuck when decrypting.
Below is the code I tried,
# Encrypt
Input : Dinindu-12Z
Output : Insnsiz-12F
# Decrypt
Input : Insnsiz-12F
Output : Dinindu-12Z # This is the expected output, but got "Dinind\-12A"
using System;
class Program
{
public static String encrypt(String input)
{
String output = "";
foreach (char c in input)
{
if (char.IsLetter(c))
{
char cc = c;
if (c == 'z') cc = 'a';
if (c == 'Z') cc = 'A';
output += (char)(((int)cc) + 5);
}
else
{
output += c;
}
}
return output;
}
public static string decrypt(String input)
{
String output = "";
foreach (char c in input)
{
if (char.IsLetter(c))
{
char cc = c;
if (c == 'z') cc = 'a';
if (c == 'Z') cc = 'A';
output += (char)(((int)cc) - 5);
}
else
{
output += c;
}
}
return output;
}
public static void Main(string[] args)
{
String a = encrypt("Dinindu-12Z");
String b = decrypt(a);
Console.WriteLine(a);
Console.WriteLine(b);
}
}

You should write a method that will accept a char array and get the element at the advanced index. You can use the modulo (%) operator to advance and wrap, e.g.
private static char GetCharWithStepAndWrap(char[] chars, char ch, int step)
{
var index = Array.IndexOf(chars, ch);
index += step;
index %= chars.Length;
return chars[index];
}
Adding the step value will advance the index, possibly past the end of the array. The modulo will then divide the index by the Length of the array and use the remainder. That means that if the index starts within the array, it will stay where it is and, if it's past the end of the array, you're effectively subtracting the Length from it to wrap back to the beginning.
You can then use that method with a char array from a to z to encrypt and then simply reverse the array to decrypt, e.g.
static void Main(string[] args)
{
var chars = Enumerable.Range(Convert.ToInt32('a'), 26).Select(Convert.ToChar).ToArray();
var plainText = "Dinindu-12Z";
var encryptedText = string.Empty;
for (var i = 0; i < plainText.Length; i++)
{
var ch = plainText[i];
if (char.IsLetter(ch))
{
var isUpper = char.IsUpper(ch);
ch = char.ToLower(ch);
ch = GetCharWithStepAndWrap(chars, ch, 5);
if (isUpper)
{
ch = char.ToUpper(ch);
}
}
encryptedText += ch;
}
Console.WriteLine(encryptedText);
Array.Reverse(chars);
var decryptedText = string.Empty;
for (var i = 0; i < plainText.Length; i++)
{
var ch = encryptedText[i];
if (char.IsLetter(ch))
{
var isUpper = char.IsUpper(ch);
ch = char.ToLower(ch);
ch = GetCharWithStepAndWrap(chars, ch, 5);
if (isUpper)
{
ch = char.ToUpper(ch);
}
}
decryptedText += ch;
}
Console.WriteLine(decryptedText);
}
If you try that code, you'll notice that the correct encrypted text is "Insnsiz-12E".

Related

How to create a sequence of strings between "start" and "end" strings [duplicate]

I have a question about iterate through the Alphabet.
I would like to have a loop that begins with "a" and ends with "z". After that, the loop begins "aa" and count to "az". after that begins with "ba" up to "bz" and so on...
Anybody know some solution?
Thanks
EDIT: I forgot that I give a char "a" to the function then the function must return b. if u give "bnc" then the function must return "bnd"
First effort, with just a-z then aa-zz
public static IEnumerable<string> GetExcelColumns()
{
for (char c = 'a'; c <= 'z'; c++)
{
yield return c.ToString();
}
char[] chars = new char[2];
for (char high = 'a'; high <= 'z'; high++)
{
chars[0] = high;
for (char low = 'a'; low <= 'z'; low++)
{
chars[1] = low;
yield return new string(chars);
}
}
}
Note that this will stop at 'zz'. Of course, there's some ugly duplication here in terms of the loops. Fortunately, that's easy to fix - and it can be even more flexible, too:
Second attempt: more flexible alphabet
private const string Alphabet = "abcdefghijklmnopqrstuvwxyz";
public static IEnumerable<string> GetExcelColumns()
{
return GetExcelColumns(Alphabet);
}
public static IEnumerable<string> GetExcelColumns(string alphabet)
{
foreach(char c in alphabet)
{
yield return c.ToString();
}
char[] chars = new char[2];
foreach(char high in alphabet)
{
chars[0] = high;
foreach(char low in alphabet)
{
chars[1] = low;
yield return new string(chars);
}
}
}
Now if you want to generate just a, b, c, d, aa, ab, ac, ad, ba, ... you'd call GetExcelColumns("abcd").
Third attempt (revised further) - infinite sequence
public static IEnumerable<string> GetExcelColumns(string alphabet)
{
int length = 0;
char[] chars = null;
int[] indexes = null;
while (true)
{
int position = length-1;
// Try to increment the least significant
// value.
while (position >= 0)
{
indexes[position]++;
if (indexes[position] == alphabet.Length)
{
for (int i=position; i < length; i++)
{
indexes[i] = 0;
chars[i] = alphabet[0];
}
position--;
}
else
{
chars[position] = alphabet[indexes[position]];
break;
}
}
// If we got all the way to the start of the array,
// we need an extra value
if (position == -1)
{
length++;
chars = new char[length];
indexes = new int[length];
for (int i=0; i < length; i++)
{
chars[i] = alphabet[0];
}
}
yield return new string(chars);
}
}
It's possible that it would be cleaner code using recursion, but it wouldn't be as efficient.
Note that if you want to stop at a certain point, you can just use LINQ:
var query = GetExcelColumns().TakeWhile(x => x != "zzz");
"Restarting" the iterator
To restart the iterator from a given point, you could indeed use SkipWhile as suggested by thesoftwarejedi. That's fairly inefficient, of course. If you're able to keep any state between call, you can just keep the iterator (for either solution):
using (IEnumerator<string> iterator = GetExcelColumns())
{
iterator.MoveNext();
string firstAttempt = iterator.Current;
if (someCondition)
{
iterator.MoveNext();
string secondAttempt = iterator.Current;
// etc
}
}
Alternatively, you may well be able to structure your code to use a foreach anyway, just breaking out on the first value you can actually use.
Edit: Made it do exactly as the OP's latest edit wants
This is the simplest solution, and tested:
static void Main(string[] args)
{
Console.WriteLine(GetNextBase26("a"));
Console.WriteLine(GetNextBase26("bnc"));
}
private static string GetNextBase26(string a)
{
return Base26Sequence().SkipWhile(x => x != a).Skip(1).First();
}
private static IEnumerable<string> Base26Sequence()
{
long i = 0L;
while (true)
yield return Base26Encode(i++);
}
private static char[] base26Chars = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
private static string Base26Encode(Int64 value)
{
string returnValue = null;
do
{
returnValue = base26Chars[value % 26] + returnValue;
value /= 26;
} while (value-- != 0);
return returnValue;
}
The following populates a list with the required strings:
List<string> result = new List<string>();
for (char ch = 'a'; ch <= 'z'; ch++){
result.Add (ch.ToString());
}
for (char i = 'a'; i <= 'z'; i++)
{
for (char j = 'a'; j <= 'z'; j++)
{
result.Add (i.ToString() + j.ToString());
}
}
I know there are plenty of answers here, and one's been accepted, but IMO they all make it harder than it needs to be. I think the following is simpler and cleaner:
static string NextColumn(string column){
char[] c = column.ToCharArray();
for(int i = c.Length - 1; i >= 0; i--){
if(char.ToUpper(c[i]++) < 'Z')
break;
c[i] -= (char)26;
if(i == 0)
return "A" + new string(c);
}
return new string(c);
}
Note that this doesn't do any input validation. If you don't trust your callers, you should add an IsNullOrEmpty check at the beginning, and a c[i] >= 'A' && c[i] <= 'Z' || c[i] >= 'a' && c[i] <= 'z' check at the top of the loop. Or just leave it be and let it be GIGO.
You may also find use for these companion functions:
static string GetColumnName(int index){
StringBuilder txt = new StringBuilder();
txt.Append((char)('A' + index % 26));
//txt.Append((char)('A' + --index % 26));
while((index /= 26) > 0)
txt.Insert(0, (char)('A' + --index % 26));
return txt.ToString();
}
static int GetColumnIndex(string name){
int rtn = 0;
foreach(char c in name)
rtn = rtn * 26 + (char.ToUpper(c) - '#');
return rtn - 1;
//return rtn;
}
These two functions are zero-based. That is, "A" = 0, "Z" = 25, "AA" = 26, etc. To make them one-based (like Excel's COM interface), remove the line above the commented line in each function, and uncomment those lines.
As with the NextColumn function, these functions don't validate their inputs. Both with give you garbage if that's what they get.
Here’s what I came up with.
/// <summary>
/// Return an incremented alphabtical string
/// </summary>
/// <param name="letter">The string to be incremented</param>
/// <returns>the incremented string</returns>
public static string NextLetter(string letter)
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (!string.IsNullOrEmpty(letter))
{
char lastLetterInString = letter[letter.Length - 1];
// if the last letter in the string is the last letter of the alphabet
if (alphabet.IndexOf(lastLetterInString) == alphabet.Length - 1)
{
//replace the last letter in the string with the first leter of the alphbat and get the next letter for the rest of the string
return NextLetter(letter.Substring(0, letter.Length - 1)) + alphabet[0];
}
else
{
// replace the last letter in the string with the proceeding letter of the alphabet
return letter.Remove(letter.Length-1).Insert(letter.Length-1, (alphabet[alphabet.IndexOf(letter[letter.Length-1])+1]).ToString() );
}
}
//return the first letter of the alphabet
return alphabet[0].ToString();
}
just curious , why not just
private string alphRecursive(int c) {
var alphabet = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
if (c >= alphabet.Length) {
return alphRecursive(c/alphabet.Length) + alphabet[c%alphabet.Length];
} else {
return "" + alphabet[c%alphabet.Length];
}
}
This is like displaying an int, only using base 26 in stead of base 10. Try the following algorithm to find the nth entry of the array
q = n div 26;
r = n mod 26;
s = '';
while (q > 0 || r > 0) {
s = alphabet[r] + s;
q = q div 26;
r = q mod 26;
}
Of course, if you want the first n entries, this is not the most efficient solution. In this case, try something like daniel's solution.
I gave this a go and came up with this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Alphabetty
{
class Program
{
const string alphabet = "abcdefghijklmnopqrstuvwxyz";
static int cursor = 0;
static int prefixCursor;
static string prefix = string.Empty;
static bool done = false;
static void Main(string[] args)
{
string s = string.Empty;
while (s != "Done")
{
s = GetNextString();
Console.WriteLine(s);
}
Console.ReadKey();
}
static string GetNextString()
{
if (done) return "Done";
char? nextLetter = GetNextLetter(ref cursor);
if (nextLetter == null)
{
char? nextPrefixLetter = GetNextLetter(ref prefixCursor);
if(nextPrefixLetter == null)
{
done = true;
return "Done";
}
prefix = nextPrefixLetter.Value.ToString();
nextLetter = GetNextLetter(ref cursor);
}
return prefix + nextLetter;
}
static char? GetNextLetter(ref int letterCursor)
{
if (letterCursor == alphabet.Length)
{
letterCursor = 0;
return null;
}
char c = alphabet[letterCursor];
letterCursor++;
return c;
}
}
}
Here is something I had cooked up that may be similar. I was experimenting with iteration counts in order to design a numbering schema that was as small as possible, yet gave me enough uniqueness.
I knew that each time a added an Alpha character, it would increase the possibilities 26x but I wasn't sure how many letters, numbers, or the pattern I wanted to use.
That lead me to the code below. Basically you pass it an AlphaNumber string, and every position that has a Letter, would eventually increment to "z\Z" and every position that had a Number, would eventually increment to "9".
So you can call it 1 of two ways..
//This would give you the next Itteration... (H3reIsaStup4dExamplf)
string myNextValue = IncrementAlphaNumericValue("H3reIsaStup4dExample")
//Or Loop it resulting eventually as "Z9zzZzzZzzz9zZzzzzzz"
string myNextValue = "H3reIsaStup4dExample"
while (myNextValue != null)
{
myNextValue = IncrementAlphaNumericValue(myNextValue)
//And of course do something with this like write it out
}
(For me, I was doing something like "1AA000")
public string IncrementAlphaNumericValue(string Value)
{
//We only allow Characters a-b, A-Z, 0-9
if (System.Text.RegularExpressions.Regex.IsMatch(Value, "^[a-zA-Z0-9]+$") == false)
{
throw new Exception("Invalid Character: Must be a-Z or 0-9");
}
//We work with each Character so it's best to convert the string to a char array for incrementing
char[] myCharacterArray = Value.ToCharArray();
//So what we do here is step backwards through the Characters and increment the first one we can.
for (Int32 myCharIndex = myCharacterArray.Length - 1; myCharIndex >= 0; myCharIndex--)
{
//Converts the Character to it's ASCII value
Int32 myCharValue = Convert.ToInt32(myCharacterArray[myCharIndex]);
//We only Increment this Character Position, if it is not already at it's Max value (Z = 90, z = 122, 57 = 9)
if (myCharValue != 57 && myCharValue != 90 && myCharValue != 122)
{
myCharacterArray[myCharIndex]++;
//Now that we have Incremented the Character, we "reset" all the values to the right of it
for (Int32 myResetIndex = myCharIndex + 1; myResetIndex < myCharacterArray.Length; myResetIndex++)
{
myCharValue = Convert.ToInt32(myCharacterArray[myResetIndex]);
if (myCharValue >= 65 && myCharValue <= 90)
{
myCharacterArray[myResetIndex] = 'A';
}
else if (myCharValue >= 97 && myCharValue <= 122)
{
myCharacterArray[myResetIndex] = 'a';
}
else if (myCharValue >= 48 && myCharValue <= 57)
{
myCharacterArray[myResetIndex] = '0';
}
}
//Now we just return an new Value
return new string(myCharacterArray);
}
}
//If we got through the Character Loop and were not able to increment anything, we retun a NULL.
return null;
}
Here's my attempt using recursion:
public static void PrintAlphabet(string alphabet, string prefix)
{
for (int i = 0; i < alphabet.Length; i++) {
Console.WriteLine(prefix + alphabet[i].ToString());
}
if (prefix.Length < alphabet.Length - 1) {
for (int i = 0; i < alphabet.Length; i++) {
PrintAlphabet(alphabet, prefix + alphabet[i]);
}
}
}
Then simply call PrintAlphabet("abcd", "");

Add next character to each char in a string

i've to return it with the next character in the ASCII table, example:
string tmp = "hello";
string modified = "ifmmp";
I've tried to split string into characters and sum 1 to each character but it gives out an error.
Try this out:
public string NextCharString(string str)
{
string result = "";
foreach(var c in str)
{
if (c=='z') result += 'a';
else if (c == 'Z') result += 'A';
else result += (char)(((int)c) + 1)
}
}
Edit: I assumed adding one to all characters is cyclic, that is, adding one to 'z' will give an 'a'
Try this :
string tmp = "hello";
string modified = "";
for (int i = 0; i < tmp.Length; i++)
{
char c = getNextChar(tmp[i]);
modified += c;
}
// 'modified' will be your desired output
Create this method :
private static char getNextChar(char c)
{
// convert char to ascii
int ascii = (int)c;
// get the next ascii
int nextAscii = ascii + 1;
// convert ascii to char
char nextChar = (char)nextAscii;
return nextChar;
}

Parse String to Generate Output String in Specific Format

I am looking to generate a Sequence Number in this format
00000A
00000B
00000B
and so on till
00000Z
and then
00001A
00001B
00001C
...
00001Z
...
00010A
till
99999Z
I know that I can generate Max 2.6 million rows using this method but I guess that is enough
so, if I have the a String, lets say 26522C, Now i want the next number as 26522D
or If I have 34287Z, i want 34288A
I can write the Algorithm about it but there will be lots of parsing of the input string characters by characters
I was wondering is there any easier way of doing it
String GetNextNumberInSequence(String inputString)
{
if (inputString.Length == 6)
{
var charArray = inputString.ToCharArray();
char[] inputChars = { charArray[0], charArray[1], charArray[2],charArray[3],charArray[4],charArray[5] };
if(Char.IsDigit(charArray[5]))
{
//Parse first 5 characters
}
}
}
private static String GetNextNumberInSequence(String inputString)
{
var integerpart = int.Parse(inputString.Substring(0, 5));
var characterPart = inputString[5];
if (characterPart == 'Z')
return string.Format("{0}{1}", (++integerpart).ToString("D5"), "A");
var nextChar = (char)(characterPart + 1);
return string.Format("{0}{1}", (integerpart).ToString("D5"), nextChar.ToString());
}
You can achieve this by converting a number to Base36.
Take a look at this sample:
private const string CharList = "0123456789abcdefghijklmnopqrstuvwxyz";
public static String Base36Encode(long input, char paddingChar, int totalWidth)
{
char[] clistarr = CharList.ToCharArray();
var result = new Stack<char>();
while (input != 0)
{
result.Push(clistarr[input % 36]);
input /= 36;
}
return new string(result.ToArray()).PadLeft(totalWidth, paddingChar).ToUpper();
}
and then use it this way:
for(int i = 0; i < 1000; i++)
{
Debug.WriteLine(Base36Encode(i, '0', 6));
}
which will produce this:
000000, 000001, 000002, 000003, 000004, 000005, 000006, 000007, 000008, 000009, 00000A, 00000B, 00000C, 00000D, 00000E, 00000F, 00000G, 00000H, 00000I, 00000J, 00000K, 00000L, 00000M, 00000N, 00000O, 00000P, 00000Q, 00000R, 00000S, 00000T, 00000U, 00000V, 00000W, 00000X, 00000Y, 00000Z, 000010, 000011, 000012, 000013, 000014, 000015, 000016, 000017, 000018, 000019, 00001A, 00001B, 00001C, 00001D, 00001E, 00001F, 00001G, 00001H, 00001I, 00001J, 00001K, 00001L, 00001M, 00001N, 00001O, 00001P, 00001Q, 00001R, 00001S, 00001T, 00001U, 00001V, 00001W, 00001X, 00001Y, 00001Z, 000020, 000021, 000022, 000023, 000024, 000025, 000026, 000027, 000028, 000029, 00002A, 00002B, 00002C, 00002D, 00002E, 00002F, 00002G, 00002H, 00002I, 00002J, 00002K, 00002L, 00002M, 00002N, 00002O, 00002P, 00002Q, 00002R, 00002S, 00002T...
and the positive thing about this approach is that you can convert this back to number by using:
public static Int64 Base36Decode(string input)
{
var reversed = input.ToLower().Reverse();
long result = 0;
int pos = 0;
foreach (char c in reversed)
{
result += CharList.IndexOf(c) * (long)Math.Pow(36, pos);
pos++;
}
return result;
}

Reverse case of all alphabetic characters in C# string

What is the simplest way to reverse the case of all alphabetic characters in a C# string? For example "aBc1$;" should become "AbC1$;" I could easily write a method that does this, but I am hoping there is a library call that I don't know about that would make this easier. I would also like to avoid having a list of all known alphabetic characters and comparing each character to what is in the list. Maybe this can be done with regular expressions, but I don't know them very well. Thanks.
Thanks for the help. I created a string extension method for this that is mostly inspired by Anthony Pegram's solution, but without the LINQ. I think this strikes a good balance between readability and performance. Here is what I came up with.
public static string SwapCase(this string source) {
char[] caseSwappedChars = new char[source.Length];
for(int i = 0; i < caseSwappedChars.Length; i++) {
char c = source[i];
if(char.IsLetter(c)) {
caseSwappedChars[i] =
char.IsUpper(c) ? char.ToLower(c) : char.ToUpper(c);
} else {
caseSwappedChars[i] = c;
}
}
return new string(caseSwappedChars);
}
You could do it in a line with LINQ. One method:
string input = "aBc1$";
string reversedCase = new string(
input.Select(c => char.IsLetter(c) ? (char.IsUpper(c) ?
char.ToLower(c) : char.ToUpper(c)) : c).ToArray());
If you don't care about internationalization:
string input = "aBc1$#[\\]^_{|{~";
Encoding enc = new System.Text.ASCIIEncoding();
byte[] b = enc.GetBytes(input);
for (int i = input.Length - 1; i >= 0; i -= 1) {
if ((b[i] & 0xdf) >= 65 && (b[i] & 0xdf) <= 90) { //check if alpha
b[i] ^= 0x20; // then XOR the correct bit to change case
}
}
Console.WriteLine(input);
Console.WriteLine(enc.GetString(b));
If, on the other hand, you DO care about internationalization, you'll want to pass in CultureInfo.InvariantCulture to your ToUpper() and ToLower() functions...
You could do it old-school if you don't know LINQ.
static string InvertCasing(string s)
{
char[] c = s.ToCharArray();
char[] cUpper = s.ToUpper().ToCharArray();
char[] cLower = s.ToLower().ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (c[i] == cUpper[i])
{
c[i] = cLower[i];
}
else
{
c[i] = cUpper[i];
}
}
return new string(c);
}
Here's a regex approach:
string input = "aBcdefGhI123jKLMo$";
string result = Regex.Replace(input, "[a-zA-Z]",
m => Char.IsUpper(m.Value[0]) ?
Char.ToLower(m.Value[0]).ToString() :
Char.ToUpper(m.Value[0]).ToString());
Console.WriteLine("Original: " + input);
Console.WriteLine("Modified: " + result);
You can use Char.Parse(m.Value) as an alternate to m.Value[0]. Also, be mindful of using the ToUpperInvariant and ToLowerInvariant methods instead. For more info see this question: In C# what is the difference between ToUpper() and ToUpperInvariant()?
I made an extension method for strings which does just this!
public static class InvertStringExtension
{
public static string Invert(this string s)
{
char[] chars = s.ToCharArray();
for (int i = 0; i < chars.Length; i++)
chars[i] = chars[i].Invert();
return new string(chars);
}
}
public static class InvertCharExtension
{
public static char Invert(this char c)
{
if (!char.IsLetter(c))
return c;
return char.IsUpper(c) ? char.ToLower(c) : char.ToUpper(c);
}
}
To use
var hello = "hELLO wORLD";
var helloInverted = hello.Invert();
// helloInverted == "Hello World"
char[] carr = str.ToCharArray();
for (int i = 0; i < carr.Length; i++)
{
if (char.IsLetter(carr[i]))
{
carr[i] = char.IsUpper(carr[i]) ? char.ToLower(carr[i]) : char.ToUpper(carr[i]);
}
}
str = new string(carr);
I was asked a similar question yesterday and my answer is like:
public static partial class StringExtensions {
public static String InvertCase(this String t) {
Func<char, String> selector=
c => (char.IsUpper(c)?char.ToLower(c):char.ToUpper(c)).ToString();
return t.Select(selector).Aggregate(String.Concat);
}
}
You can easily change the method signature to add a parameter of type CultureInfo, and use it with methods like char.ToUpper for a requirement of globalization.
A little bit faster than some other methods listed here and it is nice because it uses Char arithmetics!
var line = "someStringToSwapCase";
var charArr = new char[line.Length];
for (int i = 0; i < line.Length; i++)
{
if (line[i] >= 65 && line[i] <= 90)
{
charArr[i] = (char)(line[i] + 32);
}
else if (line[i] >= 97 && line[i] <= 122)
{
charArr[i] = (char)(line[i] - 32);
}
else
{
charArr[i] = line[i];
}
}
var res = new String(charArr);
This will helps you more.. because here i have not use directly function.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Practice
{
class Program
{
static void Main(string[] args)
{
char[] new_str = new char[50];
string str;
int ch;
Console.Write("Enter String : ");
str = Console.ReadLine();
for (int i = 0; i < str.Length; i++)
{
ch = (int)str[i];
if (ch > 64 && ch < 91)
{
ch = ch + 32;
new_str[i] = Convert.ToChar(ch);
}
else
{
ch = ch - 32;
new_str[i] = Convert.ToChar(ch);
}
}
Console.Write(new_str);
Console.ReadKey();
}
}
}
I am sure this will also works for you.. Thank you.
Code below makes only 2 function calls to each letter. Instead of checking if IsLetter, we just apply upper/lowercase if necessary.
string result="";
foreach (var item in S)
{
if (char.ToLower(item) != item )
result+= char.ToLower(item);
else
result+= char.ToUpper(item);
}
It would be also possible (tho less readable) to create an extra variable and set it to char.ToLower(item) before the check, exchanging one function call for one extra variable, thie way:
string result="";
foreach (var item in S)
{
var temp=char.ToLower(item);
if (temp != item )
result+= temp;
else
result+= char.ToUpper(item);
}

How can you remove duplicate characters in a string?

I have to implements a function that takes a string as an input and finds the non-duplicate character from this string.
So an an example is if I pass string str = "DHCD" it will return "DHC"
or str2 = "KLKLHHMO" it will return "KLHMO"
A Linq approach:
public static string RemoveDuplicates(string input)
{
return new string(input.ToCharArray().Distinct().ToArray());
}
It will do the job
string removedupes(string s)
{
string newString = string.Empty;
List<char> found = new List<char>();
foreach(char c in s)
{
if(found.Contains(c))
continue;
newString+=c.ToString();
found.Add(c);
}
return newString;
}
I should note this is criminally inefficient.
I think I was delirious on first revision.
For arbitrary length strings of byte-sized characters (not for wide characters or other encodings), I would use a lookup table, one bit per character (32 bytes for a 256-bit table). Loop through your string, only output characters that don't have their bits turned on, then turn the bit on for that character.
string removedupes(string s)
{
string t;
byte[] found = new byte[256];
foreach(char c in s)
{
if(!found[c]) {
t.Append(c);
found[c]=1;
}
}
return t;
}
I am not good with C#, so I don't know the right way to use a bitfield instead of a byte array.
If you know that your strings are going to be very short, then other approaches would offer better memory usage and/or speed.
void removeDuplicate()
{
string value1 = RemoveDuplicateChars("Devarajan");
}
static string RemoveDuplicateChars(string key)
{
string result = "";
foreach (char value in key)
if (result.IndexOf(value) == -1)
result += value;
return result;
}
It sounds like homework to me, so I'm just going to describe at a high level.
Loop over the string, examining each character
Check if you've seen the character before
if you have, remove it from the string
if you haven't, note that you've now seen that character
this is in C#. validation left out for brevity. primitive solution for removing duplicate chars from a given string
public static char[] RemoveDup(string s)
{
char[] chars = new char[s.Length];
int unique = 0;
chars[unique] = s[0]; // Assume: First char is unique
for (int i = 1; i < s.Length; i++)
{
// add char in i index to unique array
// if char in i-1 != i index
// i.e s = "ab" -> a != b
if (s[i-1] != s[i]
chars[++unique] = s[i];
}
return chars;
}
My answer in java language.
Posting here so that you might get a idea even it is in Java language.Algorithm would remain same.
public String removeDup(String s)
{
if(s==null) return null;
int l = s.length();
//if length is less than 2 return string
if(l<2)return s;
char arr[] = s.toCharArray();
for(int i=0;i<l;i++)
{
int j =i+1; //index to check with ith index
int t = i+1; //index of first repetative char.
while(j<l)
{
if(arr[j]==arr[i])
{
j++;
}
else
{
arr[t]=arr[j];
t++;
j++;
}
}
l=t;
}
return new String(arr,0,l);
}
you may use HashSet:
static void Main()
{
string textWithDuplicates = "aaabbcccggg";
Console.WriteLine(textWithDuplicates.Count());
var letters = new HashSet<char>(textWithDuplicates);
Console.WriteLine(letters.Count());
foreach (char c in letters) Console.Write(c);
}
class Program
{
static void Main(string[] args)
{
bool[] doesExists = new bool[256];
String st = Console.ReadLine();
StringBuilder sb = new StringBuilder();
foreach (char ch in st)
{
if (!doesExists[ch])
{
sb.Append(ch);
doesExists[ch] = true;
}
}
Console.WriteLine(sb.ToString());
}
}
Revised version of the first answer i.e: You don't need ToCharArray() function for this to work.
public static string RemoveDuplicates(string input)
{
return new string(input.Distinct().ToArray());
}
char *remove_duplicates(char *str)
{
char *str1, *str2;
if(!str)
return str;
str1 = str2 = str;
while(*str2)
{
if(strchr(str, *str2)<str2)
{
str2++;
continue;
}
*str1++ = *str2++;
}
*str1 = '\0';
return str;
}
char* removeDups(const char* str)
{
char* new_str = (char*)malloc(256*sizeof(char));
int i,j,current_pos = 0,len_of_new_str;
new_str[0]='\0';
for(i=0;i<strlen(str);i++)
{
len_of_new_str = strlen(new_str);
for(j=0;j<len_of_new_str && new_str[j]!=str[i];j++)
;
if(j==len_of_new_str)
{
new_str[len_of_new_str] = str[i];
new_str[len_of_new_str+1] = '\0';
}
}
return new_str;
}
Hope this helps
String str="AABBCANCDE";
String newStr="";
for( int i=0; i<str.length(); i++)
{
if(!newStr.contains(str.charAt(i)+""))
newStr= newStr+str.charAt(i);
}
System.out.println(newStr);
// Remove both upper-lower duplicates
public static string RemoveDuplicates(string key)
{
string Result = string.Empty;
foreach (char a in key)
{
if (Result.Contains(a.ToString().ToUpper()) || Result.Contains(a.ToString().ToLower()))
continue;
Result += a.ToString();
}
return Result;
}
var input1 = Console.ReadLine().ToLower().ToCharArray();
var input2 = input1;
var WithoutDuplicate = input1.Union(input2);
Console.WriteLine("Enter String");
string str = Console.ReadLine();
string result = "";
result += str[0]; // first character of string
for (int i = 1; i < str.Length; i++)
{
if (str[i - 1] != str[i])
result += str[i];
}
Console.WriteLine(result);
I like Quintin Robinson answer, only there should be some improvements like removing List, because it is not necessarry in this case.
Also, in my opinion Uppercase char ("K") and lowercase char ("k") is the same thing, so they should be counted as one.
So here is how I would do it:
private static string RemoveDuplicates(string textEntered)
{
string newString = string.Empty;
foreach (var c in textEntered)
{
if (newString.Contains(char.ToLower(c)) || newString.Contains(char.ToUpper(c)))
{
continue;
}
newString += c.ToString();
}
return newString;
}
Not sure how optimal it is:
public static string RemoveDuplicates(string input)
{
var output = string.Join("", input.ToHashSet());
return output;
}
Below is the code to remove duplicate chars from a string
var input = "SaaSingeshe";
var filteredString = new StringBuilder();
foreach(char c in input)
{
if(filteredString.ToString().IndexOf(c)==-1)
{
filteredString.Append(c);
}
}
Console.WriteLine(filteredString);
Console.ReadKey();
namespace Demo { class Program {
static void Main(string[] args) {
string myStr = "kkllmmnnouo";
Console.WriteLine("Initial String: "+myStr);
// var unique = new HashSet<char>(myStr);
HashSet<char> unique = new HashSet<char>(myStr);
Console.Write("New String after removing duplicates: ");
foreach (char c in unique)
Console.Write(c);
} } }
this works for me
private string removeDuplicateChars(String value)
{
return new string(value.Distinct().ToArray());
}

Categories