I am coding an application that asks a user to enter a word, and then the program checks if there are any words contained within the larger word that are in the dictionary. For example, if the user entered "starburst", the system would output "star" and "burst".
I am creating my own dictionary of words within the program. So far I have an array, and I simply go one by one and add different words to the dictionary. Is there a more efficient way of doing this?
code posted below:
static void Main(string[] args) {
Console.WriteLine("Enter a word");
string word = Console.ReadLine();
string word2 = word;
string [] dictionary = new string[300];
dictionary[0] = "apple";
dictionary[1] = "adversary";
dictionary[2] = "apply";
dictionary[3] = "be";
dictionary[4] = "bear";
dictionary[5] = "Bare";
dictionary[6] = "car";
dictionary[7] = "care";
dictionary[8] = "cat";
dictionary[9] = "carreer";
dictionary[10] = "day";
dictionary[11] = "dare";
dictionary[12] = "date";
dictionary[13] = "do";
dictionary[14] = "double";
dictionary[15] = "ex";
dictionary[16] = "extra";
dictionary[17] = "can";
dictionary[18] = "dog";
dictionary[19] = "dont";
for (int i = 0; i < word.Length; i++)
{
for (int n = word2.Length; n < dictionary.Length; n++)
{
if (word == dictionary[n] && word != word2)
{
Console.WriteLine(word);
}
if(word2 == dictionary[n] && word != word2)
{
Console.WriteLine(word2);
}
word.Substring(1, word.Length - 1);
word2.Substring(0, word2.Length - 2);
}
}
}
Is there a more efficient way of doing this?
I assume you mean not having to manually change the array initialization code and recompile the application when you want to add a word to the dictionary.
You could do this by putting your word list in a file, and reading it with string [] dictionary = File.ReadAllLines("dictionary.txt").
Related
I am trying to compare two string in C# and get the differences between them i.e words which are not present in the other string ignoring cases and commas just focusing on the words. If one string contains two or multiple the and the second string has one the, it means this will be disregarded as it exists in both. Example I have two strings like below;
Cat meet's a dog
Cat meet's a dog and a bird
The difference between those two strings is and bird because it does not exist in the first one or vise versa and I want to get those two words and bird either in a List or a new string with spaces between them and in other words I want the words which are not present in the other string. Is there a way this can be done in C#?
Here's a way using LINQ. You don't need the "ToList()" part, but you mentioned that as one form of output you'd want:
string str1 = "Cat meet's a dog";
string str2 = "Cat meet's a dog and a bird";
string[] str1Words = str1.ToLower().Split(' ');
string[] str2Words = str2.ToLower().Split(' ');
var uniqueWords = str2Words.Except(str1Words).Concat(str1Words.Except(str2Words)).ToList();
// Do whatever you want with uniqueWords instead
Console.WriteLine($"output: {String.Join(" ", uniqueWords)}");
#ngdeveloper. This is my variant of your solution (had to post it in a separate answer because of the length):
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int shortestLenght;
int longestLenght;
bool firstIsLongest;
if (_firstStringArray.Length > _secondStringArray.Length)
{
firstIsLongest = true;
shortestLenght = _secondStringArray.Length;
longestLenght = _firstStringArray.Length;
}
else
{
firstIsLongest = false;
shortestLenght = _firstStringArray.Length;
longestLenght = _secondStringArray.Length;
}
for (int i = 0; i < shortestLenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = shortestLenght; i < longestLenght; i++)
{
if (firstIsLongest)
_stringsDiff._diffList1.Add(_firstStringArray[i]);
else
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
return _stringsDiff;
}
I wrote you a simple solution, hope it will help -
The main method is called 'Difference' it receive 2 strings to compare and return an object called StringDiff.
It runs 2 loops, first comparing between the two strings char by char and then adding the rest of the longer string.
The 'StringDiff' object is a class with 2 char lists that represnt the differences of each string.
In the main method i use String.join to convert the char lists to a string and print it.
internal class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("enter first string");
string firstString = Console.ReadLine();
Console.WriteLine("enter second string");
string secondString = Console.ReadLine();
StringsDiff _stringsDiff = Difference(firstString, secondString);
Console.WriteLine(
$"fist string difference: {string.Join("", _stringsDiff._diffList1)} / second string difference: {string.Join("", _stringsDiff._diffList2)}");
Console.WriteLine("/////////////////////////////////////");
}
}
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int lenght;
if (_firstStringArray.Length > _secondStringArray.Length)
{
lenght = _secondStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _secondStringArray.Length; i < _firstStringArray.Length; i++)
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
}
}
else
{
lenght = _firstStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _firstStringArray.Length; i < _secondStringArray.Length; i++)
{
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
return _stringsDiff;
}
class StringsDiff
{
public List<char> _diffList1 = new List<char>();
public List<char> _diffList2 = new List<char>();
}
}
Remember to use "string.join" to connect the lists objects if you need a string.
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 =
Trying to make hangman (i'm still a newbie) and the program chooses a random word out of a textfile ==> word turned into arrays. And i have to put it in a label while having the textlabel modified to what's in the letterlist. Thing is: it doesn't show anything in the label and i can't seem to figure out why.
So the for-loop is the modifier and when it has modified every string in the list it should return the word with the right letter or "_".
At first i tried is by doing: letterlist[i] = Letter or letterlist[i] = "_", but would happen is if i typed in a right letter it would show only that letter.
For example: word = "pen". If i typed in "p", it resulted in "ppp".
letterlist = new List<string>();
char[] wordarray = woord.GetWordcharArray(); //word in charArrays
string newwordstring = new string(wordarray);
for (int i = 0; i < wordarray.Length; i++)
{
letterlist.Add(" "); //adds empty strings in list with the length of the word
}
/*
* For-loop for every string in List to check and modify if it's correct or not
*/
for (int i = 0; i < letterlist.Count; i++)
{
if (letterlist[i].Contains(Letter) && newwordstring.Contains(Letter)) //right answer: letter[i] = Letter
{
letterlist[i].Replace(Letter, Letter);
}
else if (letterlist[i].Contains(" ") && newwordstring.Contains(Letter)) //right answer: letter[i] = ""
{
letterlist[i].Replace(" ", Letter);
}
else if (letterlist[i].Contains("_") && newwordstring.Contains(Letter)) //right answer: letter[i] = "_"
{
letterlist[i].Replace("_", Letter);
}
else if (letterlist[i].Contains(" ") && !newwordstring.Contains(Letter)) //wrong answer: letter[i] = ""
{
letterlist[i].Replace(" ", "_");
}
else if (letterlist[i].Contains("_") && !newwordstring.Contains(Letter)) //wrong answer: letter[i] = "_"
{
letterlist[i].Replace(" ", "_");
}
}
/*
* empty += every modified letterlist[i]-string
*/
string empty = "";
foreach (string letter in letterlist)
{
empty += letter;
}
return empty;
New code but it only shows "___" ("_" as many times as the amount of letters as word has):
char[] wordarray = woord.GetWordcharArray(); //word in charArrays
string newwordstring = new string(wordarray); //actual word
string GuessedWord = new string('_', newwordstring.Length);//word that shows in form
bool GuessLetter(char letterguess)
{
bool guessedright = false;
StringBuilder builder = new StringBuilder(GuessedWord);
for(int i = 0; i < GuessedWord.Length; i++)
{
if(char.ToLower(wordarray[i]) == Convert.ToChar(Letter))
{
builder[i] = wordarray[i];
guessedright = true;
}
}
GuessedWord = builder.ToString();
return guessedright;
}
return GuessedWord;
First of all, note that C# string are immutable, which means letterlist[i].Replace(" ", "_") does not replace spaces with underscores. It returns a new string in which spaces have been replaced with underscores.
Therefore, you should reassign this result:
letterlist[i] = letterlist[i].Replace(" ", "_");
Second, Replace(Letter, Letter) won't do much.
Third, in your first for loop, you set every item in letterlist to " ".
I don't understand then why you expect (in your second for loop) letterlist[i].Contains("_") to ever be true.
Finally, I'll leave here something you might find interesting (especially the use of StringBuilder):
class Hangman
{
static void Main()
{
Hangman item = new Hangman();
item.Init();
Console.WriteLine(item.Guessed); // ____
item.GuessLetter('t'); // true
Console.WriteLine(item.Guessed); // T__t
item.GuessLetter('a'); // false
Console.WriteLine(item.Guessed); // T__t
item.GuessLetter('e'); // true
Console.WriteLine(item.Guessed); // Te_t
}
string Word {get;set;}
string Guessed {get;set;}
void Init()
{
Word = "Test";
Guessed = new string('_',Word.Length);
}
bool GuessLetter(char letter)
{
bool guessed = false;
// use a stringbuilder so you can change any character
var sb = new StringBuilder(Guessed);
// for each character of Word, we check if it is the one we claimed
for(int i=0; i<Word.Length; i++)
{
// Let's put both characters to lower case so we can compare them right
if(Char.ToLower(Word[i]) == Char.ToLower(letter)) // have we found it?
{
// Yeah! So we put it in the stringbuilder at the same place
sb[i] = Word[i];
guessed = true;
}
}
// reassign the stringbuilder's representation to Guessed
Guessed = sb.ToString();
// tell if you guessed right
return guessed;
}
}
I'm trying to create a word guessing game that uses a dictionary text file. The game is supposed to take input from the user on how long the word should be before asking them to guess the word. If the user fails to guess after 3 times then it reveals the answer. I used a list on recommendation from a friend to read from the dictionary as it is quite large.
My question is, how can I read the list to choose a word for the guessing game?
{
static int letterLength, LettersLeft, wrongGuess;
public static void Main(string[] args)
{
string input = System.IO.File.ReadAllText("dictionary.txt");
string[] terms = input.Split();
List<string> list = new List<string>();
for (int num = 0; num < terms.Length; num++)
list.Add(terms[num]);
int wordToGuess = GetLengthOfWordToGuess();
List<string> fixedlist = new List<string>();
for (int num = 0; num < list.Count; num++)
{
string tempword = list[num];
if (tempword.Length == wordToGuess)
fixedlist.Add(tempword);
}
for (int num = 0; num < fixedlist.Count; num++)
Console.WriteLine(fixedlist[num]);
Console.WriteLine("Welcome to the guessing game");
letterLength = GetLengthOfWordToGuess();
Console.Clear();
//Not Working from here on.
string wordGuess = GetWordToGuess();
char[] maskedWord = GetHiddenLetters(wordGuess, '-');
LettersLeft = wordGuess.Length;
char userGuess;
wrongGuess = 3;
while (wrongGuess > 0 && LettersLeft > 0)
{
DispayCharacters(maskedWord);
Console.WriteLine("Enter a Letter");
userGuess = char.Parse(Console.ReadLine());
maskedWord = CheckGuess(userGuess, wordGuess, maskedWord);
}
Console.WriteLine("Well done! Thanks for Playing.");
Console.ReadLine();
}
static string GetWordToGuess()
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
static char [] GetHiddenLetters(string word, char mask)
{
char[] hidden = new char[word.Length];
for (int i = 0; i < word.Length; i++)
{
hidden[i] = mask;
}
return hidden;
}
static void DispayCharacters(char [] characters)
{
foreach(char letter in characters)
{
Console.Write(letter);
Console.WriteLine();
}
}
static int GetLengthOfWordToGuess()
{
Console.WriteLine("Input length of word to guess");
int selectWord = int.Parse(Console.ReadLine());
return selectWord;
}
static char [] CheckGuess (char letterToCheck, string word, char [] characters)
{
bool wrong = true;
if(wrongGuess > 0)
{
for (int i = 0; i < word.Length; i++)
{
if (word[i] == letterToCheck)
{
characters[i] = word[i];
LettersLeft--;
wrong = false;
}
}
}
}
}
One major problem I see up front is that your GetWordToGuess function is not functional and probably throws an IndexOutOfRangeException.
The reason for that is that you are instantiating the words array as an array with a single empty string in it, but you are then referencing an index between 0 and 9, which will not exist in that array unless the random number generated is 0.
To solve this you should pass the fixedlist List you already created and use that instead of the words array. You should make sure to generate a random number between 0 and fixedlist.Count-1 so that you don't hit that same out of range exception. Therefore that function should look something like this:
static string GetWordToGuess(List<string> fixedlist)
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
Also, as it stands right now, your included code doesn't compile because the CheckGuess function doesn't return a char[] as it says it should. I believe what you meant to do was have a return characters; line at the end (this was probably just a copy paste issue when you put your code in your question, but I thought I'd mention it just in case).
As a side note there are a number of small issues with your code like declaring things you don't use, but since they don't break your program I didn't want to go through and fix them.
I have a problem with C#.
I am writing code to search a text file until it finds a certain word, then the code should move three lines and read the fourth, then continue the search to find the certain word again.
Now I don't know how to navigate through the file (forward and backward) to the line I want.
Can anybody help?
You can do something like this:
var text = File.ReadAllLines("path"); //read all lines into an array
var foundFirstTime = false;
for (int i = 0; i < text.Length; i++)
{
//Find the word the first time
if(!foundFirstTime && text[i].Contains("word"))
{
//Skip 3 lines - and continue
i = Math.Min(i+3, text.Length-1);
foundFirstTime = true;
}
if(foundFirstTime && text[i].Contains("word"))
{
//Do whatever!
}
}
// read file
List<string> query = (from lines in File.ReadLines(this.Location.FullName, System.Text.Encoding.UTF8)
select lines).ToList<string>();
for (int i = 0; i < query.Count; i++)
{
if (query[i].Contains("TextYouWant"))
{
i = i + 3;
}
}
Your requirements state that you are searching for a specific word. If that is true and you are not instead looking for a specific string, then the checked answer on this is wrong. Instead you should use:
string[] lines = System.IO.File.ReadAllLines("File.txt");
int skip = 3;
string word = "foo";
string pattern = string.Format("\\b{0}\\b", word);
for (int i = 0; i < lines.Count(); i++)
{
var match = System.Text.RegularExpressions.Regex.IsMatch(lines[i], pattern);
System.Diagnostics.Debug.Print(string.Format("Line {0}: {1}", Array.IndexOf(lines, lines[i], i) + 1, match));
if (match) i += skip;
}
If you use the string.contains method and the word you are searching for is "man", while your text somewhere contains "mantle" and "manual", the string.contains method will return as true.