Replacing letters in words - c#

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);

Related

Delete part of string value

I want to mix 2 string in 1 randomly using foreach but I don't know how I delete the part I used on the string for the foreach like:
string s = "idontknow";
string sNew = "";
foreach(char ss in s){
s = s + ss;
ss.Delete(s); //don't exist
}
Full code here i'm trying to do:
do
{
if (state == 0)
{
for (int i = 0; random.Next(1, 5) > variable.Length; i++)
{
foreach (char ch in variable)
{
fullString = fullString + ch;
}
}
state++;
}
else if (state == 1)
{
for (int i = 0; random.Next(1, 5) > numbers.Length; i++)
{
foreach (char n in numbers)
{
fullString = fullString + n;
}
}
state--;
}
} while (variable.Length != 0 && numbers.Length != 0);
I'm pretty confident, that in your first code snippet, you are creating an infinite loop, since you are appending the used char back to the string while removing it from the first position.
Regarding your specification to shuffle two stings together, this code sample might do the job:
public static string ShuffleStrings(string s1, string s2){
List<char> charPool = new();
foreach (char c in s1) {
charPool.Add(c);
}
foreach (char c in s2) {
charPool.Add(c);
}
Random rand = new();
char[] output = new char[charPool.Count];
for(int i = 0; i < output.Length; i++) {
int randomIndex = rand.Next(0, charPool.Count);
output[i] = charPool[randomIndex];
charPool.RemoveAt(randomIndex);
}
return new string(output);
}
In case you just want to shuffle one string into another string, just use an empty string as the first or second parameter.
Example:
string shuffled = ShuffleStrings("TEST", "string");
Console.WriteLine(shuffled);
// Output:
// EgsTtSnrTi
There are possibly other solutions, which are much shorter, but I think this code is pretty easy to read and understand.
Concerning the performance, the code above should works both for small stings and large strings.
Since strings are immutable, each modify-operation on any string, e.g. "te" + "st" or "test".Replace("t", ""), will allocate and create a new string in the memory, which is - in a large scale - pretty bad.
For that very reason, I initialized a char array, which will then be filled.
Alternatively, you can use:
using System.Text;
StringBuilder sb = new();
// append each randomly picked char
sb.Append(c);
// Create a string from appended chars
sb.ToString();
And if your question was just how to remove the first char of a string:
string myStr = "Test";
foreach (char c in myStr) {
// do with c whatever you want
myStr = myStr[1..]; // assign a substring exluding first char (start at index 1)
Console.WriteLine($"c = {c}; myStr = {myStr}");
}
// Output:
// c = T; myStr = est
// c = e; myStr = st
// c = s; myStr = t
// c = t; myStr =

String of hex into a byte array? [duplicate]

This question already has answers here:
How can I convert a hex string to a byte array? [duplicate]
(4 answers)
Closed 5 years ago.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9"
splitRHash2 = splitRHash.Split('|');
foreach (string i in splitRHash2)
{
//BYTEARRAY += Convert.ToByte(Convert.ToInt32(i, 16))???
}
I have no idea of going about this. I simply wanted this string of hex:
4ADA6CA9C2D571EF6E2A8CC3C94D36B9
Into a byte array with 16 bytes. This will greatly help me to call these values from the 'hash' and use it add round keys later on for a project. The problem is, I have no knowledge in getting the string at increments of 2 without using the .split method.
Any ideas? Thanks!!
Simply use LINQ to convert the splitted strings to bytes and to an array afterwards. Here is the code:
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
string[] splittedHash = hash.Split('|');
byte[] byteHash = splittedHash.Select(b => Convert.ToByte(b, 16)).ToArray();
You talking about something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp
{
class Program
{
static void Main (string[] args)
{
var str = "4ADA6CA9C2D571EF6E2A8CC3C94D36B9";
var result = Partition (str, 2).ToArray ();
}
public static IEnumerable<string> Partition (string str, int partSize)
{
if (str == null) throw new ArgumentNullException ();
if (partSize < 1) throw new ArgumentOutOfRangeException ();
var sb = new StringBuilder (partSize);
for (int i = 0; i < str.Length; i++)
{
sb.Append (str[i]);
bool isLastChar = i == str.Length - 1;
if (sb.Length == partSize || isLastChar)
{
yield return sb.ToString ();
sb.Clear ();
}
}
}
}
}
You could make the solution with only basic data structures and O(n) time like this.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
byte[] result = new byte[16];
int i = 0;
int j = 0;
while(i < hash.Length)
{
byte value = (byte)(HexCharToByte(hash[i]) * 16 + HexCharToByte(hash[i + 1]));
result[j] = value;
i += 3;
j++;
}
For HexCharToByte(), you could make up something like this:
static byte HexCharToByte(char c)
{
HashSet<char> NumSet = new HashSet<char>( new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} );
HashSet<char> CharSet = new HashSet<char>( new char[] { 'A', 'B', 'C', 'D', 'E', 'F' } );
if (NumSet.Contains(c))
{
return (byte)(c - '0');
}
else if (CharSet.Contains(c))
{
return (byte)(c - 'A' + 10);
}
throw new InvalidArgumentException("c");
}

Spliting a string by capital letters except for certain keywords

The following function splits a string at any uppercase character found within the string.
public static string ToSentence(this string input)
{
var list = new List<char>();
for (var i = 0; i < input.ToCharArray().Length; i++)
{
var c = input.ToCharArray()[i];
foreach (char c1 in i > 0 && char.IsUpper(c) ? new[] {' ', c} : new[] {c})
list.Add(c1);
}
return new string(list.ToArray());
}
In my code, this function is being used in conjunction with another function that retrieves the name of the current method in code. I'm finding this function breaks when a method name contains multiple capital letters sequentially.
For example, if I have a method called GetDatabaseIDE() it would return as "Get Database I D E"
How can I change my ToSentence function so that it accepts a list of keywords that won't be split (For example, I D E becomes IDE)?
Why not try Regex ? Demo # https://dotnetfiddle.net/FsPZ9O
1. ([A-Z]+) - match all leading uppercase char.
2. ([^A-Z])* - followed with zero-or-more of any that isn't an uppercase char.
Regex.Matches("GetDatabaseIDE", #"([A-Z]+)([^A-Z])*").Cast<Match>().Select(m => m.Value);
TakeWhile method can be useful here, once you find an upper case character, you can take the following upper case characters:
for (var i = 0; i < input.Length; i++)
{
var c = input[i];
if(char.IsUpper(c))
{
var charsToAdd = input.Skip(i).TakeWhile(char.IsUpper).ToArray();
if(charsToAdd.Length > 1)
{
i += charsToAdd.Length - 1;
}
if(i > 0) list.Add(' ');
list.Add(charsToAdd);
}
else
{
list.Add(c);
}
}
you can add keywords you want to skip:
public static string ToSentence(string input)
{
var list = new List<char>();
for (var i = 0; i < input.ToCharArray().Length; i++)
{
if(input.IndexOf("IDE",i,input.Length-i)==i){
list.AddRange(" IDE");
i+=2;
}
else{
var c = input.ToCharArray()[i];
foreach (char c1 in i > 0 && char.IsUpper(c) ? new[] {' ', c} : new[] {c})
list.Add(c1);
}
}
return new string(list.ToArray());
}
watch it here
This will work for your example, you will have to tweak it if your method names have numbers in them
using System.Text.RegularExpressions;
public static string GetNiceName(string testString)
{
var pattern = "([A-Z][a-z]+)|([A-Z]+)";
var result = new List<string>();
foreach (Match m in Regex.Matches(testString, pattern))
{
result.Add(m.Groups[0].Value);
}
return string.Join(" ", result);
}

While loop for alphabet

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.

C#: Find Unknown Character in a String

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 . . .

Categories

Resources