This is my code for generating words for my unity Hangman game.
public string GenerateWord()
{
int index = Random.Range(0, useWords.words.Length);
string word = useWords.words[index];
GenerateType(index);
GenerateDetails(index);
return word;
}
#region Generating Words
public void NextWord()
{
ClearSPlitWord();
GetWord();
DisplayNumberofCharacter();
}
void GetWord()
{
word = WordManager.instance.GenerateWord();
SplitWord();
}
void DisplayNumberofCharacter()
{
ClearPrevoisCharacters();
for (int i = 0; i < word.Length; i++)
{
tempWords.Add(Instantiate(wordDisplayerPrefab, wordDisplayerParent));
}
}
void ClearPrevoisCharacters()
{
for (int i = 0; i < tempWords.Count; i++)
{
Destroy(tempWords[i]);
}
correctGuess = 0;
tempWords.Clear();
}
void ClearSPlitWord()
{
splitedWord.Clear();
}
#endregion
I try fixing in prefab I think I can fix there but I doesn't work I try searching on web and YT but they only use one words, I'm new in C# and Unity so I hope you can help me. Thank You.
One way would be to check if the char at the current position is a space.
In the end you probably want to check for other special characters like '-' as well.
This could be done by adding a check into your forloop in DisplayNumberofCharacters()
if(word[i] == ' '){
//we have a space here so do something like inserting a prefab that
//shows a space or something
}
if you are showing the count of your characters you probably want to subtract space or special characters as well.
I am not really sure what your SplitWord() actually does, if it splits the string and there are still spaces etc left you could trim your string
Related
I want to compare and check if a string is a part of another string. For example:
String1 = "ACGTAAG"
String2 = "TAA"
I want to check if String1 contains String2. Im using this code but it does not work.
public bool ContainsSequence(string input, string toBeChecked)
{
for (int i = 0; i < input.Length; i++)
{
Char x = input[i];
String y = Convert.ToString(x);
for (int j = 0; j < toBeChecked.Length; j++)
{
Char a = toBeChecked[j];
String b = Convert.ToString(a);
if (b.Equals(y))
{
j = toBeChecked.Length;
return true;
}
}
}
return false;
}
input = string1 and tobechecked = string 2.
Im new in c# so some terms may be confusing.
try use String.Contains()
Check it out here:
http://msdn.microsoft.com/en-us/library/dy85x1sa%28v=vs.110%29.aspx
Good luck.
Use
If(mainString.Contains(searchedString)
{
//do stuff
}
It looks to me like you're using this to compare DNA sequences :).
Maybe string.IndexOf(string value) or one of it's overloads is better for you because it can help
you search for further occurences of the same string (stuff like "how many times does it contain the string"): http://msdn.microsoft.com/en-us/library/k8b1470s(v=vs.110).aspx
If indeed all you want is just to see if the string is contained, I'd also go for the versions provided by the others.
For nucleotide sequences you probably want some sequence alignment algorithm which has some tolerance when sequences are not equal. For example Smith–Waterman algorithm.
I am in the process of learning C# and I'm building a hangman game from scratch as one of my first projects.
Everything works except for the part that replaces the dashes of the hidden word with the correctly guessed letters.
For example: ----- becomes G-EA- after you guess G, E, and A.
I have a for loop that logically seems like it'd do the job except I can't use the == operator for strings or chars.
for (int i = 0; i <= answer.Length; i++) //answer is a string "theword"
{
if (answer[i] == passMe) //passMe is "A" for example
{
hiddenWord = hiddenWord.Remove(i, 1);
hiddenWord = hiddenWord.Insert(i, passMe);
}
}
I've scoured the net trying to find a good solution. Most recommend using Regex or other commands I haven't learned yet and therefore don't fully understand how to implement.
I've tried converting both to char format in the hope that it would fix it, but no luck so far. Thanks in advance for any help.
If passMe is a string of only one char then
if (answer[i] == passMe[0])
In this way you compare the character at i-th position with the character at the first position of your user input
There is also a serious error in your code.
Your loop goes off by one, change it to
for (int i = 0; i < answer.Length; i++)
The arrays in NET start at index zero and, the max index value possible, is always one less than the length of the array.
answer[i] refers to a character and passMe is a single character string. (not a character)
Try this
for (int i = 0; i <= answer.Length; i++) //answer is a string "theword"
{
if (answer[i] == passMe[0]) //passMe is "A" for example
{
hiddenWord = hiddenWord.Remove(i, 1);
hiddenWord = hiddenWord.Insert(i, passMe);
}
}
you need to compare a character with a character.
This might be a very basic question. I need to write a code which works similar as string replace algorithm.
static string stringReplace(string s, string stringOld, string stringNew)
{
string newWord = "";
int oldMax = stringOld.Length;
int index = 0;
for (int i = 0; i < s.Length; i++)
{
if (index != oldMax && s[i] == stringOld[index])
{
if (stringOld[index] < stringNew[index])
{
newWord = newWord + stringNew[index];
index++;
}
else
{
newWord = newWord + stringNew[index];
}
}
else
{
newWord = newWord + s[i];
}
}
return newWord;
}
Since it's 3am the code above is probably bugged. When the new word is shorter than the old one, it goes wrong. Same as when it's longer. When the index variable is equal for both stringOld and stringNew, it will do the swap. I think... Please don't post "use string.Replace(), I have to write that algorithm myself...
I don't know what you're trying to do with your code, but the problem is not a small one.
Think logically about what you are trying to do.
It is a two step process:
Find the starting index of stringOld in s.
If found replace stringOld with stringNew.
Step 1:
There are many rather complex (and elegant) efficient string search algorithms, you can search for them online or look at popular 'Introduction to Algorithms' by Cormen, Leiserson, Rivest & Stein, but the naive approach involves two loops and is pretty simple. It is also described in that book (and online.)
Step 2:
If a match is found at index i; simply copy characters 0 to i-1 of s to newWord, followed by newString and then the rest of the characters in s starting at index i + oldString.Length.
Suppose I have a string that contains a text file, carriage returns and tabs and all. How do I find the index of the first blank line (to include lines-containing-only-whitespace) in that string?
What I've tried:
In this case, I have a working function that leverages a bunch of ugly code to find the index of the blank line. There must be a more elegant/readable way to do it than this.
To be clear, the below function returns the section from a string from a supplied 'title' to the index of the first blank line after the title. Supplied in full, since most of it is consumed by the search for that index, and to avoid any 'Why in the WORLD do you need the index of a blank line' questions. Also to counteract the XY Problem, if it's happening here.
The (apparently working, haven't tested all edge cases) code:
// Get subsection indicated by supplied title from supplied section
private static string GetSubSectionText(string section, string subSectionTitle)
{
int indexSubSectionBgn = section.IndexOf(subSectionTitle);
if (indexSubSectionBgn == -1)
return String.Empty;
int indexSubSectionEnd = section.Length;
// Find first blank line after found sub-section
bool blankLineFound = false;
int lineStartIndex = 0;
int lineEndIndex = 0;
do
{
string temp;
lineEndIndex = section.IndexOf(Environment.NewLine, lineStartIndex);
if (lineEndIndex == -1)
temp = section.Substring(lineStartIndex);
else
temp = section.Substring(lineStartIndex, (lineEndIndex - lineStartIndex));
temp = temp.Trim();
if (temp.Length == 0)
{
if (lineEndIndex == -1)
indexSubSectionEnd = section.Length;
else
indexSubSectionEnd = lineEndIndex;
blankLineFound = true;
}
else
{
lineStartIndex = lineEndIndex + 1;
}
} while (!blankLineFound && (lineEndIndex != -1));
if (blankLineFound)
return section.Substring(indexSubSectionBgn, indexSubSectionEnd);
else
return null;
}
FOLLOW-UP EDIT:
The result (based heavily on Konstantin's answer):
// Get subsection indicated by supplied title from supplied section
private static string GetSubSectionText(string section, string subSectionTitle)
{
string[] lines = section.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
int subsectStart = 0;
int subsectEnd = lines.Length;
// Find subsection start
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Trim() == subSectionTitle)
{
subsectStart = i;
break;
}
}
// Find subsection end (ie, first blank line)
for (int i = subsectStart; i < lines.Length; i++)
{
if (lines[i].Trim().Length == 0)
{
subsectEnd = i;
break;
}
}
return string.Join(Environment.NewLine, lines, subsectStart, subsectEnd - subsectStart);
}
The primary differences between the result and Konstantin's answer are due to framework version (I'm working with .NET 2.0, and it doesn't support string[].Take), and leveraging Environment.NewLine instead of the hardcoded '\n'. Much, much prettier and more readable than the original pass. Thanks all!
Have you tried using String.Split Method :
string s = "safsadfd\r\ndfgfdg\r\n\r\ndfgfgg";
string[] lines = s.Split('\n');
int i;
for (i = 0; i < lines.Length; i++)
{
if (string.IsNullOrWhiteSpace(lines[i]))
//if (lines[i].Length == 0) //or maybe this suits better..
//if (lines[i].Equals(string.Empty)) //or this
{
Console.WriteLine(i);
break;
}
}
Console.WriteLine(string.Join("\n",lines.Take(i)));
EDIT: responding the OP's edit.
By "blank line", you mean a line that contains only whitespace? Yes, you should use regex; the syntax you're looking for is #"(?<=\r?\n)[ \t]*(\r?\n|$)".
(?<=…) indicates a lookahead, something that should precede what you're looking for.
\r?\n indicates a newline, supporting both the Unix and Windows conventions.
(?<=\r?\n) is therefore a lookahead for the preceding newline.
[ \t]* means zero or more space or tab characters; these will match the content (if any) of your blank line.
(\r?\n|$) means newline or end-of-file.
Example:
string source = "Line 1\r\nLine 2\r\n \r\nLine 4\r\n";
Match firstBlankLineMatch = Regex.Match(source, #"(?<=\r?\n)[ \t]*(\r?\n|$)");
int firstBlankLineIndex =
firstBlankLineMatch.Success ? firstBlankLineMatch.Index : -1;
Just for fun: It seems like you're OK with re-allocating strings once per line. It would be possible then, to write an iterator that would lazily evaluate the string and return each line. For example:
IEnumerable<string> BreakIntoLines(string theWholeThing)
{
int startIndex = 0;
int endIndex = 0;
for(;;)
{
endIndex = theWholeThing.IndexOf(Environment.NewLine,startIndex) + Environment.NewLine.Count; //Remember to pick up the newline character(s) too!
if(endIndex = -1) //Didn't find a newline
{
//Return the end part of the string and finish
yield return theWholeThing.SubString(startIndex);
yield break;
}
else //Found a newline
{
//Return where we're at up to the newline
yield return theWholeThing.SubString(startIndex, endIndex - startIndex);
startIndex = endIndex;
}
}
}
You could then wrap that iterator in another one that only returns the lines you care about and discards the others.
IEnumerable<string> GetSubsectionLines(string theWholeThing, string subsectionTitle)
{
bool foundSubsectionTitle = false;
foreach(var line in BreakIntoLines(theWholeThing))
{
if(line.Contains(subSectionTitle))
{
foundSubsectionTitle = true; //Start capturing
}
if(foundSubsectionTitle)
{
yield return line;
} //Implicit "else" - Just discard the line if we haven't found the subsection title yet
if(String.IsNullOrWhiteSpace(line))
{
//This will stop iterating after returning the empty line, if there is one
yield break;
}
}
}
Now, this method (along with some of the others posted) do not do EXACTLY what your original code does. For example, if the text in subsectionTitle happens to span a line, it won't get found. We'll assume that the spec is written in such a way that this isn't allowed. This code will also make a copy of every line that gets returned which the original code did too, so that's probably OK.
The only benefit of doing it this way vs string.split, is that when you're done returning the SubSection, the rest of the string doesn't get evaluated. For most reasonably sized string you probably don't care. Any "performance gains" are likely to be non-existent. If you really cared about performance, you wouldn't be copying each line in the first place!
The other thing that you get (that actually could be valuable) is code re-use. If you're writing a program that parses documents, it's probably helpful to be able to operate on individual lines.
I'm doing some work with strings, and I have a scenario where I need to determine if a string (usually a small one < 10 characters) contains repeated characters.
`ABCDE` // does not contain repeats
`AABCD` // does contain repeats, ie A is repeated
I can loop through the string.ToCharArray() and test each character against every other character in the char[], but I feel like I am missing something obvious.... maybe I just need coffee. Can anyone help?
EDIT:
The string will be sorted, so order is not important so ABCDA => AABCD
The frequency of repeats is also important, so I need to know if the repeat is pair or triplet etc.
If the string is sorted, you could just remember each character in turn and check to make sure the next character is never identical to the last character.
Other than that, for strings under ten characters, just testing each character against all the rest is probably as fast or faster than most other things. A bit vector, as suggested by another commenter, may be faster (helps if you have a small set of legal characters.)
Bonus: here's a slick LINQ solution to implement Jon's functionality:
int longestRun =
s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
So, OK, it's not very fast! You got a problem with that?!
:-)
If the string is short, then just looping and testing may well be the simplest and most efficient way. I mean you could create a hash set (in whatever platform you're using) and iterate through the characters, failing if the character is already in the set and adding it to the set otherwise - but that's only likely to provide any benefit when the strings are longer.
EDIT: Now that we know it's sorted, mquander's answer is the best one IMO. Here's an implementation:
public static bool IsSortedNoRepeats(string text)
{
if (text.Length == 0)
{
return true;
}
char current = text[0];
for (int i=1; i < text.Length; i++)
{
char next = text[i];
if (next <= current)
{
return false;
}
current = next;
}
return true;
}
A shorter alternative if you don't mind repeating the indexer use:
public static bool IsSortedNoRepeats(string text)
{
for (int i=1; i < text.Length; i++)
{
if (text[i] <= text[i-1])
{
return false;
}
}
return true;
}
EDIT: Okay, with the "frequency" side, I'll turn the problem round a bit. I'm still going to assume that the string is sorted, so what we want to know is the length of the longest run. When there are no repeats, the longest run length will be 0 (for an empty string) or 1 (for a non-empty string). Otherwise, it'll be 2 or more.
First a string-specific version:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Now we can also do this as a general extension method on IEnumerable<T>:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Then you can call "AABCD".LongestRun() for example.
This will tell you very quickly if a string contains duplicates:
bool containsDups = "ABCDEA".Length != s.Distinct().Count();
It just checks the number of distinct characters against the original length. If they're different, you've got duplicates...
Edit: I guess this doesn't take care of the frequency of dups you noted in your edit though... but some other suggestions here already take care of that, so I won't post the code as I note a number of them already give you a reasonably elegant solution. I particularly like Joe's implementation using LINQ extensions.
Since you're using 3.5, you could do this in one LINQ query:
var results = stringInput
.ToCharArray() // not actually needed, I've left it here to show what's actually happening
.GroupBy(c=>c)
.Where(g=>g.Count()>1)
.Select(g=>new {Letter=g.First(),Count=g.Count()})
;
For each character that appears more than once in the input, this will give you the character and the count of occurances.
I think the easiest way to achieve that is to use this simple regex
bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, #"(\w)\1");
If you need more information about the match (start, length etc)
Match match = null;
string testString = "ABCDE AABCD";
match = Regex.Match(testString, #"(\w)\1+?");
if (match.Success)
{
string matchText = match.Value; // AA
int matchIndnex = match.Index; // 6
int matchLength = match.Length; // 2
}
How about something like:
string strString = "AA BRA KA DABRA";
var grp = from c in strString.ToCharArray()
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in grp)
{
Console.WriteLine(
string.Format("Character:{0} Appears {1} times",
item.Key.ToString(), item.Count));
}
Update Now, you'd need an array of counters to maintain a count.
Keep a bit array, with one bit representing a unique character. Turn the bit on when you encounter a character, and run over the string once. A mapping of the bit array index and the character set is upto you to decide. Break if you see that a particular bit is on already.
/(.).*\1/
(or whatever the equivalent is in your regex library's syntax)
Not the most efficient, since it will probably backtrack to every character in the string and then scan forward again. And I don't usually advocate regular expressions. But if you want brevity...
I started looking for some info on the net and I got to the following solution.
string input = "aaaaabbcbbbcccddefgg";
char[] chars = input.ToCharArray();
Dictionary<char, int> dictionary = new Dictionary<char,int>();
foreach (char c in chars)
{
if (!dictionary.ContainsKey(c))
{
dictionary[c] = 1; //
}
else
{
dictionary[c]++;
}
}
foreach (KeyValuePair<char, int> combo in dictionary)
{
if (combo.Value > 1) //If the vale of the key is greater than 1 it means the letter is repeated
{
Console.WriteLine("Letter " + combo.Key + " " + "is repeated " + combo.Value.ToString() + " times");
}
}
I hope it helps, I had a job interview in which the interviewer asked me to solve this and I understand it is a common question.
When there is no order to work on you could use a dictionary to keep the counts:
String input = "AABCD";
var result = new Dictionary<Char, int>(26);
var chars = input.ToCharArray();
foreach (var c in chars)
{
if (!result.ContainsKey(c))
{
result[c] = 0; // initialize the counter in the result
}
result[c]++;
}
foreach (var charCombo in result)
{
Console.WriteLine("{0}: {1}",charCombo.Key, charCombo.Value);
}
The hash solution Jon was describing is probably the best. You could use a HybridDictionary since that works well with small and large data sets. Where the letter is the key and the value is the frequency. (Update the frequency every time the add fails or the HybridDictionary returns true for .Contains(key))