I am looking for a way to figure out if textboxes are filled in in a specific way.
I have the following textboxes:
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
Users are expected to input into them continuously. For example, if only X1,Y1 have texts, it's valid. While if X1,Z1 have texts while Y1 hasn't, it's invalid.
The reason for this is because:
string G1
if(!string.IsNullOrWhiteSpace(X1.Text) && string.IsNullOrWhiteSpace(Y1.Text))
{
G1 = "<" + X1.Text + ">";
}
else if(!string.IsNullOrWhiteSpace(X1.Text) && !string.IsNullOrWhiteSpace(Y1.Text))
{
G1 = "<" + X1.Text + ">, ";
}
If they skip around then what is printed in the end will not be what is expected.
If you can think of an easier way to do all of this, please share. I am sure that my way of attacking this problem is quite simplistic and inefficient.
The answer I found is to use an array of the text boxes, then to iterate over that to determine the text of the filled out boxes. Then add the text from those boxes to a list.
Finally I used joined all of the items of that list, in a way that made the final output correct.
Code I used in the end:
string[] cells = new string[] { X1.Text, Y1.Text, Z1.Text, X2.Text, Y2.Text, Z2.Text, X3.Text, Y3.Text, Z3.Text };
List<string> final_cells = new List<string>();
//Process array to determine which cells are full, adds full cells to list
for (int i = 0; i < cells.Length; i++)
{
if(cells[i].Length == 0)
{
//If cell is empty, continue to the next one
continue;
}
else
{
// If cell is full add its contents to the final_cells list
final_cells.Add(cells[i]);
}
}
//Join the list to one string
string content = string.Join(">, <", final_cells);
Also I am sorry that I did not better explain the original situation.
The purpose of the final application is to output text in a specific format for a minecraft plugin to read. The 3x3 of text boxes is meant to mimic the crafting grid from the game.
The type of recipe this part of the application is supposed to add does not need to use 9 items/blocks, and is not shaped (so it doesn't technically matter where the user inputs each item name). Because of this, the empty boxes have to be completely ignored, and the program needs to know if there is something coming next, so I could not simply say that the recipe ended at the first empty box.
An output of <item1> <item2> is not valid, the correct format is <item1>, <item2>. However the input can also be a single item... so this <only_item> is a valid format.
I hope it is clear both what the function of this is, but also why this was important for my application.
Related
I'm trying to get better at understanding recursion and I'm working on a program that is supposed to solve Sudoku puzzles by iterating over each cell in the puzzle and trying a value out of a list of possible values. After it drops in a value, it checks if doing so has solved the puzzle. If not, it continues on adding values and checking if doing so has solved the puzzle. There's a problem, though - I can see in my app's GUI that it eventually gets confused or stuck and starts attempting the same value insertion over and over. For example, here's an example of some logging that shows it being stuck:
Possible values: F
Old string: 086251B7D93+++C4
New string: 086251B7D93F++C4
As you can see, it's looking to see what value could possibly go into the cell after the 3 without violating the row, column, or box constraints. The only possible value is F, so it places it in there. But then it does the same thing over and over, and randomly starts attempting to edit other cells in other lines even though there are still +'s in this first row. It'll try to edit a row a few rows down, and it'll swap between doing that and then attempting this same scenario with the F repeatedly until the app crashes because of what Visual Studio thinks is a ContextSwitchDeadlock error.
What have I missed in my algorithm? Here is my method that tries to fill in the Sudoku puzzle:
public bool SolveGrid(List<Row> rows, List<Box> boxes)
{
textBox1.Clear()
foreach (var row in rows)
{
textBox1.AppendText(row.content + "\n");
}
if (ValidatorAgent.IsGridSolved(rows, boxes))
{
textBox2.AppendText("Success!");
successGrid = rows;
return true;
}
foreach (var row in rows)
{
foreach (var cell in row.content)
{
if (cell.Equals('+'))
{
var possibleValues = availableValues.Where(v => !ValidatorAgent.AreGridConstraintsBreached(cell, v, row, rows, boxes)).ToList();
if (!possibleValues.Any())
{
return false;
}
Console.WriteLine("Possible values: ");
possibleValues.ForEach(v => Console.Write(v.ToString()));
List<char> values = new List<char>();
possibleValues.ForEach(v => values.Add(v));
foreach (var possibleValue in values)
{
var oldContent = row.content;
var stringBuilder = new StringBuilder(row.content);
var indexToChange = row.content.IndexOf(cell);
stringBuilder[indexToChange] = possibleValue;
Console.WriteLine("Old string: " + oldContent);
Console.WriteLine("New string: " + stringBuilder.ToString());
var alteredPuzzle = BuilderAgent.BuildPuzzleCopy(rows);
alteredPuzzle.Single(r => r.yCoord == row.yCoord).content = stringBuilder.ToString();
var newBoxes = BuilderAgent.BuildBoxes(alteredPuzzle);
SolveGrid(alteredPuzzle, newBoxes);
}
}
}
}
return false;
}
I am pretty confident that my IsGridSolved method works correctly because I've tested it on puzzle solutions and found that it reported whether or not a puzzle was already solved. I've also tested my AreGridConstraintsBreached method with unit tests and also by eyeballing the results of the code, so I'm fairly confident in that code. It basically checks whether or not a cell's potential value is redundant due to the relevant row, column, or box already having that value. In Sudoku, when you place a value you need to make sure that the value 1) doesn't already exist in the row 2) doesn't already exist in the column and 3) doesn't already exist in the small box surrounding the cell. I feel like I'm missing something obvious in the algorithm itself, and that it isn't backtracking properly. I've tried fiddling with the SolveGrid method so that it takes in a list of validValues that are based off of the availableValues, with some pruning so that failed values are pruned out after each recursive call to SolveGrid but that didn't do anything besides keep the puzzle from even getting as far as it currently does. Any tips would be appreciated.
I am currently making a text based game. I am drawing a map using ASCII. I want to place an "#" sign in the room where the player is located. the four square boxes are the rooms. Here is the code:
string map = #"
+--------+
| |
|| ||
| |
+---||---+
||
+-||-+
|| ||
+-||-+
||
+-||-+
|| ||
+-||-+
||
+-||-+
|| ||
+- -+";
//this doesn't work lol
map = map.Replace("||","#");
It is for an assignment.
To answer your direct question, assuming that there is a part of your map string that has two spaces after two vertical bars and you want to replace the second space with an # symbol, you could do this:
map.Replace("|| ", "|| #");
Which of course would replace every instance of the search string, scattering # symbols throughout your map, and I strongly doubt that you want this to happen.
In fact I don't think it's a good idea to change the map string at all. Instead you would be better served by keeping the map data separate from the player position data and handling the output differently.
For example, if you are allowed to use the Console object's positioning commands you can do something like this:
int playerX;
int playerY;
string map;
public void Draw()
{
Console.Clear();
Console.Write(map);
// save cursor position
int l = Console.CursorLeft;
int t = Console.CursorTop;
// display player marker
Console.SetCursorPosition(playerX, playerY);
Console.Write("#");
// restore cursor position
Console.SetCursorPosition(l, t);
}
You can use cursor positioning to do all sorts of fun things, just like we used to in the good old days of ANSI art. Ah, nostalgia.
If you can't use - or for some reason can't rely on - cursor positioning you will need to get a bit more creative. One method is to break the map down into lines and figure out which one needs to have the player mark added right before you do the output:
public void Draw()
{
string[] lines = map.Replace("\r", "").Split('\n');
for(int y = 0; y < lines.Length; y++)
{
string curr = lines[y];
if (y == playerY)
curr = curr.Substring(0, playerX) + "#" + curr.Substring(playerX + 1);
Console.WriteLine(curr);
}
}
Of course this will blow up as soon as the player movement goes outside of the area covered by the map string, or hits the right-most character of the line.
Another option would be to create an array of map cells with information in each cell about what is there. The map string is used as input for generating the map array, which is used for all operations after that. The draw loop for that would then test against the player position to determine whether it will draw the player's marker or whatever character the map cell is represented by. You can also use this array for testing whether a move is valid (empty map cell), adding things like cell content (treasure!), etc.
The code for which is well outside the scope of this answer.
I have a method that checks if the current item exists in the database before it adds it to the database, if it does exist it deletes the item else it adds it.
Is there any better way of doing this?
Because right now the titles have to be exactly the same. If the titles have a char/word difference then it wont delete it.
Basically what I mean is this:
If title is "Ronaldo lost his right leg" and there is a title in the database that is "Ronaldo lost his right leg yesterday" it should delete current item.
Another example:
If title is "hello world" and there is a title in the database that is "hello world everyone" it should delete current item.
So basically if the text has common words it should delete the item.
Here is the method I have so far:
public void AddNews(News news)
{
var exists = db.News.Any(x => x.Title == news.Title);
if (exists == false)
{
db.News.AddObject(news);
}
else
{
db.News.DeleteObject(news);
}
}
Any kind of help is appreciated.
First, I agree with #Jonesy that the strings could be split into words using
string[] list1 = myStr.Split(null);
The null forces splitting on whitespace. See: Best way to specify whitespace in a String.Split operation
and those words can be put into lists. The intersection of the lists right away tells you which words match exactly, and how many words match exactly. Any other words are words that don't match.
var result = list1.Intersect(list2, StringComparer.InvariantCultureIgnoreCase);
So for the words that don't match, you can get a score for each word comparison using the Levenshtein distance. I included code below but haven't tested to see if this is a correctly working implementation. Anyway, the reason to use this is that you can compare each word by how many operations it takes to make one word match another. So misspelled words that are very close can be counted as equal.
However, as has been pointed out, the whole process is going to be very error prone. What it sounds like you really want to do is compare the MEANING of the two strings, and while we are making advances in that direction, I am not aware of any C# over the counter AI for parsing meaning from sentences yet.
using System;
/// <summary>
/// Contains approximate string matching
/// </summary>
static class LevenshteinDistance
{
/// <summary>
/// Compute the distance between two strings.
/// </summary>
public static int Compute(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// Step 1
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
// Step 2
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
// Step 3
for (int i = 1; i <= n; i++)
{
//Step 4
for (int j = 1; j <= m; j++)
{
// Step 5
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
// Step 6
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
// Step 7
return d[n, m];
}
}
Cited from here: http://www.dotnetperls.com/levenshtein
I don't know C#, but BASIC has instr$ and javascript has indexOf()... C# probably has something similar which will check if your string is present in the other string - which means it will show as a match for "hello" or "hello world" or "world hello" if you search "hello", but "hello world" won't find "world hello"... since I don't know C# this isn't valid code but should set you on the right track...
var dbTitle = wherever you get the existing titles from
var yourSearchTerm = what you want to find
if (dbTitle.indexOf(yourSearchTerm)>0) { //indexOf() returns -1 if match not found
db.News.AddObject(news);
}
else {
db.News.DeleteObject(news);
}
Search string manipulation in your help file to find the right command.
Your question raises more questions than it invites to provide a clear answer. May I ask why you'd ever want to delete an item in a method that's called AddItem? Don't you mean you want to update an item when it's identifier matches the one that's provided as an argument?
Having said that, there's basically two options to implement the desired behavior: perform the match in code, or perform the match in the database. However, both naturally require you two define exactly what it means two have a match. The other answers already hint to that.
The advantage of performing the match in code is flexibility: it's generally easier to pogram (complex) logic of this kind in C# that it is to write it in SQL. Plus you'll get the persistance-code for free since you can use EF (as I assume you're using looking at the code sample).
The advantage of doing it in SQL is that it's more performant, because you don't have to retrieve the entire entity from the database before you make the insert/update/delete decision. You can do this by adding an INSTEAD-OF INSERT trigger on the entity-table and perform an update/delete whenever you find the provided entity actually matches an existing one.
I have a method that checks if the current item exists in the database before it adds it to the database, if it does exist it deletes the item else it adds it.
Are you sure you want to delete (and re-add?) the item when found? You probably want to find a way to update the data instead. That will be much more efficient and less error prone. (For example, if you use delete, your record will be missing for everyone for a few miliseconds, and it will be gone forever if the client crashes at the wrong time.)
Also, you probably want to record all the things that the user types.
1) they are helpful for later mapping "what people searched for" to "what people really wanted". If one person typos, it's likely other people will typo that same way. (i.e. people rarely type "tqe" when typing "the". But they type "teh" all the time.)
2) you never know which one is the "best". More words isn't always better.
You're probably better off having a name table with "name, item_id" that allows multiple names to map to the same item in the items table that has the item attributes.
if the title just have a small char difference it wont delete it.
using ToUpper() on both ends will ensure a valid check, even if the casing is different
var exists = db.News.Any(x => x.Title.ToUpper() == news.Title.ToUpper());
if you want other ways to check if an object exists, we need more information.
Update
Going on your comment, you can strip all non-alphanumeric characters from it
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
var exists = db.News.Any(x => rgx.Replace(x.Title.ToUpper(), "") == rgx.Replace(news.Title.ToUpper(), ""));
and "Hello world" will match "Hello World!"
I am reading in multiple files in with millions of lines and I am creating a list of all line numbers that have a specific issue. For example if a specific field is left blank or contains an invalid value.
So my question is what would be the most efficient date type to keep track of a list of numbers that could be upwards of a million number of rows. Would using String Builder, Lists, or something else be more efficient?
My end goal is to out put a message like "Specific field is blank on 1-32, 40, 45, 47, 49-51, etc. So in the case of a String Builder, I would check the previous value and if it is is only 1 more I would change it from 1 to 1-2 and if it was more than one would separate it by a comma. With the List, I would just add each number to the list and then combine then once the file has been completely read. However in this case I could have multiple list containing millions of numbers.
Here is the current code I am using to combine a list of numbers using String Builder:
string currentLine = sbCurrentLineNumbers.ToString();
string currentLineSub;
StringBuilder subCurrentLine = new StringBuilder();
StringBuilder subCurrentLineSub = new StringBuilder();
int indexLastSpace = currentLine.LastIndexOf(' ');
int indexLastDash = currentLine.LastIndexOf('-');
int currentStringInt = 0;
if (sbCurrentLineNumbers.Length == 0)
{
sbCurrentLineNumbers.Append(lineCount);
}
else if (indexLastSpace == -1 && indexLastDash == -1)
{
currentStringInt = Convert.ToInt32(currentLine);
if (currentStringInt == lineCount - 1)
sbCurrentLineNumbers.Append("-" + lineCount);
else
{
sbCurrentLineNumbers.Append(", " + lineCount);
commaCounter++;
}
}
else if (indexLastSpace > indexLastDash)
{
currentLineSub = currentLine.Substring(indexLastSpace);
currentStringInt = Convert.ToInt32(currentLineSub);
if (currentStringInt == lineCount - 1)
sbCurrentLineNumbers.Append("-" + lineCount);
else
{
sbCurrentLineNumbers.Append(", " + lineCount);
commaCounter++;
}
}
else if (indexLastSpace < indexLastDash)
{
currentLineSub = currentLine.Substring(indexLastDash + 1);
currentStringInt = Convert.ToInt32(currentLineSub);
string charOld = currentLineSub;
string charNew = lineCount.ToString();
if (currentStringInt == lineCount - 1)
sbCurrentLineNumbers.Replace(charOld, charNew);
else
{
sbCurrentLineNumbers.Append(", " + lineCount);
commaCounter++;
}
}
My end goal is to out put a message like "Specific field is blank on 1-32, 40, 45, 47, 49-51
If that's the end goal, no point in going through an intermediary representation such as a List<int> - just go with a StringBuilder. You will save on memory and CPU that way.
StringBuilder serves your purpose so stick with that, if you ever need the line numbers you can easily change the code then.
Depends on how you can / want to break the code up.
Given you are reading it in line order, not sure you need a list at all.
Your current desired output implies that you can't output anything until the file is completely scanned. The size of the file suggests a one pass`analysis phase would be a good idea as well, given you are going to use buffered input as opposed to reading the entire thing into memory.
I'd be tempted with an enum to describe the issue e.g Field??? is blank and then use that as the key a dictionary of string builders.
As a first thought anyway
Is your output supposed to be human readable? If so, you'll hit the limit of what is reasonable to read, long before you have any performance/memory issues from your data structure. Use whatever is easiest for you to work with.
If the output is supposed to be machine readable, then that output might suggest an appropriate data structure.
As others have pointed out, I would probably use StringBuilder. The List may have to resize many times; the new implementation of StringBuilder does not have to resize.
Sorry for the weird title, I could't think of anything better!
Anyways, I'm half way through writing a program (Windows Forms App) that reads in a fixed-width file, gathers field lengths from user input, then it's supposed to display each column from the first line of the file in a different color... Do you know what I mean? It's basically to differentiate between the different fields in a fixed-width file using color.
What I wanted to ask was what was the best way to go about this? Because I'm having a lot of trouble, and I keep running into things and just implementing disgusting solutions when I know there is a much better one.
Obviously you don't have to give me a whole program, just some ideas of better ways to go about this - because my solution is just horrendous.
Thank you all in advance!
I would use a RichTextBox. This has an easy way to change the color of text. Here is an example where I have 3 inputs from the user that tells how wide each column should be. Then it reads in a file and colors the widths appropriately. Hopefully this will give you some more ideas.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ReadFile();
}
private void ReadFile()
{
// Assumes there are 3 columns (and 3 input values from the user)
string[] lines_in_file = File.ReadAllLines(#"C:\Temp\FixedWidth.txt");
foreach (string line in lines_in_file)
{
int offset = 0;
int column_width = (int)ColumnWidth1NumericUpDown.Value;
// Set the color for the first column
richTextBox1.SelectionColor = Color.Khaki;
richTextBox1.AppendText(line.Substring(offset, column_width));
offset += column_width;
column_width = (int)ColumnWidth2NumericUpDown.Value;
// Set the color for the second column
richTextBox1.SelectionColor = Color.HotPink;
richTextBox1.AppendText(line.Substring(offset, column_width));
offset += column_width;
column_width = (int)ColumnWidth3NumericUpDown.Value;
// Make sure we dont try to substring incorrectly
column_width = (line.Length - offset < column_width) ?
line.Length - offset : column_width;
// Set the color for the third column
richTextBox1.SelectionColor = Color.MediumSeaGreen;
richTextBox1.AppendText(line.Substring(offset, column_width));
// Add newline
richTextBox1.AppendText(Environment.NewLine);
}
}
}