How to combine paths through a loop - c#

I am creating a folder maze creator (creating one folder within another) application for some fun, but it seems to be much more complicated than what I first expected. I think examples will explain this better. Basically I want to do this
for (int i = 0; i < iterations; i++)
{
Directory.CreateDirectory(dirName + i);
for (int ii = 0; ii < iterations; ii++)
{
Directory.CreateDirectory(Path.Combine(dirName + i, dirName + ii));
for (int iii = 0; iii < iterations; iii++)
{
Directory.CreateDirectory(Path.Combine(dirName + i, dirName + ii, dirName + iii));
for (int iv = 0; iv < iterations; iv++)
{
Directory.CreateDirectory(Path.Combine(dirName + i, dirName + ii, dirName + iii, dirName + iv));
}
}
}
}
But, instead of setting the number of nested loops, I wanted the user to be able to set that at runtime. So with some help from Programmers, I got this.
private void Recursion(int depth)
{
if (depth >= depthMax)
return;
//string[] folderPlace = new string[depthMax + 1];
//for (int ii = 0; ii < depthMax; ii++)
//{
// if (ii <= depth)
// {
// folderPlace[ii] = dirName;
// }
// else
// {
// folderPlace[ii] = "";
// }
//}
for (int i = 0; i < iterations; i++)
{
folderPlace[1] = dirName + i;
Directory.CreateDirectory(dirName + i);
Recursion(depth + 1);
}
}
But I just can't seem to find a way to get the right path in an array so every folder goes where it should automatically...
Any help appreciated, thanks!

I would suggest you have a look at this example:
public partial class Form1 : Form
{
const string DirName = "Mydir";
const string RootFolder = #"c:\test";
public Form1()
{
CreateDirectories(0, 5, 5, RootFolder);
InitializeComponent();
}
public void CreateDirectories(int currentDepth, int maxDepth, int iterations, string root)
{
if (currentDepth > maxDepth)
{
return;
}
for (var i = 0; i < iterations; i++)
{
var currentDirName = Path.Combine(root, DirName + i.ToString());
Directory.CreateDirectory(currentDirName);
CreateDirectories(currentDepth + 1, maxDepth, iterations, currentDirName);
}
}
}

Basically, you need to know the difference between Iterations and Recursions.
Iterations are all types of loops (eg. for, foreach). Recursion means a method calls its self and provides some kind of an exit-condition to prevent endless exectution.
Recursions allow you to define the level of nesting for operations, but is considered slower. Iterations only allow you to define how many circles one iteration processes, but not the level of nesting which is kind of hard coded (the 3 nested loops in you first example). IMO Iterations are easier to understand and to develop, compared to recursion.
Your particular problem calls for a combined solution, where a method calls its self recursively inside iteration-circles.
A possible solution would look like below (the most interesting part is the Magic(int, string)-method, where i have added some comments to point out examples of the things I have explained above):
private class FolderMaze
{
private const string SubDirectoryName = "Maze_";
private readonly string baseDirectory;
private readonly int depth;
private readonly int nFoldersPerIteration;
public FolderMaze(string baseDirectory, int depth, int nFoldersPerIteration)
{
this.baseDirectory = baseDirectory;
this.depth = depth;
this.nFoldersPerIteration = nFoldersPerIteration;
}
public void Magic()
{
this.Magic(0, this.baseDirectory);
}
private void Magic(int iteration, string iterationPath)
{
// exit condition
if (iteration >= this.depth)
{
return;
}
// Iteration
for (int i = 0; i < this.nFoldersPerIteration; i++)
{
var currentPath = Path.Combine(iterationPath, SubDirectoryName + i);
Directory.CreateDirectory(currentPath);
// recursive call to Magic(int string)
this.Magic(++iteration, currentPath);
}
}
}
You can call it like this:
var maze = new FolderMaze(Environment.CurrentDirectory, 2, 2);
maze.Magic();
I did put the solution inside a class, so that you can focus on the important things in the Magic-method, but you could also put this inside a single method w/o a surrounding class like in the answer provided by #Jean F.

Related

Unable to move the hash sign the right side

I'm unable to move the hash sign to the right to get the below shape.
My below code is working not as expected but I need to get the below shape.
Please how do I do it?
#
##
###
####
#####
######
#######
public class MyProgramTest
{
public static void StaircaseChallenge(int n)
{
for (int i = 1; i <= n; i++) {
Console.WriteLine(MySpace(i) + HashSign(i));
}
}
public static string HashSign(int n)
{
string t = "";
for (int i = 1; i <= n; i++) {
t += "#";
}
return t;
}
public static string MySpace(int n)
{
string t = "/t";
for (int i = 1; i < n; i++)
{
t += " ";
}
return t;
}
}
Try this:
public class MyProgramTest
{
public static void StaircaseChallenge(int n)
{
for (int i = 1; i <= n; i++)
{
Console.WriteLine(" ".PadLeft(n - i+1, ' ')+"#".PadLeft(i,'#'));
}
}
Or make few changes to your code:
public class MyProgramTest
{
public static void StaircaseChallenge(int n)
{
for (int i = 1; i <= n; i++)
{
Console.WriteLine(MySpace(n - i + 1) + HashSign(i));
}
}
public static string HashSign(int n)
{
string t = "";
for (int i = 1; i <= n; i++)
{
t += "#";
}
return t;
}
public static string MySpace(int n)
{
string t = string.Empty;
for (int i = 1; i < n; i++)
{
t += " ";
}
return t;
}
}
A more memory efficient way would be using the StringBuilder class.
For this situation it's not critical, but nice to know.
// define the amount of steps
int n=8;
// amount of leading whitespaces, for later usage
int padding=0;
// this one is the "working" memory, initialized by n + padding whitespaces
StringBuilder currentLine=new StringBuilder(new string(' ',n+padding));
// it counts down from the last index to the one indicated by padding
for (int i = currentLine.Length-1; i >=padding; i--)
{
// replace the char at the current index with #; (here: always the index of the last whitespace)
currentLine[i]='#';
// display a copy of the current state on the console,
Console.WriteLine(currentLine.ToString());
}
Please change only few things in your code :
public class MyProgramTest
{
public static void StaircaseChallenge(int n)
{
for (int i = 1; i <= n; i++) {
Console.WriteLine(MySpace(i, n) + HashSign(i));
}
}
public static string HashSign(int n)
{
string t = "";
for (int i = 1; i <= n; i++) {
t += "#";
}
return t;
}
public static string MySpace(int m, int n)
{
string t = "";
for (int i = 1; i <= n - m; i++)
{
t += " ";
}
return t;
}
}
You have to pass more one variable is n (number of row) in MySpace() function for leave space. When you pass number of row in MySpace() function then it will leave (number of row - 1) space. So if you enter 5 then first time it will leave 4 space and then put "#" like wise.

Execution time and number of comparisons done for string matching search

I need to count the number of comparisons done by the following search function..
Also how to calculate the execution time..Any help? I want the count and time to be printed in the output.
// C# program for Naive Pattern Searching
using System;
class GFG {
public static void search(String txt, String pat)
{
int M = pat.Length;
int N = txt.Length;
/* A loop to slide pat one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for pattern
match */
for (j = 0; j < M; j++)
if (txt[i + j] != pat[j])
break;
// if pat[0...M-1] = txt[i, i+1, ...i+M-1]
if (j == M)
Console.WriteLine("Pattern found at index " + i);
}
}
// Driver code
public static void Main()
{
String txt = "AABAACAADAABAAABAA";
String pat = "AABA";
search(txt, pat);
}
}
// This code is Contributed by Sam007
I need to count the number of comparisons done by the following search function...
You can use counter for this:
public static void search(String txt, String pat, out int counter)
{
int M = pat.Length;
int N = txt.Length;
counter = 0;
/* A loop to slide pat one by one */
for (int i = 0; i <= N - M; i++)
{
int j;
/* For current index i, check for pattern
match */
for (j = 0; j < M; j++)
{
counter++; // counter for below if statement
if (txt[i + j] != pat[j])
{
break;
}
}
// if pat[0...M-1] = txt[i, i+1, ...i+M-1]
if (j == M)
{
Console.WriteLine("Pattern found at index " + i);
}
counter++; // counter for above if statement
}
}
Also how to calculate the execution time.
You can use StopWatch class for this case:
public static async Task Main(string[] args)
{
String txt = "AABAACAADAABAAABAA";
String pat = "AABA";
var stopWatch = new Stopwatch();
stopWatch.Start();
search(txt, pat, out var counter);
stopWatch.Stop();
Console.WriteLine("--------------");
Console.WriteLine($"Count of operations: {counter}, elapsed time: {stopWatch.ElapsedMilliseconds} miliseconds");
}

Bubble sort when using struct members

struct SSales
{
private int Y;
private double S;
public int Year
{
get { return Y; }
set { Y = value; }
}
public double Sale
{
get { return S; }
set { S = value; }
}
public SSales (int _year, double _sales)
{
Y = _year;
S = _sales;
}
private void Sortbutton_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
if (yearradio.Checked)
{
int temp = 0;
for (int i = 0; i < bubble.Length - 1; i++)
{
for (int j = 0; j < bubble.Length - 1; j++)
{
if (bubble[i + 1].Year < bubble[i].Year)
{
temp = bubble[i].Year;
bubble[i].Year = bubble[i + 1].Year;
bubble[i + 1].Year = temp;
}
}
}
}
if (salesradio.Checked)
{
double temp2 = 0;
for (int i = 0; i < bubble.Length - 1; i++)
{
for (int j = 0; j < bubble.Length - 1; j++)
{
if (bubble[i + 1].Sale > bubble[i].Sale)
{
temp2 = bubble[i].Sale;
bubble[i].Sale = bubble[i + 1].Sale;
bubble[i + 1].Sale = temp2;
}
}
}
}
for (int i = 0; i < bubble.Length; i++)
{
listBox1.Items.Add(bubble[i].ToString());
}
}
While my bubble sorting algorithms work perfectly fine, they only sort incrementally with each click of the Sort Button. I need the listbox to be completely sorted with 1 click.
Also, as my code is now, the Years and Sales reorganize completely independent of each other. When the Sales index changes, the corresponding Year index remains at the same location and vice versa.
I'm guessing a for loop with int j would work, but I'm not sure how to implement it. Any help would be appreciated!
I see two issues. One you are setting/exchanging the Properties of the struct, not the structs themselves. That is why your sales and years are out of sync. You need to exchange the entire struct. Something like:
var temp = bubble[i];
bubble[i] = bubble[i + 1];
bubble[i + 1] = temp;
This leads to the second issue. You have a double loop using index variables i and j. Your swap only uses i. If you are trying to do a bubble sort do you really need nested loops? Consider the pseudo-code implementation that can be found here bubble sort, you should quickly be able to see the issue. Model your sort after that example.
I will guess that you are doing bubble sort for learning / practice reasons. If not you should just use the inbuilt Array.Sort() or Enumerable.OrderBy() or something similar.
There are multiple things you have done wrong. I have the improved code below which I will explain
struct SSales {
public int Year { get; set; } // use auto-properties for brevity
public double Sale { get; set; } // use auto-properties for brevity
public SSales(int year, double sales) {
Year = year;
Sale = sales;
}
}
// Use a generic routine to Swap, instead of replicating the code multiple times
// Note that we are passing by reference so the actual array eventually gets sorted
// Also, don't swap the properties, but the whole record. Else it will corrupt your data
static void Swap<T>(ref T obj1, ref T obj2) {
var temp = obj1;
obj1 = obj2;
obj2 = temp;
}
// Write the sort routine separately. Sorts usually just need a way to compare records, which can be provided by Caller (IoC pattern)
static void Sort<T>(T[] items, Func<T, T, int> comparer) {
for (int i = 0; i < items.Length - 1; i++) {
// Every execution of the inner loop will bubble-up the largest element in the range
// Your array is getting sorted from the end, so you don't need to re-compare the already sorted part
for (int j = 0; j < items.Length - 1 - i; j++) {
if (comparer(items[j], items[j + 1]) > 0) // call the generic user provided comparer to know the sequence
Swap(ref items[j], ref items[j + 1]); // use teh generic swapper to swap elements in the array
}
}
}
private void Sortbutton_Click(object sender, EventArgs e) {
listBox1.Items.Clear();
if (yearradio.Checked) {
// Invoke the Sort routine, with the required comparer
Sort(bubble, (a, b) => a.Year - b.Year);
}
if (salesradio.Checked) {
// Invoke the Sort routine, with the required comparer
Sort(bubble, (a, b) => (int)(a.Sale - b.Sale));
}
for (int i = 0; i < bubble.Length; i++) {
listBox1.Items.Add(bubble[i].ToString());
}
}
Hope that clarifies the issues you are facing and also helps you learn how to write better C# code.

Is there some sort of algorithm to continue looping through an unknown amount of child members? [duplicate]

This question already has answers here:
Depth-first flattened collection of an object hierarchy using LINQ
(4 answers)
Closed 8 years ago.
I have the following object set up:
public class DrawingInstance
{
public string DrawingNum;
public string Rev;
public string Title;
public int LevelNum;
public string RefDesc;
public string DateRelease;
public string DrawingType;
public DrawingInstance ParentMember;
public int PageInstance;
public List<DrawingInstance> ChildMembers = new List<DrawingInstance>();
}
After gathering all of the data, I am currently accessing each child member one level at a time, like so:
for (int i = 0; i < drawingInstance.ChildMembers.Count; i++)
{
for (int j = 0; j < drawingInstance.ChildMembers[i].ChildMembers.Count; j++)
{
....
....
}
}
The number of levels in the file being processed can be different each time.
Is there a way through recursion to loop through and traverse an infinite number of levels? I need to process them 1 level at a time. So all of the i's will be processed, then all of the j's for each i are processed, and so on. Currently I have 10 blocks of code for processing a possible of 10 levels, but I feel like there has to be a better way to go about this.
EDIT
Thanks for the quick responses.
Here is a more detailed look straight from my code that gives a little more insight into how I am currently processing the objects
//Level 0 Pages
int _pageNum = PageNum;
int startIdx = 0;
int pageCount = 0;
pageCount = GetVisioPageCount(_treeArray.ChildMembers.Count);
for (int i = 0; i < pageCount; i++)
{
VisioSheetOutline tempSheet = new VisioSheetOutline();
tempSheet = GetSingleSheet(_treeArray, startIdx, _pageNum, (i + 1));
for (int cMember = 0; cMember < tempSheet.ChildPairs.Length; cMember++)
{
ParentDictionary.Add(tempSheet.ChildPairs[cMember].SingleInstance, tempSheet.SheetName);
}
SheetList.Add(tempSheet);
_pageNum++;
startIdx += 15;
}
//Level 1 Pages
for (int i = 0; i < _treeArray.ChildMembers.Count; i++)
{
pageCount = 0;
pageCount = GetVisioPageCount(_treeArray.ChildMembers[i].ChildMembers.Count);
startIdx = 0;
for (int j = 0; j < pageCount; j++)
{
VisioSheetOutline tempSheet = new VisioSheetOutline();
tempSheet = GetSingleSheet(_treeArray.ChildMembers[i], startIdx, _pageNum, (i + 1));
for (int cMember = 0; cMember < tempSheet.ChildPairs.Length; cMember++)
{
ParentDictionary.Add(tempSheet.ChildPairs[cMember].SingleInstance, tempSheet.SheetName);
}
SheetList.Add(tempSheet);
_pageNum++;
startIdx += 15;
}
}
//Level 2 Pages
for (int i = 0; i < _treeArray.ChildMembers.Count; i++)
{
for (int j = 0; j < _treeArray.ChildMembers[i].ChildMembers.Count; j++)
{
pageCount = 0;
pageCount = GetVisioPageCount(_treeArray.ChildMembers[i].ChildMembers[j].ChildMembers.Count);
startIdx = 0;
for (int k = 0; k < pageCount; k++)
{
VisioSheetOutline tempSheet = new VisioSheetOutline();
tempSheet = GetSingleSheet(_treeArray.ChildMembers[i].ChildMembers[j], startIdx, _pageNum, (i + 1));
for (int cMember = 0; cMember < tempSheet.ChildPairs.Length; cMember++)
{
ParentDictionary.Add(tempSheet.ChildPairs[cMember].SingleInstance, tempSheet.SheetName);
}
SheetList.Add(tempSheet);
_pageNum++;
startIdx += 15;
}
}
}
I am currently looking into a few of the suggestions that were made to see which one fits my particular need.
Yes, as you suggested, you can easily deal with this using recursion; you just need a recursive function:
public void ProcessDrawingData(DrawingInstance instance)
{
// Do processing
foreach (DrawingInstance d in ChildMembers)
ProcessDrawingData(d);
}
Call it with the parent instance. This won't do a true breadth-first traversal though, as the first child will execute its first childs children (first all the way down) and slowly unwind.
Microsoft's Ix-Main package contains a number of LINQ extensions, including the Expand method which will flatten a hierarchical layout:
IEnumerable<DrawingInstance> rootList = ...;
IEnumerable<DrawingInstance> flattened = rootList.Expand(x => x.ChildMembers);
You can use the foreach() statement. This will iterate through a group that you need, assuming the object implements IEnumerable.
In your case, try this:
foreach(DrawingInstance di in ChildMembers)
{
// Do something with di.
}
EDIT
If you need to do this repeatedly, you should have some sort of a recursive method that takes a DrawingInstance, like this:
public void RecursiveMethod(DrawingInstance d)
{
foreach(DrawingInstance di in d.ChildMembers)
{
RecursiveMethod(di);
}
}
I don't know your project, so it is up to you to figure out the base case, or if this recursive edit is what you actually want.

Looking for keywords in a given string. Easiest and Fastest, + what I have so far

I am making a syntax coloring tool. I am currently writing the method to find and highlight the keywords, ex if then else.. I am sure there is a better (faster and more aesthetic) way to do this.
Below are two methods, the first I try and not to use any string methods except for length to try and improve speed.
The second I used string methods but I've been told they are slower then doing it the first way.
Which way is faster? And for the first one, the word is only highlighted when a space is after that word which is not right, any remedy for that too?
Code:
private string[] m_keywords = new string[] { "GOTO", "IF", "THEN", "ELSE", "WHILE", "DO" };
private int m_nShortestKeywordLength = 2;
// lcpy_strLine is a copy in all uppercase of the current line I am processing
private void ProcessKeywords(Color clr)
{
if(lcpy_strLine.Length > m_nShortestKeywordLength)
for (int i = 0; i < m_keywords.Length; i++)
{
string curWord = m_keywords[i];
int len = curWord.Length;
for (int j = 0; j < lcpy_strLine.Length; j++)
{
if (j + len < lcpy_strLine.Length)
{
int k = 0;
while (k < len && lcpy_strLine[j + k] == curWord[k])
k++;
if (k == len)
{
Console.WriteLine("Found Keyword");
SelectionStart = m_nLineStart + j;
SelectionLength = k;
SelectionColor = clr;
}
}
}
}
}
private void ProcessKeywords2(Color clr)
{
/*for (int i = 0; i < m_keywords.Length; i++)
if (lcpy_strLine.Contains(m_keywords[i]))
{
int indx1 = lcpy_strLine.IndexOf(m_keywords[i]);
SelectionStart = m_nLineStart + indx1;
SelectionLength = m_keywords[i].Length;
SelectionColor = clr;
}*/
}
The easiest way to do this would probably be a regular expression. It'll be reasonably fast, too.
private string[] m_keywords = new string[] { "GOTO", "IF", "THEN", "ELSE", "WHILE", "DO" };
private Regex keywordRegex = new Regex(#"\b(" + string.Join("|", m_keywords) + #")\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
And no need to uppercase the line:
private void ProcessKeywords(Color clr)
{
foreach (Match m in keywordRegex.Matches(someLine)) {
SelectionStart = m.Index;
SelectionLength = m.Length;
SelectionColor = clr;
}
}
When using string.IndexOf, you need to specify StringComparison.Ordinal to get good performance.
The default overload uses a culture-aware comparison (e.g. it considers "æ" equal to "ae"), which is a lot more expensive than a simple character-by-character comparison.

Categories