I am trying to code the following example.
Input ABCDEFGHIJKLMNOPQRSTUVWXYZ
Output ZYXWVUTSRQPONMLKJIHGFEDCBA
If user types in A it will output Z. It has to go past 25 characters to reach Z. So I am guessing a while loop will be needed, then if B it has to go through 23 times, so – 2 and so on until it reaches M as it will skip though 1 to reach N, then start again at 25.
Any suggestion on how to approach this?
Capital ASCII characters range according to the ASCII-table from 65 (0x41, 'A') to 90 (0x5A, 'Z').
This is the algorithm:
// inputChar is a char holding your character
char inputChar = getCharFromUser();
int inputVal = inputChar - 65; // e.g. 0 for 'A', 1 for 'B'
char outputChar = 90 - inputVal; // e.g. 90 - 1 = 89 = 'Y'
outputCharToUser(outputChar);
And this is how you might implement it in C#:
while (true)
{
var key = Console.ReadKey(intercept: true);
var inputChar = char.ToUpper(key.KeyChar);
var outputChar = (char)('Z' - inputChar + 'A');
Console.Write("{0}={1} ", inputChar, outputChar);
}
You could use two dictionaries which enable to lookup the char from index and vice-versa:
var indexLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.chr, x => x.index);
var charLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.index, x => x.chr);
Now it's simple, the essential part is charLookup[25 - indexOfChar]:
string userInput = "B";
bool isUpper = char.IsUpper(userInput[0]);
char inputChar = Char.ToLowerInvariant(userInput[0]);
if(indexLookup.ContainsKey(inputChar))
{
int indexOfChar = indexLookup[inputChar];
char oppositeChar = charLookup[25 - indexOfChar];
string result = isUpper ? Char.ToUpperInvariant(oppositeChar).ToString() : oppositeChar.ToString();
Console.Write(result); // Y
}
Actually you don't need two dictionaries but only one since the string can already be used to lookup a char by index. Here is a class which provides the logic:
public class CharSwap
{
private string alphabet;
private Dictionary<char, int> indexLookup;
public CharSwap() : this("abcdefghijklmnopqrstuvwxyz") { }
public CharSwap(string alphabet)
{
if(alphabet == null) throw new ArgumentNullException("alphabet");
this.alphabet = alphabet;
indexLookup = alphabet.Select((chr, index) => new { chr, index }).ToDictionary(x => x.chr, x => x.index);
}
public char? OppositeChar(char input)
{
char lowerChar = Char.ToLowerInvariant(input);
if (!indexLookup.ContainsKey(lowerChar))
return null;
int indexOfChar = indexLookup[lowerChar];
int indexOpposite = alphabet.Length - 1 - indexOfChar;
return Char.IsUpper(input)
? Char.ToUpperInvariant(alphabet[indexOpposite])
: alphabet[indexOpposite];
}
}
Test:
CharSwap cw = new CharSwap();
char? oppositeChar = cw.OppositeChar('B');
Console.Write(oppositeChar);
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range[Range.Length - 1 - Range.IndexOf(input)]; //Y
or maybe another approach
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range.Reverse().ElementAt(Range.IndexOf(input)); //Y
How about something like this?
char[] alphabet = {'A','B', 'C'} // and so on
char[] mapsTo = {'Z', 'Y', 'X'} // and so on, excluded for brevity
public function string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i];
}
i++;
}
return '';
}
Converted to c#:
char[] alphabet = {'A','B', 'C'}; // and so on
char[] mapsTo = {'Z', 'Y', 'X'}; // and so on, excluded for brevity
public string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i].ToString();
}
i++;
}
return default(char).ToString();
}
You would call this function like this (for instance):
public static void RunProgram()
{
Console.WriteLine("Please type in character");
input = Console.ReadKey().KeyChar;
Console.WriteLine("You typed in " + input + ". This results in: " + ChangeInput(input));
}
... where "ChangeInput" is the function defined earlier.
The easy way to solve this is to use a Dictionary<char, char>:
public class Atbash {
static string source = "abcdefghijklmnopqrstuvwxyz";
static List<char> keys = source.ToList();
static List<char> values = source.Reverse().ToList();
static Dictionary<char, char> Converter = keys.ToDictionary(x => x, x => values[keys.IndexOf(x)]);
public static char Convert(char input)
{
char output;
bool isUpper = char.IsUpper(input);
input = char.ToLowerInvariant(input);
if(Converter.ContainsKey(input)) {
output = Converter[input];
return (isUpper) ? char.ToUpperInvariant(output) : output;
}
throw new ArgumentOutOfRangeException("Input char is unknown");
// of course, it can return default(char) instead of throwing an exception.
}
}
Why Atbash? read about it here.
Related
Write a function which takes a string input and removes all the characters which appear more than or equal to the given number.
RemoveCharacters("Spanish", 2) should return "panih"
RemoveCharacters("Spanish", 3) should return "Spanish"
string text = "Spanish";
var sb = new StringBuilder(text.Length);
int maxCount = 2;
int currentCount = 2;
char specialChar = 'S';
foreach (char c in text)
if (c != specialChar || ++currentCount <= maxCount)
sb.Append(c);
text = sb.ToString();
int commasFound = 0;
int maxCommas = 1;
text = new string(text.Where(c => c != 'S' || ++commasFound <= maxCommas).ToArray());
Console.WriteLine(text);
Let's process the string in two steps:
Find out characters to remove (which apperas more or equal than count times)
Remove such characters from the string.
Implemenattaion
private static String RemoveCharacters(string value, int count) {
if (string.IsNullOrEmpty(value))
return value;
else if (count <= 1)
return "";
HashSet<char> toRemove = new HashSet<char>(value
.GroupBy(c => char.ToUpper(c))
.Where(chunk => chunk.Count() >= count)
.Select(chunk => chunk.Key));
return string.Concat(value.Where(c => !toRemove.Contains(char.ToUpper(c))));
}
Some tests:
string[] tests = new string[] {
"Spanish",
"bla-bla-bla",
"Abracadabra",
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test,-15} => '{RemoveCharacters(test, 2)}'"));
Console.Write(report);
Outcome:
Spanish => 'panih' // S is removed
bla-bla-bla => '' // all characters are removed
Abracadabra => 'cd' // A, b, r are removed
I'm not writing your homework for you, but consider using a dictionary. Iterate the characters in your word. If it exists in your dictionary, increment that element. Otherwise insert it in your dictionary with a value of 1. Then iterate your dictionary keys and note which ones exceed your target. Finally, write out your string excluding those characters.
I am trying to complete a brain teaser which has a bug and I cant find it. Just wondering if anyone knows the answer. My goal is to return the character that appears most often.
public string solution(string S)
{
int[] occurrences = new int[26];
foreach (char ch in S)
{
occurrences[ch - 'a']++;
}
char best_char = 'a';
int best_res = 0;
for (int i = 1; i < 26; i++)
{
if (occurrences[i] >= best_res)
{
best_char = (char)('a' + i);
best_res = occurrences[i];
}
}
return best_char.ToString();
}
You have small mistake. Your index should start from 0, not 1
for (int i = 0; i < 26; i++)
{
if (occurrences[i] >= best_res)
{
best_char = (char)('a' + i);
best_res = occurrences[i];
}
}
Another and safer version is that
public string Solution(string text)
{
string strResponse = string.Empty;
if (!string.IsNullOrEmpty(text))
{
List<KeyValuePair<char, int>> occurance = text.GroupBy(ch => ch)
.Where(grp => char.IsLetter(grp.Key))
.Select(grp => new KeyValuePair<char, int>(grp.Key, grp.Count()))
.OrderByDescending(c => c.Value)
.ToList();
if (occurance.Any())
strResponse = occurance.First().Key.ToString();
}
return strResponse;
}
There could actually be more than one character with the maximum number of occurrences, so:
private static Char[] GetMostFrequentChars(String text)
{
Dictionary<Char,Int32> rank = new Dictionary<Char,Int32>();
foreach (Char c in text.Where(c => !char.IsWhiteSpace(c)))
{
if (rank.ContainsKey(c))
rank[c]++;
else
rank.Add(c, 1);
}
return rank.Where(r => r.Value == rank.Values.Max()).Select(x => x.Key).ToArray();
}
If you don't care about special characters (like spaces), you could do this with LINQ:
public static GetMostFrequentCharacter(string value)
{
return value
.GroupBy(o => o)
.OrderByDescending(o => o.Count())
.First()
.Key
.ToString()
}
There are at least 2 problems:
as #Adem Çatamak says, for loop should start at index 0
ch - 'a' will throw an exception if the string contains any other character than a-z lowercase,
public static string solution(string S)
{
var charDict = new Dictionary<char, int>();
foreach (char c in S.Where(c => !char.IsWhiteSpace(c)))
{
if(!charDict.TryGetValue(c, out int count))
{
charDict[c] = 1;
}
charDict[c]++;
}
return charDict.OrderByDescending(kvp => kvp.Value).First().Key.ToString();
}
Using a dictionary and LINQ is going to be better I think. Don't just copy this code and paste it into what ever homework or class this is for, use it to learn otherwise its a waste of my time and yours really
I have * strings and I want the only unknown character and its position. For instance, I want character 'a' or 'b' or 'c' or anything (unknown) and its positions in the strings below:
1) "******a***" // I want 'a'
2) "b****" // I want 'b'
3) "*******c" // I want 'c'
The strings are always have * characters. Sometimes I have 'a', sometimes 'n', sometimes 'x', and so on. I don't know what character coming inside stars (*).
How can I do this in C#?
Try this:
// the string
var str = "******a***";
// the character
var chr = str.Single(x => x != '*');
// the position
var pos = str.IndexOf(chr);
Please be aware that Single will throw an exception in case nothing found. Use it only when you're certain there's one (and only one) unknown character. If you're not sure use SingleOrDefault and check for Char.MinValue.
With regex
public static char GetUnknownChar(string s, char knownChar)
{
const string mask = "[^{0}]";
var match = Regex.Match(s, string.Format(mask, knownChar));
return match.Value[0];
}
with LINQ:
public static char GetUnknownChar(string s, char knownChar)
{
return s.First(c => c != knownChar);
}
with multiple known chars:
public static char GetUnknownChar(string s, IEnumerable<char> knownChars)
{
var knownSet = new HashSet<char>(knownChars);
return s.First(knownSet.Contains);
}
You can use String.IndexOf to get the positions
How about this:
string foo = "**x*";
char[] knownChars = new char[]{'*','!','?'};
int i = 0;
for (; i < foo.Length; i++)
if (knownChars.Contains(foo[i]))
break;
Here's a more primitive way:
public class Program
{
public static void Main(string[] args)
{
FindUnknown("******a***");
FindUnknown("b****");
FindUnknown("*******c");
}
private static void FindUnknown(string myString)
{
var tag = '*';
var unknown = ' ';
var unknownIndex = -1;
var currentIndex = 0;
foreach (var character in myString)
{
if (character != tag)
{
unknown = character;
unknownIndex = currentIndex;
break;
}
currentIndex++;
}
Console.WriteLine(String.Format("Unknown character: {0}", unknown));
Console.WriteLine(String.Format("Unknown character index: {0}", unknownIndex));
}
}
Here's a relatively novel yet understandable LINQ solution:
var strings = new[] {"******a***", "b****", "*******c"};
foreach (var str in strings)
{
var prefix = str.TakeWhile(c => c.Equals('*'));
var postPrefixIndex = prefix.Count();
var unknownCharacter = str[postPrefixIndex];
Console.WriteLine("{0} at {1}", unknownCharacter, postPrefixIndex);
}
// a at 6
// b at 0
// c at 7
// Press any key to continue . . .
Hello I'm having a little trouble on this one aspect in my code. I have some strings and I have a array of chars. I'm trying to replace the last two letters of each string
with the characters in the char array until the last one.
My array of char is as follows:
char[] array = { 'v', 'x', 'f' };
My code so far:
char[] array = { 'v', 'x', 'f' };
string newWord="";
string apple="apple";
string sam="sam";
foreach(char c in array)
{
apple= apple.Substring(0, apple.Length - 2) +""; ///DON'T KNOW WHAT TO PUT HERE;
sam= sam.Substring(0, sam.Length - 2)+""; ///DON'T KNOW WHAT TO PUT HERE;
newWord = apple+Environment.NewLine+sam ;
}
The output should like like this:
appvx
sfm
Maybe I'm doing this wrong but I'm explicitly telling it in the substring to get rid of the last to letters in the word but if the array runs out won't it still delete the last two. For instance the word sam still needs to have m at the end of it since all the chars in the array have already been used like what the out but shows but replace a with f
something like this?
private static void something()
{
List<char> tokens = new List<char>(new char[]{ 'v', 'x', 'f' });
List<char[]> lArr = new List<char[]>();
lArr.Add("apple".ToCharArray());
lArr.Add("sam".ToCharArray());
List<string> lStr = new List<string>();
int cnt = 2;
foreach (var token in tokens)
{
var aktArr = lArr.FirstOrDefault();
if (aktArr == null)
break;
if (cnt == 0)
{
cnt = 2;
lStr.Add(new string(aktArr));
lArr.RemoveAt(0);
aktArr = lArr.FirstOrDefault();
if (aktArr == null)
break;
}
aktArr[aktArr.Length - cnt--] = token;
}
lStr.AddRange(lArr.Select(x => new string(x)));
foreach (var item in lStr)
{
Console.WriteLine(item);
}
}
You can treat a string as an array of chars, so the result can be something like this (supposing that you have an array of words, not only 2 variables for them and a little helper to replace chars)
var words = new [] {"apple", "sam"};
var wordPos = 0;
for (int i = 0; i < array.Length; i++)
{
var wordLen = words[wordPos].Length;
var letterPos = i % 2 == 0 ? 1 : 2;
words[wordPos] = words[wordPos].ReplaceAt(wordLen - letterPos, letter);
if (letterPos == 1) wordPos++;
}
public static string ReplaceAt(this string input, int index, char newChar)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
char[] chars = input.ToCharArray();
chars[index] = newChar;
return new string(chars);
}
I think something like this will do what you need:
var charArray = new[] {'a', 'b', 'c'};
var words = new List<string> {"apple", "sam"};
var currentWord = 0;
var currentChar = 0;
var charsToReplace = 2;
while (currentChar < charArray.Length && currentWord != words.Count)
{
var word = words[currentWord].ToCharArray();
word[word.Length - charsToReplace] = charArray[currentChar];
words[currentWord] = new string(word);
charsToReplace--;
currentChar++;
if (charsToReplace == 0)
{
charsToReplace = 2;
currentWord++;
}
}
words.ForEach(Console.WriteLine);
I am doing a security presentation for my Computer and Information Security course in a few weeks time, and in this presentation I will be demonstrating the pros and cons of different attacks (dictionary, rainbow and bruteforce). I am do the dictionary and rainbow attacks fine but I need to generate the bruteforce attack on the fly. I need to find an algorithm that will let me cycle though every combination of letter, symbol and number up to a certain character length.
So as an example, for a character length of 12, the first and last few generations will be:
a
ab
abc
abcd
...
...
zzzzzzzzzzzx
zzzzzzzzzzzy
zzzzzzzzzzzz
But it will also use numbers and symbols, so it's quite hard for me to explain... but I think you get the idea. Using only symbols from the ASCII table is fine.
I can kind of picture using an ASCII function to do this with a counter, but I just can't work it out in my head. If anyone could provide some source code (I'll probably be using C#) or even some pseudo code that I can program a function from that'd be great.
Thank you in advance. :)
A recursive function will let you run through all combinations of ValidChars:
int maxlength = 12;
string ValidChars;
private void Dive(string prefix, int level)
{
level += 1;
foreach (char c in ValidChars)
{
Console.WriteLine(prefix + c);
if (level < maxlength)
{
Dive(prefix + c, level);
}
}
}
Assign the set of valid characters to ValidChars, the maximum length of string you want to maxlength, then call Dive("", 0); and away you go.
You need to generate all combinations of characters from a set of valid characters ; let's call this set validChars. Basically, each set of combinations of length N is a cartesian product of validChars with itself, N times. That's pretty easy to do using Linq:
char[] validChars = ...;
var combinationsOfLength1 =
from c1 in validChars
select new[] { c1 };
var combinationsOfLength2 =
from c1 in validChars
from c2 in validChars
select new[] { c1, c2 };
...
var combinationsOfLength12 =
from c1 in validChars
from c2 in validChars
...
from c12 in validChars
select new[] { c1, c2 ... c12 };
var allCombinations =
combinationsOfLength1
.Concat(combinationsOfLength2)
...
.Concat(combinationsOfLength12);
Obviously, you don't want to manually write the code for each length, especially if you don't know in advance the maximum length...
Eric Lippert has an article about generating the cartesian product of an arbitrary number of sequences. Using the CartesianProduct extension method provided by the article, you can generate all combinations of length N as follows:
var combinationsOfLengthN = Enumerable.Repeat(validChars, N).CartesianProduct();
Since you want all combinations from length 1 to MAX, you can do something like that:
var allCombinations =
Enumerable
.Range(1, MAX)
.SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct());
allCombinations is an IEnumerable<IEnumerable<char>>, if you want to get the results as a sequence of strings, you just need to add a projection:
var allCombinations =
Enumerable
.Range(1, MAX)
.SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct())
.Select(combination => new string(combination.ToArray()));
Note that it's certainly not the most efficient solution, but at least it's short and readable...
You can try this code, that use recursion to print all possible strings of 0 to stringsLenght chars lenght, composed by all combination of chars from firstRangeChar to lastRangeChar.
class BruteWriter
{
static void Main(string[] args)
{
var bw = new BruteWriter();
bw.WriteBruteStrings("");
}
private void WriteBruteStrings(string prefix)
{
Console.WriteLine(prefix);
if (prefix.Length == stringsLenght)
return;
for (char c = firstRangeChar; c <= lastRangeChar; c++)
WriteBruteStrings(prefix + c);
}
char firstRangeChar='A';
char lastRangeChar='z';
int stringsLenght=10;
}
This look to be faster than the solution of #dthorpe.I've compared the algorthms using this code:
class BruteWriter
{
static void Main(string[] args)
{
var st = new Stopwatch();
var bw = new BruteWriter();
st.Start();
bw.WriteBruteStrings("");
Console.WriteLine("First method: " + st.ElapsedMilliseconds);
for (char c = bw.firstRangeChar; c <= bw.lastRangeChar; c++)
bw.ValidChars += c;
st.Start();
bw.Dive("", 0);
Console.WriteLine("Second method: " + st.ElapsedMilliseconds);
Console.ReadLine();
}
private void WriteBruteStrings(string prefix)
{
if (prefix.Length == stringsLenght)
return;
for (char c = firstRangeChar; c <= lastRangeChar; c++)
WriteBruteStrings(prefix + c);
}
char firstRangeChar='A';
char lastRangeChar='R';
int stringsLenght=5;
int maxlength = 5;
string ValidChars;
private void Dive(string prefix, int level)
{
level += 1;
foreach (char c in ValidChars)
{
if (level <= maxlength)
{
Dive(prefix + c, level);
}
}
}
}
and, on my pc, I get these results:
First method: 247
Second method: 910
public void BruteStrings(int maxlength)
{
for(var i=1;i<i<=maxlength;i++)
BruteStrings(Enumerable.Repeat((byte)0,i));
}
public void BruteStrings(byte[] bytes)
{
Console.WriteLine(bytes
.Cast<char>()
.Aggregate(new StringBuilder(),
(sb,c) => sb.Append(c))
.ToString());
if(bytes.All(b=>b.MaxValue)) return;
bytes.Increment();
BruteStrings(bytes);
}
public static void Increment(this byte[] bytes)
{
bytes.Last() += 1;
if(bytes.Last == byte.MinValue)
{
var lastByte = bytes.Last()
bytes = bytes.Take(bytes.Count() - 1).ToArray().Increment();
bytes = bytes.Concat(new[]{lastByte});
}
}
Another alternative i did, that return a string.
I did not care about the performance of the thing since it was not for a real world scenario.
private void BruteForcePass(int maxLength)
{
var tempPass = "";
while (tempPass.Length <= maxLength)
{
tempPass = GetNextString(tempPass);//Use char from 32 to 256
//Do what you want
}
}
private string GetNextString(string initialString, int minChar= 32, int maxChar = 256)
{
char nextChar;
if (initialString.Length == 0)
{
nextChar = (char)minChar;//the initialString Length will increase
}
else if (initialString.Last() == (char)maxChar)
{
nextChar = (char)minChar;
var tempString = initialString.Substring(0, initialString.Length -1);//we need to increment the char just before the last one
initialString = GetNextString(tempString, minChar, maxChar);
}
else
{
nextChar = (char)(initialString.Last() + 1);//Get the lash Char and increment it;
initialString= initialString.Remove(initialString.Length - 1);//Remove the last char.
}
return initialString + nextChar;
}