How to print asterisk pattern with asterisk - c#
I'm doing this for my school library where I need to print asterisk pattern like below with *'s
* *
* *
***
*******
***
* *
* *
Below is what I tried,
using System;
using System.Text;
namespace Patterns
{
class Asterisks
{
static void Main(string[] args)
{
int n = 7;
for(int i = 1; i<=n; i++){
for(int j =1; j<=n; j++){
if(j==i || j==n-i+1 || i==n/2+1){
Console.Write("*");
}else{
Console.Write(" ");
}
}
Console.WriteLine();
}
}
}
}
Outputs below :
* *
* *
* *
*******
* *
* *
* *
My logic above is faulty, I tried couple of edits on the loops and conditions but somewhere I'm going wrong. Need help to fix this. Thanks
Break the pattern into parts, and write checks for them individually. If any of checks pass, print a *, otherwise a space. This seems to be what you are already doing. You just seem to be missing some disjunctions in your if statement.
Right now, your condition to print a * is:
j==i || // the "\" part
j==n-i+1 || // the "/" part
i==n/2+1 // the "-" part
You really just need one more condition that those two missing positions would match. One way to check for this is to check that the column (j) is the middle column, and that the row (i) is one away from the middle row.
j == n / 2 + 1 && (i == n / 2 + 2 || i == n / 2)
There's quite a lot of + 1s in your conditions. You can remove them if you start your loop at 0. Rather than repeating n / 2 all the time, you can extract to a variable.
Your code ends up being like this:
int n = 7;
int midRow = n / 2;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (j == i ||
j == n - i - 1 ||
i == midRow ||
j == midRow && (i == midRow + 1 || i == midRow - 1))
{
Console.Write("*");
}
else
{
Console.Write(" ");
}
}
Console.WriteLine();
}
Output:
* *
* *
***
*******
***
* *
* *
Think of the problem as painting a picture line by line and pixel by pixel, starting from the top left (TL) corner and moving to the bottom right (BR).
Depending on the brush/cursor's current position, the program should either "paint" a * or a . This is what the if inside the for does.
If you only wanted to paint a diagonal going from TL to BR then the if only needed one check:
if (j == i) {
Console.Write("*");
} else {
Console.Write(" ");
}
Try it out for yourself and you'll see this shape:
*
*
*
*
*
*
*
Also try and understand how i and j are changed by the two for loops over time and why this works.
For the opposite diagonal we'll have to get the "inverted" value of i which is n - i + 1. This inverted i is what the value of i would have been if we were drawing the picture going right to left, but still top to bottom (i.e. from TR to BL). Knowing this inverted i we can now add an additional check to the if that makes the if more inclusive and draw on more positions:
if (j == i // diag from TL to BR
|| j == n - i + 1 // diag from TR to BL
) {
Console.Write("*");
} else {
Console.Write(" ");
}
This will give us the following shape:
* *
* *
* *
*
* *
* *
* *
Again, try it out for yourself.
The horizontal center line is easier, because it only depends on i, but not on j. We just have to check if we are currently in the center line:
if (j == i // diag from TL to BR
|| j == n - i + 1 // diag from TR to BL
|| i == n / 2 + 1 // center horizontal
) {
Console.Write("*");
} else {
Console.Write(" ");
}
Make sure you understand why the + 1 in n / 2 + 1 is necessary.
Similarly we can also include the center vertical line like so:
if (j == i // diag from TL to BR
|| j == n - i + 1 // diag from TR to BL
|| i == n / 2 + 1 // center horizontal
|| j == n / 2 + 1 // center vertical
) {
Console.Write("*");
} else {
Console.Write(" ");
}
...and we'll end up with this shape:
* * *
* * *
***
*******
***
* * *
* * *
The only problem now is that we don't want to draw the whole vertical line, only it's middle part. So the last check we added to the if is too inclusive, it needs to be more strict. Only the parts of the vertical line that are right next to the center point should be drawn. Or, more precisely, only the point above and the point below the center point should be drawn. (It doesn't matter if we include or exclude the actual center point in the check, because all other checks will cause it to be drawn anyway).
The cursor is right on the center point when i == n / 2 + 1 and j == n / 2 + 1. The point above the center has an i value of n / 2 and the point below an i value of n / 2 + 2.
So when j == n / 2 + 1 is true (we're currently somewhere on the vertical center line) we must also ensure that we're either directly above or below the center point like so:
if (j == i // diag from TL to BR
|| j == n - i + 1 // diag from TR to BL
|| i == n / 2 + 1 // center horizontal
|| (j == n / 2 + 1 && (i == n / 2 || i == n / 2 + 2))
) {
Console.Write("*");
} else {
Console.Write(" ");
}
* *
* *
***
*******
***
* *
* *
Here is an idea - you can map your shape using a jagged array, where 1 means a sign in this case'*' and 0 is a space.
So our pattern will be like this:
int[][] myPattern = new int[][]
{
new int[] {1,0,0,0,0,0,0,0,0,0,1 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {0,1,0,0,0,0,0,0,0,1,0 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {0,0,0,0,1,1,1,0,0,0,0 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {1,1,1,1,1,1,1,1,1,1,1 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {0,0,0,0,1,1,1,0,0,0,0 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {0,1,0,0,0,0,0,0,0,1,0 },
new int[] {0,0,0,0,0,0,0,0,0,0,0 },
new int[] {1,0,0,0,0,0,0,0,0,0,1 }
};
If you look at it - represent our asterisk sign.
What you then have to is loop per each item in the jagged array.
for (int j = 0; j < myPattern.Length; j++)
{
for (int i = 0; i < myPattern[j].Length; i++)
{
if (myPattern[j][i] > 0)
{
Console.Write('*');
}
else
{
Console.Write(' ');
}
if (i+1 == myPattern[j].Length)
{
Console.WriteLine();
}
}
}
if you want you can remove altogether the patter with all 0's and replace this
if (i+1 == myPattern[j].Length)
{
Console.WriteLine();
}
with
Console.WriteLine();
I have left it in for demonstration purpose.
Related
Why aren't these integer number reaching the cap?
I wanted to try creating a console app that could give me the results of evaluating the Collatz conjecture with several different numbers, but when the program runs up to 113,000 the numbers stop calculating. In order to do so, I used a (double,int) for calculations. Here is my reasoning: if an odd double is divided by 2, you will get a decimal: 2.3,2.4,2.5, and so on; however, if an odd integer is divided by 2 you will get another integer. Using this knowledge, if a number is odd, then the decimal version of the number will not be equal to the integer version. However, after doing a few tests, I found that the numbers stopped at 113,000. When the max for integers and doubles should be higher. These are the results. [1]: https://i.stack.imgur.com/xdHpT.png The following code bellow checks if a number is even or odd. If the number is even, the number is divided by two, and if the number is odd, the number is multiplied by three and added by 1. There are no errors listed in the debug screen. My expected result is for the list of numbers to continue up to the int maximum. static (double,int) Checker(double n1, int n2) { double newn1 = n1; int newn2 = n2; if(n1/2==n2/2) { newn1 = n1 / 2; newn2 = n2 / 2; } else { newn1 = (n1 * 3) + 1; newn2 = (n2 * 3) + 1; } return (newn1,newn2); } The part of code below ensures that each number is calculated using the Collatz conjecture until a result of 1 is released or j = (1,1) static void Main(string[] args) { int v = 2; int timer = 1; int savedv = 1; bool run = true; bool reached = false; (double, int) j; j.Item2 = -5; j.Item1 = 0; while (1 == 1) { while (1==1) { while (reached == false) { if (timer == 1) { savedv = v; } j = Checker(v, v); v = j.Item2; timer += 1; if (j == (1, 1)) { v = savedv; reached = true; } } if (reached == true) { Console.WriteLine("The number" + " " + v + " " + "follows the sequence, and 1 was reached on a timer of" + " "+ timer +"\n" + "Total steps:"+" " + (timer-1)); v += 1; timer = 1; reached = false; } } } }
The core problem you're hitting is that Collatz(113383) has an intermediate value that surpasses Int32.MaxVaue. Here's a simpler & faster implementation to demonstrate that point; private static void Collatz() { for (ulong i = 1; ; i++) { var j = i; var steps = 0; while (j != 1) { steps++; if ((j & 1) == 0) j = j >> 1; else { j = (j << 1) + j + 1; // *3 via shifting * addition if (j >= Int32.MaxValue) break; } } if ((i%10000) == 0 || j != 1) Console.WriteLine($"{i} hit {j} after {steps} steps"); if (j != 1) break; } } Outputs; 10000 hit 1 after 29 steps 20000 hit 1 after 30 steps 30000 hit 1 after 178 steps 40000 hit 1 after 31 steps 50000 hit 1 after 127 steps 60000 hit 1 after 179 steps 70000 hit 1 after 81 steps 80000 hit 1 after 32 steps 90000 hit 1 after 164 steps 100000 hit 1 after 128 steps 110000 hit 1 after 92 steps 113383 hit 2482111348 after 120 steps
Calculating the correct length of string per line with Page X/Y
I got asked a question and now I am kicking myself for not being able to come up with the exact/correct result. Imagine we have a function that splits a string into multiple lines but each line has to have x number of characters before we "split" to the new line: private string[] GetPagedMessages(string input, int maxCharsPerLine) { ... } For each line, we need to incorporate, at the end of the line "x/y" which is basically 1/4, 2/4 etc... Now, the paging mechanism must also be part of the length restriction per line. I have been overworked and overthinking and tripping up on things and this seems pretty straight forward but for the life of me, I cannot figure it out! What am I not "getting"? What am I interested in? The calculation and some part of the logic but mainly the calculation of how many lines are required to split the input based on the max chars per line which also needs to include the x/y. Remember: we can have more than a single digit for the x/y (i.e: not just 1/4 but also 10/17 or 99/200) Samples: input = "This is a long message" maxCharsPerLine = 10 output: This i 1/4 // << Max 10 chars s a lo 2/4 // << Max 10 chars ng mes 3/4 // << Max 10 chars sage 4/4 // << Max 10 chars Overall the logic is simple but its just the calculation that is throwing me off.
The idea: First, find how many digits is the number of lines: (n = input.Length, maxCharsPerLine = 10) if n <= 9*(10-4) ==> 1 digit if n <= 9*(10-5) + 90*(10-6) ==> 2 digits if n <= 9*(10-6) + 90*(10-7) + 900*(10-8) ==> 3 digits if n <= 9*(10-7) + 90*(10-8) + 900*(10-9) + 9000*(10-10) ==> No solution Then, subtract the spare number of lines. The solution: private static int GetNumberOfLines(string input, int maxCharsPerLine) { int n = input.Length; int x = maxCharsPerLine; for (int i = 4; i < x; i++) { int j, sum = 0, d = 9, numberOfLines = 0; for (j = i; j <= i + i - 4; j++) { if (x - j <= 0) return -1; // No solution sum += d * (x - j); numberOfLines += d; d *= 10; } if (n <= sum) return numberOfLines - (sum - n) / (x - j + 1); } return -2; // Invalid } Usage: private static string[] GetPagedMessages(string input, int maxCharsPerLine) { int numberOfLines = GetNumberOfLines(input, maxCharsPerLine); if (numberOfLines < 0) return null; string[] result = new string[numberOfLines]; int spaceLeftForLine = maxCharsPerLine - numberOfLines.ToString().Length - 2; // Remove the chars of " x/y" except the incremental 'x' int inputPosition = 0; for (int line = 1; line < numberOfLines; line++) { int charsInLine = spaceLeftForLine - line.ToString().Length; result[line - 1] = input.Substring(inputPosition, charsInLine) + $" {line}/{numberOfLines}"; inputPosition += charsInLine; } result[numberOfLines-1] = input.Substring(inputPosition) + $" {numberOfLines}/{numberOfLines}"; return result; }
A naive approach is to start counting the line lengths minus the "pager"'s size, until the line count changes in size ("1/9" is shorter than "1/10", which is shorter than "11/20", and so on): private static int[] GetLineLengths(string input, int maxCharsPerLine) { /* The "pager" (x/y) is at least 4 characters (including the preceding space) and at most ... 8? * 7/9 (4) * 1/10 (5) * 42/69 (6) * 3/123 (6) * 42/420 (7) * 999/999 (8) */ int charsRemaining = input.Length; var lineLengths = new List<int>(); // Start with " 1/2", (1 + 1 + 2) = 4 length var highestLineNumberLength = 1; var lineNumber = 0; do { lineNumber++; var currentLineNumberLength = lineNumber.ToString().Length; // 1 = 1, 99 = 2, ... if (currentLineNumberLength > highestLineNumberLength) { // Pager size changed, reset highestLineNumberLength = currentLineNumberLength; lineLengths.Clear(); lineNumber = 0; charsRemaining = input.Length; continue; } var pagerSize = currentLineNumberLength + highestLineNumberLength + 2; var lineLength = maxCharsPerLine - pagerSize; if (lineLength <= 0) { throw new ArgumentException($"Can't split input of size {input.Length} into chunks of size {maxCharsPerLine}"); } lineLengths.Add(lineLength); charsRemaining -= lineLength; } while (charsRemaining > 0); return lineLengths.ToArray(); } Usage: private static string[] GetPagedMessages(string input, int maxCharsPerLine) { if (input.Length <= maxCharsPerLine) { // Assumption: no pager required for a message that takes one line return new[] { input }; } var lineLengths = GetLineLengths(input, maxCharsPerLine); var result = new string[lineLengths.Length]; // Cut the input and append the pager var previousIndex = 0; for (var i = 0; i < lineLengths.Length; i++) { var lineLength = Math.Min(lineLengths[i], input.Length - previousIndex); // To cater for final line being shorter result[i] = input.Substring(previousIndex, lineLength) + " " + (i + 1) + "/" + lineLengths.Length; previousIndex += lineLength; } return result; } Prints, for example: This 1/20 is a 2/20 long 3/20 strin 4/20 g tha 5/20 t wil 6/20 l spa 7/20 n mor 8/20 e tha 9/20 n te 10/20 n li 11/20 nes 12/20 beca 13/20 use 14/20 of i 15/20 ts e 16/20 norm 17/20 ous 18/20 leng 19/20 th 20/20
Is my method for Recursive division for my maze generator correct?
Im trying to make a maze generator using Recursive division explained here: https://en.wikipedia.org/wiki/Maze_generation_algorithm The first iteration works for me. But when I do it multiple times It doesnt do it properly. Question is: Is my recursve method corrext? The if and else statements followed up with either a return or recusion. private void DevideRecursive(int pMinX, int pMaxX, int pMinY, int pMaxY) { Debug.Log("minx: " + pMinX); Debug.Log("maxx: " + pMaxX); Debug.Log("miny: " + pMinY); Debug.Log("maxy: " + pMaxY); int randomX = Random.Range(pMinX +1, pMaxX); int randomY = Random.Range(pMinY +1, pMaxY); int randomWall = Random.Range(0, 4); List<GameObject> WalllistX1 = new List<GameObject>(); List<GameObject> WalllistX2 = new List<GameObject>(); List<GameObject> WalllistY1 = new List<GameObject>(); List<GameObject> WalllistY2 = new List<GameObject>(); List<List<GameObject>> MainWallList = new List<List<GameObject>>(); MainWallList.Add(WalllistX1); MainWallList.Add(WalllistX2); MainWallList.Add(WalllistY1); MainWallList.Add(WalllistY2); //// add a wall on a random x coordinate for (int x = pMinX; x < pMaxX; x++) { GameObject wall = Instantiate(WallHor); wall.transform.position = new Vector2(tilesize * x + tilesize / 2, tilesize * randomY); if (x < randomX) { WalllistX1.Add(wall); } else { WalllistX2.Add(wall); } } //// add a wall on a random y coordinate for (int y = pMinY; y < pMaxY ; y++) { GameObject wall = Instantiate(WallVer); wall.transform.position = new Vector2(tilesize * randomX, tilesize * y + tilesize / 2); if (y < randomY) { WalllistY1.Add(wall); } else { WalllistY2.Add(wall); } } //make a hole in 3 out of tht 4 walls randomly for (int i = 0; i < MainWallList.Count; i++) { Debug.Log("list" + MainWallList.Count); if (randomWall != i) { Debug.Log("1: " + WalllistX1.Count); Debug.Log("2: " + WalllistX2.Count); Debug.Log("3: " + WalllistY1.Count); Debug.Log("4: " + WalllistY2.Count); RemoveWall(MainWallList[i]); } } //// //// //// If either of the walls have a cell with only 1 grid stop the recursion if (randomX - pMinX <= 1 || pMaxY - randomY <= 1) { return; } else { DevideRecursive(pMinX, randomY, randomX, pMaxY); } if (pMaxX - randomX <= 1 || pMaxY - randomY <= 1) { return; } else { DevideRecursive(randomY, pMaxX, randomX, pMaxY); } if (randomX - pMinX <= 1 || randomY - pMinY <=1) { return; } else { DevideRecursive(pMinX, randomY, pMinY, randomX); } if (pMaxX - randomX <= 1 || randomY - pMinY <= 1) { return; } else { DevideRecursive(randomY, pMaxX, pMinY, randomX); } } what my code does(or is supposed to do). in a rectangular maze, build at random points two walls that are perpendicular to each other. These two walls divide the large chamber into four smaller chambers separated by four walls. Choose three of the four walls at random, and open a one cell-wide hole at a random point in each of the three. Continue in this manner recursively, until every chamber has a width of one cell in either of the two directions. here is quick illustration of the frist iteration https://gyazo.com/08e1cb2483fcf841e4d854d001c51647 for example the next iteration is going to be in the upper left room. then minX stays the same. MaxX becomes the RandomX. the same for the Y values. then it should do the same again(creating 2 walls )
Step through 2D array in hexagon pattern
I use a nested for loop to create a grid of hexagons. This creates a square grid: for (int z = 0; z < gridSize; z++) { for (int x = 0; x < gridSize; x++) { // creates verts for a hexagon shape which later form a mesh // x and z form the basis of the Vector3 position of the center // of each hexagon CreateCell(x, z); } } I've drawn the start and end values for z & x on the image. What I'd like is to have the grid itself also shaped hexagonally: I think figured out the limits for x: int greaterThan = Mathf.RoundToInt(gridSize/ 3) - 1; int lessThan = width - greaterThan; And that (I think) x should only be at it's min and max (0 & 6 in the examples) when z = gridSize / 2 rounded up, though I may well be wrong! I tried putting a bunch if IFs in the loops but it quickly started to get overly complicated, I figure there must be a more 'mathsy' way to do it, but sadly I'm not mathsy! Any idea how I can write a loop to form the required pattern?
If #AsfK's solution is not good enough, I'll give it a try as well: private static void PrintHexLine(int z, int size) { if (z >= size) { z = 2 * size - 2 - z; } int start = size - z - 1; int end = start + size + z; for (int x = 0; x < start; x++) { Console.Write(" "); } for (int x = start; x < end; x++) { Console.Write("* "); //Console.Write((x - start / 2) + " "); // position v1 //Console.Write((x - (start + 1) / 2) + " "); // position v2 } Console.WriteLine(); } public static void PrintHex(int size) { for (int z = 0; z < 2 * size - 1; z++) { PrintHexLine(z, size); } } With such code PrintHex(4) results in * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * And if you uncomment the position v1 line instead of the one that prints "* ", you'll get 2 3 4 5 1 2 3 4 5 1 2 3 4 5 6 0 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 2 3 4 5 similarly position v2 1 2 3 4 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 6 0 1 2 3 4 5 1 2 3 4 5 1 2 3 4 which looks like the x indices you want. Basing on your data I'm not really sure whether you need v1 or v2 variant. The v2 looks more consistent to me but it really depends on how your CreateCell(x, z); treats the x = 0 case. P.S. obviously you can inline PrintHexLine call but it means having two different z variables that you should not mess up with and I think it is cleaner to move that in a separate method.
According your excepted picture the center is the long row (gridSize = 7). floor(7/2) = 3 (/2 because the long row is in the center) Now, gridSize - 3 = 4 ==> 4 items in your first row Then each iterate add one till you have 7 items in one row. Then do a minus... it's the code (draw "*", not added spaces before and after..) int gridSize = 7; int center = 7/2; int delta = 1; for (int r = 0; r < gridSize; r++) { for (int c = gridSize - center; c < gridSize + delta; c++){ System.out.print("*"); // location of c = c - delta (position) } System.out.println(); if (r < center) delta++; else delta--; }
Thanks to a hint from AsfK I solved it like this int xL, xU, xMid, zM2; xL = Mathf.FloorToInt(width / 3) - 1; xU = (width - xL) + 1; xMid = Mathf.FloorToInt(width / 2); for (int z = 0; z < height; z++) { for (int x = xL; x < xU; x++) { CreateCell(x, z); } zM2 = z % 2; if(z < xMid) { if (zM2 == 0) { xL--; } if (z > 0 && zM2 == 1) { xU++; } } else { if (zM2 == 1) { xL++; } if (zM2 == 0) { xU--; } if (z == width - 1) { xL--; xU++; } } } Would be great if anyone can think of a more elegant solution!
While loop wrong output given
I have a list of Points List<Point> newcoor = new List<Point>(); and specific coordinate which is the center of the List of Points. int centerx, centery; What I want to do is add 1 with centerx and subtract 1 with centery until it reaches a combination that will match a Point inside a list. Then store that point inside an array. This is my code: List<Point> newcoor = new List<Point>(); // list of points that where the tempx and tempy will be compared to. //... Point[] vector = new Point[4]; int x = 0; while (x <= 3) { var tempx = centerx + 1; //add 1 to centerx var tempy = centerx - 1; //subtrat 1 to centery int y = 0; if (y < newcoor.Count() - 1 && newcoor[y].X == tempx && newcoor[y].Y == tempy) // compare if there is a Point in the List that is equal with the (tempx,tempy) coordinate { vector[x].X = tempx;// store the coordinates vector[x].Y = tempy; } break; // this is what I don't understand, I want to exit the loop immediately if the if-condition is true. And add 1 to x so the while loop will update. } Tried New Code: for (int y = 0; y < newcoor.Count() - 1; y++) { var tempx = centerx + 1; var tempy = centery - 1; for (int x = 0; x < newcoor.Count() - 1; x++) { if (newcoor[y].X == tempx && newcoor[y].Y == tempy) { //vectorPoints.Add(new Point(tempx,tempy)); MessageBox.Show("success"); } } } But no messagebox success shows, meaning there was no match. but there must be. All I need is 4 output that's why I have conditon while (x <= 3) Update: My centerx = 30 and centery = 28 And here is my list: What I want to do is add 1 to centerx and subtract 1 to centery from original centerx= 30 and centery= 28, it should be (31,27) (32,26) (33,25) (34,24) (35,23) <----- This should be the to the one with the same value inside my list, which is shown in the image above.
No idea what you're hoping for here, but there's several problems I can spot anyway; Firtly, tempx and tempy will be the same value on each loop, as nothing inside the loop manipulates centerx or centery. Secondly, the loop will exit on the first run, as the break statement is not inside the if {..} block. Perhaps you meant; if (y < newcoor.Count() - 1 && newcoor[y].X == tempx && newcoor[y].Y == tempy) { vector[x].X = tempx;// store the coordinates vector[x].Y = tempy; break; // <-- needs to be inside the if{..} block }