Regex access elements within string - c#

I have the following regex code:
#"(N[0-9][EHPULMAVRYGBWK123670]{4}[N]{1}PF[0]{1}[0-9]{1})";
The [EHPULMAVRYGBWK123670] within the regex refer to specific button types or colours.
There are four buttons in total, and the order they are in the part number denotes the order that they are in the product (from top left to top right).
For example if the part number contained:
RGBY - Red (Top Left), Green (Top Right), Blue (Bottom Left), Yellow (Bottom Right)
GBYR - Green (Top Left), Blue (Top Right), Yellow (Bottom Left), Red (Bottom Right)
After the buttons, there is always the letter N, and a PF number.
What I want to do is extract the 4 letter combination for the colors. The {4} in the regex is what captures those letters. I then needs to make a decision based on the order of the letters.
How would I go about doing this?

You need to modify your regex slightly so that it captures the four letters in question. You can then decide what to do with them:
var pattern = #"(N[0-9]([EHPULMAVRYGBWK123670]{4})[N]{1}PF[0]{1}[0-9]{1})";
var test = "NO4A6SRP11N2UBWYNPF05";
var regex = new Regex(pattern, RegexOptions.IgnoreCase);
var result = regex.Match(test);
if(result.Success)
{
var value = result.Groups[2].Value;
switch (value)
{
case "UBWY":
//Do something
break;
case "RBYG":
//Do something
break;
default:
break;
}
}
Notice the parenthesis around the pattern that matches the four letters.
There are more elegant approaches to deciding what to do with the four letter code. In this case I have provided a simple switch statement for illustration purposes.
Alternatively, you can examine the string you capture letter by letter:
//Character by character, in order
for (int i = 0; i < value.Length; i++)
{
char letter = value[i];
//Decide what to do here.
}
//Or check positions by index
if(value[0] == 'U')
{
//Decide what to do here.
}
Depending on how many combinations are possible, you might want to consider using a state machine.

Related

String handling in c#?

I have each string below :
MULTIPOLYGON(((107.067521 16.873693000000003,107.06849999999997 16.873613000000034)))
Now is there any way to group 107.067521 16.8736930000003 into a group, 107.06849999999997 16.873613000000034 into a group and in each group separate them. Example with group 107.067521 16.873693000000003 will split lat=107.067521, lng=16.873693000000003, do the same with the rest of the groups.
I think I'd use Split to do all the work:
var nums = input.Split(", ()".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var points = new List<Point>();
for(int i = 1; i < nums.Length; i += 2){
points.Add(new Point {
Lat = double.Parse(nums[i+1],
Lon = double.Parse(nums[i])
});
}
Note in WKT representation it's more typical to have it in "Long Lat" order - you've said the lat comes first. If you're absolutely certain your string is "Long Lat" then swap the assignments over inside the loop, but double check first otherwise you might end up drawing your polygons on a completely different part of the planet
Another thing to point out; you've only got a single poly here and if you only ever have one then simple parsing it like above will do, but the use of a multi poly is to keep track of which polygons are supposed to be kept together. Flattening to a list of points will work ok if there is only one poly, but things could go wonky if there really are multiple polys in your string eg
MULTIPOLYGON( (1 2,3 4,5 6,1 2) , (7 8,9 10,11 12,7 8) )
POLYGON( (1 2,3 4,5 6,1 2,7 8,9 10,11 12,7 8) )
These two are completely different shapes (and the latter doesn't close).. Take care with it, and consider a more involved parsing routine if you truly have multi polys
With no regular expression, my approach is to find the text enclosed by the last ( and the first ), then split it using String.Split and delimiters of , and a space . Remove empty entries in case there are multiple spaces.
string example = #"MULTIPOLYGON(((107.067521 16.873693000000003,107.06849999999997 16.873613000000034)))";
int start = example.LastIndexOf('(');
int end = example.IndexOf(')');
string inside = example.Substring(start + 1, end - start - 1);
string[] fields = inside.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
// Example
Console.WriteLine($"long1={fields[0]} lat1={fields[1]} long2={fields[2]} lat2={fields[3]}");
To be slightly more robust, you could do a first pass to delimit on commas to get long-lat pairs separated by spaces, and then split those fields on spaces. But assuming the input is well formed, the example above should work reasonably well.

How to write in multiple positions in a console application at the same time? C#

I want lines as many as the width of the console to simultaneously write downwards one char to the height of the console. I've done most of it, but it goes from top to bottom to right etc...
If you need help picturing what I mean, think of the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < w)
{
int j = 0;
while (j < h)
{
Thread.Sleep(1);
Console.SetCursorPosition(i, j);
Console.Write(".");
j++;
}
i++;
}
What I would do is construct a List<string> lines; that would contain the lines you want to write to the console window, where each line is as wide as the console width. Then just print the list out to the console window in reverse order, so the first line (at lines[0]) will always be the last one printed, and will always be at the bottom of the console window.
Sample Implementation -- someone mentioned this might be homework. I did not think so, but if it is, then please try your own implementation of the above idea first.
We can add new items to the list in the same loop that we use to print out its items. Before we add a line, however, we first check to see if there are already as many lines in the list as there are in the console window (Console.WindowHeight). If there are, then we just remove the line at lines[0] before we add a new one. In this way, the List<string> lines is "scrolling" along with the console window.
The scrolling speed is controlled by a Thread.Sleep, but this code could easily be added to a Timer instead, so that other work could happen in the background (like if this was intended to be a "screensaver", and you wanted to wait for user input to "wake up"). But no matter how we decide to implement the speed, I decided to create an enum with values that represent the number of milliseconds a Thread.Sleep implementation would use:
class Program
{
enum MatrixCodeSpeed
{
Fastest = 0,
Faster = 33,
Fast = 67,
Normal = 100,
Slow = 333,
Slower = 667,
Slowest = 1000
}
I would also create a helper method that creates a "random" line for you. It could take in an integer that specifies the "density", which means how many characters you'd want in the line. density represents a percentage, so if 10 is specified, then we pick a random number between 0 and 99, and if it's less than 10 then we add a random matrix character to the string (otherwise we add a space character).
Also, in order to replicate the matrix a little closer, I've also chosen 4 different characters to print, each one slightly darker than the previous. This adds to the three dimensional effect, where the faded blocks look further away than the solid ones:
private static Random rnd = new Random();
// Add whatever 'matrix' characters you want to this array. If you prefer to have one
// character chosen more often than the others, you can write code to favor a specific
// index, or just add more instances of that character to the array below:
private static char[] matrixChars = new[] { '░', '▒', '▓', '█' };
static string GetMatrixLine(int density)
{
var line = new StringBuilder();
for (int i = 0; i < Console.WindowWidth; i++)
{
// Choose a random number from 0-99 and see if it's greater than density
line.Append(rnd.Next(100) > density
? ' ' // If it is, add a space to reduce line density
: matrixChars[rnd.Next(matrixChars.Length)]); // Pick a random character
}
return line.ToString();
}
Next, we have the main method, which populates a list with random lines (using a density of 10%), then prints them out one at a time, in reverse order, in an endless loop (removing the first line if we need to):
static void Main()
{
var lines = new List<string>();
var density = 10; // (10% of each line will be a matrix character)
var speed = MatrixCodeSpeed.Normal;
// Hide the cursor - set this to 'true' again before accepting user input
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.DarkGreen;
while (true)
{
// Once the lines count is greater than the window height,
// remove the first item, so that the list "scrolls" also
if (lines.Count >= Console.WindowHeight)
{
lines.Remove(lines[0]);
}
// Add a new random line to the list, which will be the new topmost line.
lines.Add(GetMatrixLine(density));
Console.SetCursorPosition(0, 0);
// Print the lines out to the console in reverse order so the
// first line is always last, or on the bottom of the window
for (int i = lines.Count - 1; i >= 0; i--)
{
Console.Write(lines[i]);
}
Thread.Sleep(TimeSpan.FromMilliseconds((int)speed));
}
}
}
Here's a gif of it in action, up to the point where the screen is full (then the gif repeats, but the code version continues to scroll normally):
The task smells like an assignment, so I'm guiding you instead feeding the implementation. It is not ethical to feed you with an answer if it is a homework.
You are looking for a better fit of algorithm. The stated algorithm fill the console from top to bottom, as it iterate to fill through the Y-axis first (the nested loop) and followed by the X-axis (the outer loop).
What is needed is to iterate x-axis and y-axis alternatively so that it looks like it fills from the top left corner to the bottom right corner.
// 1 step to (0,0)
*
// 3 steps to (1,1)
**
**
// 5 steps for reaching (2,2)
***
***
***
// 7 steps for reaching (3,3)
****
****
****
// 9 steps for reaching (4,4) and 11 steps for (5,5)...
// I do think everyone could get this pattern
This draft would also be the final outcome of what it looks like.
Instead of filling them all at the same time, what you need is actually get the thread sleep after it reach the next square point.
(Computers are so fast that it probably do all its work to feed your screen within a second and the black console window is gone without any notice.)
At the time you posted the question, I'm also solving it from the very beginning. I thought of filling X and Y axis alternatively is the solution, but stopping at each time that the square expands is far more important to get the effect.
It is not a threading problem tag either at my point of view.
Let's sum up the above pattern:
Assume i and j are x and y coordinates respectively.
Each iteration takes you from (i, j) and n*2+1 steps to reach
(i+1,j+1)
Note that we are zero-based in this example.
We are about to construct the loop:
The n*2+1 step number is useful. It means you need to fill x-axis for
n times and y-axis for n times, and finally get the diagonal grid
(n+1,n+1) done.
In each inner loop, we first render the X frontier along y-axis and
then render the Y frontier along x-axis.
Let say the cycle start with the checkpoint (n,n), where n=3, and we
slept for a while, so we are in n=4 now.
To achieve this, we'd better first navigate to (n+1,0) then fill up
to (n+1,n)
Afterwards we navigate to (0,n+1) and fill to (n+1,n+1)
Then we are in m=n+1 now (sounds like a mathematical proving :(
The loop would be
//calculate how many checkpoints (n)
int checkpoints = 1080;
//n should indicate the actual turn we are instead of naming the total turns like sucks
//The main, the outermost For-loop
for (int n=0;n<checkpoints;n++)
{
// The nested step
for (int y=0;y<n;y++)
{
// Just fill in (n+1, y) grid
Console.SetCursorPosition(n+1, y);
Console.Write(".");
}
for (int x=0;x<n+1;x++)
{
// Just fill in (x, n+1) grid
Console.SetCursorPosition(x, n+1);
Console.Write(".");
}
// Upon completion of each main cycle we have a sleep, yah
Thread.Sleep(100);
}
Well, I expect the program to crash when the console size is smaller than 1080x1080.
This algorithm could only get you a square to fill, and a typical monitor with resolution 1920x1080 just fails as it is 16:9. This is intentional, if you're doing homework you need to configure it before shipping it to your teacher. (I've got no chance to do an assignment as I self learned programming :(
(The site continuously urging me to format my code, this has been half an hour and I just didn't do things wrong. So I decided to post it bit by bit to debug that. Finally I've got the job done...)
If you just want to write one line at a time you can use this:
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
Console.WriteLine(new string('.', w-1));
Thread.Sleep(20);
i++;
}
Just a bit of modification allow the code to simulate the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
int j = 0;
string s = "";
Thread.Sleep(10);
while (j < w)
{
Console.SetCursorPosition(j, i);
s += ".";
j++;
}
Console.Write(s);
i++;
}
basically what i did here is just some restructuring of the logic and putting in the proper delays at the right position. Hope it helps.

Trying to replace the two spaces after the matched pattern in c#

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.

System of the Unicode Box Drawing table

I'm implementing a function in C# where providing from which side goes what kind of line, it will return one character from the Box Drawing table (0x2500-0x257F) from Unicode. However I've failed (yet) to find a system in the position of these characters in the table, that would make a significantly simpler function, then assigning all possible input to an output in one enormous if-then-else block.
I've noted that there are 9 different line styles (thin, double, thick, double-dashed, triple-dashed, quad-triple-dashed, thick double-dashed, ...) in that table, and with the four direction, with the "no line" information makes 10 different states, which would make up to 9999 different combination not including the "none of the side has a line" case, which in my case would be a space character.
The easiest way I've found to implement this, is to make one freakin' huge array containing all 10000 possible outcome, (where the first digit notes North, the second East, then South and West) but I believe that this is actually the second worst case scenario I've found, and there is a much more elegant solution. (BTW This would be hilarious if you're not planning on implement it this way. That is how I feel about this anyways.)
This question is probably not suitable here, but considering the size of this task, I even take that risk:
Is there a system how the Box Drawing table arranges the characters, and/or is there a simpler algorithm that does the exact same I would like to do?
The simplest/shortes solution I see, needs an array/list of 128 elements.
You declare a struct/class like this:
// I use consts instead of enum to shorten the code below
const int thin = 1;
const int double = 2;
const int thick = 3;
... // other line styles
struct BoxDrawingChar{
int UpLine, DownLine, LeftLine, RightLine;
BoxDrawingChar(int UpLine, int DownLine, int LeftLine, int RightLine)
{ ... }
};
Then you describe appearance of each character:
BoxDrawingChar[] BoxDrawingCharList =
{
new BoxDrawingChar(0, 0, thin, thin), // 0x2500
new BoxDrawingChar(0, 0, thick, thick), // 0x2501
...
new BoxDrawingChar(...), // 0x257F
}
Then your function will be quite simple:
int GetCharCode(int UpLine, int DownLine, int LeftLine, int RightLine)
{
for(int i = 0; i < BoxDrawingCharList.Length; ++i){
BoxDrawingChar ch = BoxDrawingCharList[i];
if (ch.UpLine == UpLine && ch.DownLine == DownLine && ...)
return i + 0x2500;
}
return 0;
}
Of course you can add diagonal lines, rounded angles etc and refactor the code in many ways. I gave only a general idea.

How check if letters are in string?

It quite hard question to ask but I will try.
I have my 4 letters m u g o . I have also free string word(s).
Let'say: og ogg muogss. I am looking for any wise method to check if I can construct word(s) using only my letters. Please take notice that we used once g we won't be able to use it again.
og - possible because we need only **g** and **o**
ogg - not possible we took **o** and **g**, need the second **g**
muogss - not possible we took all, need also additional **s**
So my tactic is take my letters to char array and remove one by one and check how many left to build the word(s). But is it possible to use somehow in few lines, i do not know - regex ?
your method is only a few lines...
public static bool CanBeMadeFrom(string word, string letters)
{
foreach (var i in word.Select(c => letters.IndexOf(c, 0)))
{
if (i == -1) return false;
letters = letters.Remove(i, 1);
}
return true;
}
Here's a simple approach:
For your source word, create an array of size 26 and use it to count the how many times each letter appears.
Do the same for each word in your dictionary.
Then compare the two.
If every letter occurs less than or equal to as many times in the dictionary word as the source word, then it can be used to make that word. If not, then it cannot.
C-Sharpish Pseudocode: (probably doesn't compile as written)
/** Converts characters to a 0 to 25 code representing alphabet position.
This is specific to the English language and would need to be modified if used
for other languages. */
int charToLetter(char c) {
return Char.ToUpper(c)-'A';
}
/** Given a source word and an array of other words to check, returns all
words from the array which can be made from the letters of the source word. */
ArrayList<string> checkSubWords(string source, string[] dictionary) {
ArrayList<string> output = new ArrayList<string>();
// Stores how many of each letter are in the source word.
int[] sourcecount = new int[26]; // Should initialize to 0, automatically
foreach (char c in source) {
sourcecount[c]++;
}
foreach (string s in dictionary) {
// Stores how many of each letter are in the dictionary word.
int[] dictcount = new int[26]; // Should initialize to 0, automatically
foreach (char c in s) {
dictcount[c]++;
}
// Then we check that there exist no letters which appear more in the
// dictionary word than the source word.
boolean isSubword = true;
for (int i=0;i<26;i++) {
if (dictcount[i] > sourcecount[i]) {
isSubword = false;
}
}
// If they're all less than or equal to, then we add it to the output.
if (isSubWord) {
output.add(s);
}
}
return output;
}
If your definition of words is any arbitrary permutation of the available charactters then why do you need a regex? Just make sure you use each characters once. Regex doesn't know what a "correct word" is, and it's better to avoid using invalid characters by your algorithms than using them AND using a regex to make sure you didn't use them.

Categories