My code is currently busted and I am aware of this. I'm working one one part at a time and I have hit two stumbling blocks which I'm hoping to find help here in regards too.
I am trying to address my formatting issue with this question here.
With the code below, i read in a text file using StreamReader, and the selections come in all on the same line as I want them too seperated by a BAR ("|"). Unfortunately, the bar prints at the end of each word, not actually 'between' each word. I don't want the last bar to print. I know i could cheat and add a bar to the font with a Console.Write("|") but that would be cheating in my mind - i wouldn't really be printing/displaying a bar between the words as I was trying to make a more elegant console selection.
This is just something I'm doing to learn and is not part of our assignment, but i like to push myself when I can. I am very very new to attempting to code, I am a complete newb, please assume I know nothing and please know all help is very much appreciated.
THIS IS MY CODE THUS FAR:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;// Needed for Streaming...
using System.IO;// Needed for Streaming...
namespace a090___StreamReader_DictionarySearch
{
class Program
{
private const String FILE_NAME = "dictionary.txt";//establish text file instance
public void Play()
{
do
{
DisplayTitle();
List<Listing> items = LoadListings();//create a list of WordDef objects
int count = 0;
foreach (Listing myListing in items)//read in items from file
{
//Console.WriteLine(myListing.GetName() + ": " + myListing.GetDefinition());
Console.Write(myListing.GetName());
if (count != items.Count - 1)
{
Console.Write(" | ");
}
count++;
}
DisplayText("\n\nPlease enter a word from the selections about to see it's definition");// Nice use of PROMPT
String userSelection = Console.ReadLine().ToLower();//Capture input
/// What are we trying to do?
/// Collect value entered for comparison - chek!
///
/// Compare value entered against list (Does value match to name?)
/// IF value matches print description
/// if value does not match(Else), state no match
//if (userSelection == Listing.name)
//{Console.WriteLine("You selected: " + userSelection() +
// "\nWhich Means: " + Listing.GetDefinition());}
//else{Console.WriteLine("I'm sorry, I don't have a match for that.");}
} while (PlayAgain());
Salutation();
}
//ToolBox -- my program specific tools
public List<Listing> LoadListings()//load entries display as list
{
StreamReader fileIn = new StreamReader(FILE_NAME);
List<Listing> entry = new List<Listing>();
//loop through every line of the file
while (!fileIn.EndOfStream)
{
String line = fileIn.ReadLine();
String[] pieces = line.Split(':');
if (pieces.Length < 1) continue;//error handling - set to length of text items
Listing myListing = new Listing(pieces[0], pieces[1]);
entry.Add(myListing);
}
fileIn.Close(); return entry;
}
//MaxBox -- my useful tools
public void DisplayText(String StringNameIs)
{ Console.WriteLine(StringNameIs); }//Where are we?
public Boolean PlayAgain()
{
Console.Write("\n\nDo you select again? (y)es or (n)o: ");
String command = Console.ReadLine().ToLower();
if (command == "y" || command == "yes") return true;
return false;
}
public void Salutation()
{ Console.Clear(); Console.WriteLine("Ti Do - oh - oh Ti Do -- So Do!"); } //The last line from the 'do-re-mi' song from the Sound of Music
public void DisplayTitle()
{ Console.Clear(); Console.WriteLine(">>>-- A Dictionary of Sounds --<<< \n"); } //Announce Our Program
static void Main(string[] args)
{
Program DictionaryLookup = new Program();
DictionaryLookup.Play();
Console.Read();
}
}
}
Please note: I have searched StackOverflow, GOOGLE, BING, MS' resources, et al. for an answer i can understand with my limited skills/understanding. I've also been working on this for a few hours. Please help.
You're looking for string.Join. Replace the whole foreach loop
foreach (Listing myListing in items)//read in items from file
{
//Console.WriteLine(myListing.GetName() + ": " + myListing.GetDefinition());
Console.Write(myListing.GetName() + " | ");
}
with
Console.Write(string.Join(" | ", items.Select(x => x.GetName())));
Alternatively, you could try a writing a backspace to the console.
Edit: As noted in the comments, you'd need to print a space char over the last pipe.
Console.Write("\b \b");
You may convert List of objects to array of object property and cast it to a string with delimeter:
string str = String.Join(" | ", items.Select(x => x.GetName()).ToArray());
try something like this...
var items = LoadListings();//create a list of WordDef objects
int i = 1;
var sw = new StringBuilder();
foreach(var myListing in items)
{
sw.AppendFormat("{0}", myListing.GetName() + "|");
if (i=items.Count)
{
sw.Replace("|", "", i,i);
}else
{ i++; }
}
//Console.WriteLine(myListing.GetName() + ": " + myListing.GetDefinition());
Console.Write(sw);
List<Listing> items = LoadListings(); //create a list of WordDef objects
int checklast = 0;
foreach (Listing myListing in items) //read in items from file
{
if (checklast == items.Count-1)
{
Console.Write(myListing.GetName());
}
else
{
//Console.WriteLine(myListing.GetName() + ": " + myListing.GetDefinition());
Console.Write(myListing.GetName() + " | ");
}
++checklast;
}
You can use the lazy method by checking when the last item will come so you make sure won't add BAR at the end.
Related
I'd like to create a short program to download several pictures from a website.
On a form, I would like to enter a root-link to a website with placeholders.
The placeholders can be defined with Start/End value and asc/desc.
For example: the original link is
google.de/1236-01.jpg
and I'd like to generate all links from
google.de/1236-1.jpg
up to
google.de/9955-12.jpg
So my input would be "google.de/[0]-[1].jpg" and placeholders are set to:
[0] = start 1236|end 9955|asc
[1] = start 1|end 12|asc
Via GetValidCharacters() I get a String-List of valid combinations for each entered placeholder (can be selected via ascending/descending + start&end).
The goal I'm struggling with is to build all combinations of this link, because I need to determine while runtime, how much placeholders I have.
My idea was to loop over an queue and enquueue each new build line, until there is none left with placeholders, but I don't know how to do this.
I need to make sure that all combinations are entered and they are entered only once.
private static void CreateDownloadList()
{
Queue<string> tmpQueue = new Queue<string>(); //temp queue
tmpQueue.Enqueue(DL_path); //DL_Path = google.de/[0]-[1].jpg
string line = "";
while ((line = tmpQueue.Dequeue()) != null) //not empty
{
if (line.Contains("[")) //placeholder
{
string tmpLine = line;
//how to determine, which placeholder is next?? need to know this and replace this with every combination, I get from GetValidCharacters(start, end, DESC)
}
else //done
{
_urlList.Add(line);
}
}
}
how about a simple for loop?
for (int i = 1236; i <= 9955; i++)
{
for (int j = 1; j <= 12; j++)
{
tmpQueue.Enqueue(string.Format("google.de/{0}-{1}.jpg", i, j));
}
}
I'm not going give you the full code but here is some pseudo code that would solve the problem.
given :
todostack -- stack object that holds a list of unresolved items
replace_map -- map object that holds marker string and map of all values
marker_list -- list of all markers
final_list -- list object that holds the results
(note you can probably use marker_list and replace_map in one object -- I have them separate to make my code clearer)
init :
push todostack with your starting string
set marker_list and replace_map to correct values (from parameters I assume)
clear final_list
algorithm :
while (there are any items in todostack)
{
curitem = todostack.pop
if (curitem contains a marker in marker_list)
{
loop for each replacement in replace_map
{
new_item = curitem replaced with replacement
todostack.push(new_item)
}
}
else
add curitem to final_list
}
#Hogan this was the hint to the correct way.
solution is this
private void CreateDownloadList()
{
Queue<string> tmpQueue = new Queue<string>();
tmpQueue.Enqueue(downloadPathWithPlaceHolders);
while(tmpQueue.Count > 0)
{
string currentItem = tmpQueue.Dequeue();
bool test = false;
if(currentItem.Contains("["))
{
foreach(Placeholder p in _placeholders)
{
if(currentItem.Contains(p.PlaceHolder))
{
foreach(string s in p.Replacements)
{
tmpQueue.Enqueue(currentItem.Replace(p.PlaceHolder, s));
}
test = true;
}
if(test)
break;
}
}
else
{
_downloadLinkList.Add(currentItem);
}
}
}
Is there an algorith or C# library to determine if a human name is correct or not and, if not, to find its nearest matching?
I found algorithms for string matching like the Levenshtein's distance algorithm, but all of them check the matching between one string and another, and i want to check the matching between one name and all the possible names in English (for example), to check if the name was wrongly written.
For example:
Someone inserts the name "Giliam" while it should be "william". I want to know if there are any algorithm (or group of them) to detect the error and propose a correction.
All solutions that come to my mind involves the implementation of a huge human name's dictionary and use it to check for the correctness of each input name matching one by one... And it sounds terrorific performace to me, so i want to ask for a better approach.
Thanks.
What you are in effect asking is how to create a spell checker with a given dictionary. One way to do this that doesn't involve looking up and testing every possible entry in a list is to do the inverse of the problem: Generate a list of possible permutations from the user input, and test each one of those to see if they're in a list. This is a much more manageable problem.
For instance, you could use a function like this to generate each possible permutation that one "edit" could get from a given word:
static HashSet<string> GenerateEdits(string word)
{
// Normalize the case
word = word.ToLower();
var splits = new List<Tuple<string, string>>();
for (int i = 0; i < word.Length; i++)
{
splits.Add(new Tuple<string, string>(word.Substring(0, i), word.Substring(i)));
}
var ret = new HashSet<string>();
// All cases of one character removed
foreach (var cur in splits)
{
if (cur.Item2.Length > 0)
{
ret.Add(cur.Item1 + cur.Item2.Substring(1));
}
}
// All transposed possibilities
foreach (var cur in splits)
{
if (cur.Item2.Length > 1)
{
ret.Add(cur.Item1 + cur.Item2[1] + cur.Item2[0] + cur.Item2.Substring(2));
}
}
var letters = "abcdefghijklmnopqrstuvwxyz";
// All replaced characters
foreach (var cur in splits)
{
if (cur.Item2.Length > 0)
{
foreach (var letter in letters)
{
ret.Add(cur.Item1 + letter + cur.Item2.Substring(1));
}
}
}
// All inserted characters
foreach (var cur in splits)
{
foreach (var letter in letters)
{
ret.Add(cur.Item1 + letter + cur.Item2);
}
}
return ret;
}
And then exercise the code to see if a given user input can be easily convoluted to one of these entries. Finding the best match can be done by weighted averages, or simply by presenting the list of possibilities to the user:
// Example file from:
// https://raw.githubusercontent.com/smashew/NameDatabases/master/NamesDatabases/first%20names/all.txt
string source = #"all.txt";
var names = new HashSet<string>();
using (var sr = new StreamReader(source))
{
string line;
while ((line = sr.ReadLine()) != null)
{
names.Add(line.ToLower());
}
}
var userEntry = "Giliam";
var found = false;
if (names.Contains(userEntry.ToLower()))
{
Console.WriteLine("The entered value of " + userEntry + " looks good");
found = true;
}
if (!found)
{
// Try edits one edit away from the user entry
foreach (var test in GenerateEdits(userEntry))
{
if (names.Contains(test))
{
Console.WriteLine(test + " is a possibility for " + userEntry);
found = true;
}
}
}
if (!found)
{
// Try edits two edits away from the user entry
foreach (var test in GenerateEdits(userEntry))
{
foreach (var test2 in GenerateEdits(test))
{
if (names.Contains(test))
{
Console.WriteLine(test + " is a possibility for " + userEntry);
found = true;
}
}
}
}
kiliam is a possibility for Giliam
liliam is a possibility for Giliam
viliam is a possibility for Giliam
wiliam is a possibility for Giliam
Of course, since you're talking about human names, you had, at best, make this a suggestion, and be very prepared for odd spellings, and spellings of things you've never seen. And if you want to support other languages, the implementation of GenerateEdits gets more complex as you consider what counts for a 'typo'
I have an object class "Character" with a hashtable inside of it for weapons. I'm just trying to print the weapon to the console when I print the character stats for approval, but having a hard time figuring out a simple way to do this.
Advs is the Character object array, if there's any information I forgot to include please let me know, first time posting. The i.weapons.value is what I'm trying to fix, everything else prints to console correctly, that gives me strange values that look like pointers to the hashtable on print.
private static void ChStats(Character[] Advs) {
foreach (Character i in Advs) {
Console.WriteLine("Name: {0}\nClass: {1}\nLevel: {2}\nHealth: {3}\nStrength: {4}\nIntellect: {5}\nAgility: {6}\nSanity: {7}\nWeapon: {8}\n",
i.name, i.characterClass, i.lvl, i.hlth, i.str, i.itl, i.agi, i.san, i.weapons.value);
}
as an addition, the hash table contains two values for each weapon wNme and dmg. The code below works, but seem so sloppy, hopefully there's a better way to accomplish this.
foreach (Character i in Advs) {
string[] weaponDesc = new string[10];
int n = 0;
foreach (Weapon w in i.weapons.Values)
{
weaponDesc[n++] = w.wNme;
}
// this version works but with extra commas
//Console.WriteLine("Name: {0}\nClass: {1}\nLevel: {2}\nHealth: {3}\nStrength: {4}\nIntellect: {5}\nAgility: {6}\nSanity: {7}\nWeapon: {8}\n",
// i.name, i.characterClass, i.lvl, i.hlth, i.str, i.itl, i.agi, i.san, string.Join(", ", weaponDesc));
// better but more complex
Console.WriteLine("Name: {0}\nClass: {1}\nLevel: {2}\nHealth: {3}\nStrength: {4}\nIntellect: {5}\nAgility: {6}\nSanity: {7}\nWeapon: {8}\n",
i.name, i.characterClass, i.lvl, i.hlth, i.str, i.itl, i.agi, i.san, string.Join(", ", weaponDesc.Where(s => !string.IsNullOrEmpty(s))));
Generics typed HashSet class is a better choice.
HashSet<Weapon> Weapons;
Weapons = new HashSet<Weapon>();
Weapons.Add(new Weapon()); // Assume this is created and populated elsewhere
StringBuilder SBText = new StringBuilder(64 + (Weapons.Count * 8)); // An approximation of the eventual string length
SBText.Append(#"Class, Level, etc...");
// Cryptic but compact Lync method (Not my favourite)
Weapons.Where(Wpn => !string.IsNullOrEmpty(Wpn.name)).ToList().ForEach(delegate (Weapon Wpn) { if (SBText.Length > 0) { SBText.Append(#", "); } SBText.Append(Wpn.name); });
// Explicit code method
foreach (Weapon Wpn in Weapons)
{
if (!string.IsNullOrEmpty(Wpn.name))
{
if (SBText.Length > 0) { SBText.Append(#", "); }
SBText.Append(Wpn.name);
}
}
Console.WriteLine(SBText.ToString());
I'm very new to working with C#. I am trying to save data (text such as a persons name) which is entered into the console and then 'read' to an array.
The name of the array i want to save data to is: name2convert
The variable collecting the data (name to be converted) is: nameEntered
Any help is very much appreciated. I've been working on this for a few hours and have done several searches, but i have not found any answers which I could understand with my limited understanding of C# at this time. I've only been trying to learn this for a few weeks - i'm very very green. Any help is appreciated.
Note: String names was my test array so that i could see that i knew how to read data back from an array.
I want to save the data to the names2Convert array.
This is my code:
using System;
namespace a061___String_Manipulations___PigLatin
{
///loop - ask for number of names equal to number asked
/// read line, save to array, iterate one up until num equals value asked for
class Program
{
//Arrays
String[] names = { "test01", "test02", "test03", "test04", "test05" }; //Test loop
String[] name2convert = new String[1];
//Variables & Ints?
string title = ">>>-- Welcome to the Highly Enlightening World of Igp-ay Atinl-ay --<<< \n";
string totalIs = "You said you want to convert a total of";
string listCommands = "Is that correct? If so type (Y)es, (R)enter or (Q)uit";// general commands used
string addSuffix ="-ah!"; // Add to end of each name
string nameEntered = "";//name to be converted
int namesTotal = 0;//
//Main Method
public void Play()
{
Console.WriteLine(title); //announce program
askTotal(); //ask number of names
while (true)
{
Console.WriteLine(listCommands);//lists options
String command = Console.ReadLine().ToLower();//reads user command
if (command == "y") // if askTotal true save to array? how?
{
askName();//collects name entered
confirmName();//allows user to confirm spelling, etc.
//y save the array nameEntered name2convert
//name2convert.Add(nameEntered);
name2convert[0] = nameEntered;
//confirm name
for (int i = 0; i < name2convert.Length; i++)
{
Console.WriteLine("Name Aquired: " + name2convert[i]);
}
}
else if (command == "r")
{
askName();//asks name
}
else if (command == "q")
{
Console.WriteLine("Cheers!"); break; //end
}
else
{
Console.WriteLine("Sorry. Invalid Request");//try again
}
PrintList();//test array
}
}
//Helper Methods
public void PrintList()//iterates through, prints names stored in array
{
Console.WriteLine("Print List");
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine((i + 1) + ". " + names[i] + addSuffix);
}
}
//iterates through, prints names stored in array
public void askName()
{
Console.WriteLine("Enter Name: ");//Confirming
String nameEntered = Console.ReadLine().ToLower();// Capture name
Console.WriteLine("Name Captured: " + nameEntered);//confirming name caught
}
//iterates through, prints names stored in array
public void confirmName()
{
Console.WriteLine(listCommands);//Confirming
String command = Console.ReadLine().ToLower();
}
//how many names to convert
public void askTotal()
{
Console.WriteLine("How many names would you like to convert?");//Ask for content
namesTotal = int.Parse(Console.ReadLine());
Console.WriteLine(totalIs + " " + namesTotal);//Confirming
}
//Call Application
static void Main(string[] args)
{
Program StringManipulations = new Program();
StringManipulations.Play(); //Call forth the Pig Latin...
Console.Read();//
}
}
}
Change this:
//y save the array nameEntered name2convert
name2convert.Add(nameEntered);
To this:
name2convert[0] = nameEntered;
EDIT:
In askName() function change:
String nameEntered = Console.ReadLine().ToLower();// Capture name
To:
nameEntered = Console.ReadLine().ToLower();// Capture name
You already have nameEntered of type string declared as property of your class.
And why are you using string and then String? it's the same, as string is alias of String (which is in fact System.String in C#) - but be consistent!
As you already allocated the memory for this array (it's fixed size - in your case it's one).
So to access the first (and only) cell in your array, you should use name2convert[0] - 0 is the first index at any array and usually at any other struct/container in C# (and many other programming languages).
Another approach (as you were trying in your example) is to user List<String> instead.
For more information on arrays and Lists refer to here:
Array tutorial
List tutorial and examples
If you want save EVERY WORD that the user inputs use an List of Strings e.g
List<String> name2convert;
then
name2convert.Add(nameEntered);
to go through the list
foreach (String word in name2convert)
{
Console.WriteLine(word);
}
How can I assign values to a group of variables using recursion in C#?
I can easily do it with a simple procedure, but I have no idea how to do it using recursion.
public void Assign()
{
Console.Write("Name: ");
Name = Console.ReadLine();
Console.Write("e-mail: ");
Email = Console.ReadLine();
Console.Write("Phone Number: ");
Phone = int.Parse(Console.ReadLine());
}
Thanks for the help.
If you're going to use recursion, you've got to have some sort of local context that's sufficient to accomplish whatever work you're going to do in your function, and you've got to know when / where to stop (and start popping your stack).
Your example looks like (if anything at all) a loop.
Your problem seems like homework because textbooks usually use this kind of horrible questions to teach recursion.
namespace Homework
{
class Recursion
{
static string[] nameList = new string[5];
static void Main(string[] args)
{
AssignNames(0);
Console.WriteLine("The names are:");
foreach(string name in nameList)
{
Console.WriteLine(name);
}
Console.ReadKey();
}
static void AssignNames(int index)
{
if (index == nameList.Length) return;
Console.Write("Enter name #{0}: ", index + 1);
nameList[index] = Console.ReadLine();
AssignNames(index + 1);
}
}
}