Reputation: 103
I have made a code that works but Is there a way to make it better
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r).Replace("-", string.Empty);
string h = c.Replace("A", "K").Replace("B", "L").Replace("C", "M").Replace("D", "N").Replace("E", "O")
.Replace("F", "P").Replace("0", "A").Replace("1","B").Replace("2", "C").Replace("3", "D").Replace("4", "E")
.Replace("5", "F").Replace("6", "G").Replace("7", "H").Replace("8", "I")
.Replace("9", "J");
Console.WriteLine(h.ToLower());
It replace 0-9
with A-J
example 0-A | 1-B | 2-C
and it replace
A-F
with K-P
example A-K | B-L | C-M
output must be:
fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal
Note: that this works I only want to know If there is a easier way to do that.
EDIT: Thanxs for all the answers I really dont know which one is the best one but I think that one I marked as answered should be it!
Upvotes: 3
Views: 480
Reputation: 273844
The BitConverter.ToString(r).Replace()
stuff is an awful detour.
const string lookup = "abcdefghijklmnop";
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string h = string.Concat(r.Select(b => "" + lookup[b >> 4] + lookup[b & 0xf]));
System.Diagnostics.Debug.Assert(h == "fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal");
Optimized code:
const string lookup = "abcdefghijklmnop";
public string Decode(string input)
{
byte[] buf = Convert.FromBase64String(input);
var result = new StringBuilder(buf.Length*2);
foreach (byte b in buf)
{
result.Append(lookup[b >> 4]).Append(lookup[b & 0xf]);
}
return result.ToString();
}
string h = Decode("XFEWtnopccImhpHTzGeoeXBg4ws=");
System.Diagnostics.Debug.Assert(h == "fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal");
Upvotes: 2
Reputation: 416149
If you know the length in advance (and you do in this situation), .Net Core has an even better option than StringBuilder
now (at least in terms of performance):
private static Dictionary<char, char> map = new Dictionary<char, char> {
{'A', 'k'}, {'B', 'l'}, {'C', 'm'}, {'D', 'n'}, {'E', 'o'}, {'F', 'p'},
{'0', 'a'},{'1', 'b'}, {'2', 'c'}, {'3', 'd'},{'4', 'e'}, {'5', 'f'},
{'6', 'g'},{'7', 'h'},{'8', 'i'}, {'9', 'j'}
};
public static string GetMyString(string input)
{
byte[] b = Convert.FromBase64String(input);
string source = BitConverter.ToString(b);
return string.Create(2*(input.Length+1)/3 , input, (r, d) => {
int j = 0;
foreach(char c in d)
{
if (c == '-') continue;
r[j++] = map[c];
}
});
}
Console.WriteLine(GetMyString("XFEWtnopccImhpHTzGeoeXBg4ws="));
If I were to use StringBuilder
, I know I could easily remove that last .Replace()
call and the ToLower()
call, both of which allocate and copy whole new strings:
public static string GetMyString(string input)
{
byte[] b = Convert.FromBase64String(input);
string source = BitConverter.ToString(b);
var result = new StringBuilder(2*(input.Length+1)/3);
foreach(char c in input)
{
if (c == '-') continue;
result.Append(map[c]);
}
return result.ToString();
}
I haven't benchmarked, but I would expect this to significantly out-perform the other Dictionary/StringBuilder-based answer... but that's what I get for taking longer to answer and providing two solutions ;)
Upvotes: 0
Reputation: 849
How about a regex solution?
Dictionary<string, string> map = new Dictionary<string, string>{{"A", "K"}, {"B", "L"}, {"C", "M"}, {"D", "N"}, {"E", "O"},
{"F", "P"}, {"0", "A"}, {"1", "B"}, {"2", "C"}, {"3", "D"},
{"4", "E"}, {"5", "F"}, {"6", "G"}, {"7", "H"}, {"8", "I"},
{"9", "J"}};
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r).Replace("-", string.Empty);
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(c, m => map[m.Value]);
Console.WriteLine(newStr.ToLower());
Upvotes: 0
Reputation: 1347
You could also do the following:
static string DecodeWithoutLinq(string encoded)
{
char[] s = new char[encoded.Length];
for (int i = 0; i < encoded.Length; i++)
{
char currentChar = encoded[i];
if (char.IsLetter(currentChar))
s[i] = (char)(encoded[i] + 10);
else if (char.IsNumber(currentChar))
s[i] = (char)('A' + (currentChar - '0'));
}
return new string(s).ToLower();
}
static string DecodeWithLinq(string encoded)
{
return string.Concat(encoded.ToCharArray()
.Select(s => char.IsLetter(s) ? (char)(s + 10) : (char)('A' + (s - '0')))).ToLower();
}
static void Main(string[] args)
{
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r).Replace("-", string.Empty);
string decodedString1 = DecodeWithoutLinq(c);
string decodedString2 = DecodeWithLinq(c);
Console.WriteLine(decodedString1);
Console.WriteLine(decodedString2);
Console.ReadKey();
}
Just one way that doesn't involve string manipulation.
DecodeWithLinq isn't verifying if it's a number though. Can be easily added if needed.
Upvotes: 1
Reputation: 216363
You could store all your char transforms in a dictionary and then use a simple loop to replace the chars. Using a StringBuilder.Replace (using the char as input parameters overload) should be better because it avoids the constant creation of new strings at each string.Replace call and there is no worry about string size changes.
Dictionary<char, char> replacements = new Dictionary<char, char>
{
{'A', 'K'}, {'B', 'L'}, {'C', 'M'}, {'D', 'N'}, {'E', 'O'}, {'F', 'P'},
{'0', 'A'}, {'1', 'B'}, {'2', 'C'}, {'3', 'D'}, {'4', 'E'}, {'5', 'F'},
{'6', 'G'}, {'7', 'H'}, {'8', 'I'}, {'9', 'J'}
};
void Main()
{
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r).Replace("-", string.Empty);
StringBuilder sb = new StringBuilder(c);
foreach(char x in replacements.Keys)
sb.Replace(x, replacements[x]);
Console.WriteLine(sb.ToString().ToLower());
}
Upvotes: 3
Reputation: 11216
This is my solution which uses a couple of arrays and a bit of Linq.
void Main()
{
string inputChars = "0123456789ABCDEF";
string replacementChars = "ABCDEFGHIJKLMNOP";
byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r);
string result = new String(c.Where(ch => inputChars.Contains(ch))
.Select(ch => replacementChars[inputChars.IndexOf(ch)])
.ToArray());
Console.WriteLine(result.ToLower());
}
Upvotes: 0