For-loop condition mechanic for Pyramid code - c#

for (int row = 0; row < 5; row++)
{
// PRINTS CORRECT NUMBER OF SPACES
for (int space = 0; space < 5 - row - 1; space++)
{
Console.Write(" ");
}
// PRINTS CORRECT NUMBER OF STARS
for (int star = 0; star < row * 2 + 1; star++)
{
Console.Write("*");
}
// JUMPS ONTO NEXT LINE AFTER EVERY ITERATION OF THE FIRST LOOP
Console.WriteLine();
}
How do the conditions "5 - row - 1", and "row * 2 + 1" work in this code?

This is all about noticing patterns in a pyramid. The comment for the first for loop says that it is printing the correct number of spaces before the actual pyramid (i.e. the asterisks).
Let's look at how many spaces there are at each level:
* level 0 - 4 spaces
*** level 1 - 3 spaces
***** level 2 - 2 spaces
******* level 3 - 1 space
********* level 4 - 0 spaces
Notice how as the level number increases, the number of spaces decreases? They are inversely proportional. What would be a function that maps the level number n into the number of spaces? It would be
f(n) = 4 - n
Or more generally,
f(n) = k - n - 1
where k is the number of levels.
This is why we wrote 5 - row - 1. It maps row (i.e. n) into the number of spaces that should be printed!
The same goes for the second for loop, which figures out how many asterisks should be printed.
* level 0 - 1 asterisks
*** level 1 - 3 asterisks
***** level 2 - 5 asterisks
******* level 3 - 7 asterisk
********* level 4 - 9 asterisks
This time the pattern is even simpler. It is just an arithmetic sequence. The function that maps the level number into the number of asterisks is
f(n) = 2 * n + 1
This explains the 2 * row + 1 in the second for loop.

Related

Can someone explain how Dmitry got the NMin math down?

The original problem is located at Project Euler Largest palindrome product and is below.
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. Find the largest palindrome made from the product of two 3-digit numbers.
The question in context is found at
Dmitry Answering Largest palindrome product - C#. I got the correct answer but did it from min to max instead of max to min so I looked for a more efficient answer to study. I understand what all the code does, but I can't figure out where Dmitry started to get the formula to get the minimum multiplicand from the maximum multiplicand constant. I'm blitzing through several coding challenge websites in preparation for some technical interviews.
This line:
const int NMin = NMax - (NMax + 1) / 10 + 1;
OF
// Store the maximum palindrome number here:
long maxNumber = 0;
// The maximum multiplicand (typically: 9...9):
const int NMax = 999;
// The minimum multiplicand.
// Obviously, it couldn't be less than 90...0:
const int NMin = NMax - (NMax + 1) / 10 + 1;
for (int i = NMax; i > NMin; i--)
{
// Starting from i since i * j = j * i for any i, j:
for (int j = i; j > NMin; j--)
{
long number = Math.BigMul(i, j);
// The fastest condition should be the first in the `if` statement:
if (number > maxNumber && isPalindome(number))
{
maxNumber = number;
Console.WriteLine("{0} = {1} * {2}", number, i, j);
break; // Leave the `j` loop, because it's guaranteed that there is
// no numbers greater than `number` for the current `i`
}
}
}
The websites I've been going through include:
Advent Of Code
HackerEarth and HackerRank
Leetcode I've been attempting to finish the Comprehensive Study Plans
Project Euler Only on Problem #4 right now
As stated in problem 4 the largest palindrome for the product of two-digit numbers is 91*99. I believe Dmitry recognized that of all max palindromes for a given digit range (3, 4, or 5 as he calculated but realistically to infinity) must be 9x -> 9y (where x represents 0's and y represents 9's). The amount of x and y needed is digit - 1 if you always want the highest palindrome. The lower 90% here is simply not worth checking for palindromes because they won't produce the highest multiplication.
Thus he can calculate the minimum every time given the equation he provided:
NMin = NMax - (NMax + 1) / 10 + 1 // NMin = 900 if NMax = 999
In the case of 4-digit palindrome, this produces 9,000 -> 9,999 or 90,000 -> 99,999 for 5.
The important thing to note here is he could have hard-coded NMin or picked a larger minimum number.

Display rows of a 2d array in reverse order

I'm working on an app that is a "poor man's matrix" ie. 1 and 0 fall down the screen.
So far I have managed to get the 2d array to display one row on 1st user input, 2 rows on 2nd user input, 3 rows on 3rd user input etc.
The problem is, that the 1st row always stays at the top and I can't get the "drop-down" effect. It always appends an additional row of 1 and 0 bellow the previous row/row on user input.
Example - how it works so far:
my 2d array:
1 0 1 0 1 1 1 (1st row)
0 1 0 1 0 1 0 (2nd row)
0 0 1 0 1 0 1 (3rd row)
1 0 0 1 0 1 0 (4th row)
1st user input (Console.ReadKey();):
1 0 1 0 1 1 1 (1st row)
2cnd user input (Console.ReadKey();):
1 0 1 0 1 1 1 (1st row)
0 1 0 1 0 1 0 (2nd row)
3rd user input:
1 0 1 0 1 1 1 (1st row)
0 1 0 1 0 1 0 (2nd row)
0 0 1 0 1 0 1 (3rd row)
etc.
What I would like to achive is something similar but in "reverse" order.
Example - what I would like to achive:
1st user input:
1 0 1 0 1 1 1 (1st row)
2cnd user input:
0 1 0 1 0 1 0 (2nd row)
1 0 1 0 1 1 1 (1st row)
3rd user input:
0 0 1 0 1 0 1 (3rd row)
0 1 0 1 0 1 0 (2nd row)
1 0 1 0 1 1 1 (1st row)
So, to summerise, I would like to modify my existing code, so that the 1st row is always added last. Or possible start reading from the end of the array - last row. I have tried this, but I constantly get outOfRange error...
Any help would be welcome.
The code that just adds additional rows below an existing one:
public static int row = 0;
static void PrintRelevantLines()
{
Console.Clear();
if (rowl <= pnms.GetLength(0) - 1)
{
for (int i = 0; i <= row; i++)
{
for (int j = 0; j <= pnms.GetLength(1) - 1; j++)
{
Console.Write(pnms[i, j]);
}
Console.WriteLine();
}
}
row += 1;
}
Edit: The anwser I requested was
for (int i = row; i >= 0; i--;)
which was provided by: Pranav Hosangadi
But I accepted the anwser from Caius Jard, as he went over and beyond what I asked for.
Thank you.
Here you go; this is a matrix effect:
int width = 60; //draw 60 columns
int height = 20; //draw 20 rows
var chars = "1234567890-=qwertyuiop[]asdfghjkl;'#zxcvbnm,./!\"£$%^&*()_+QWERTYUIOP{}ASDFGHJKL:#~ZXCVBNM<>?".ToCharArray(); //create an array of chars to randomly choose and pump onto screen
var r = new Random(); //make only one Random. Never make a Random in a loop
while (true) //forever
{
int randCol = r.Next(0, width); //pick which column we will draw now
for (int i = 0; i < height; i++) { //for every row from top to bottom
Console.SetCursorPosition(randCol, i); //put the cursor there
Console.Write(chars[r.Next(chars.Length)]); //pump a random char
Thread.Sleep(200); //it's a bit fast otherwise
}
}
I haven't out and out given the solution for your exercise, because it looks like a homework (and I don't do homework), but I hope you can step through this and look at how it's working, and make the adaptations that you need to your program to get the result you're after
Perhaps, for example, you can keep your lines in a 2D buffer, and you can decide on a column randomly (like I did), and you can render it down the screen row by row, by reading down the column (or up), writing to the screen, the same column as you selected from the buffer, then select another column
Perhaps you can periodically insert lines into the buffer (scrolling new data through it).
Perhaps also, yoou can write the char first in white, then later overwrite it in grey just before you write the new char in white (the effect is hard to see when the screen has filled up)
Then you can write multiple chars at different offsets at the same time..
..then you can give it to the peeps at codegolf.se.com and they'll write you a version in like, 15 chars of 05AB1E or something

How do I make a round robin match schedule?

I am building a tournament schedule with round robin style match order. I have an algorithm set up to build the matches, however the match order is not what I am looking for. I am struggling to develop an algorithm that will build the matches in my desired order. See example below with a 6 team bracket. Each vertical line represents a row in the tournament. The far left number represents the base team seed and who they will play in each round.
Note: The only thing that is really important to me is that the 1 and 2 seed play in the last round of the tournament. And preferably that 1 v 6, 2 v 5, 3 v 4 happens in the first round of the tournament. All other matches aren't as important. Thank you in advance for any help you can provide.
1: 6 5 4 3 2
2: 5 4 3 6 1
3: 4 6 2 1 5
4: 3 2 1 5 6
5: 2 1 6 4 3
6: 1 3 5 2 4
Here is my current code:
int numTeams = teamList.Count;
int rounds = (numTeams - 1);
int halfSize = numTeams / 2;
List<Team> teams = new List<Team>();
teams.AddRange(teamList); // Copy all the elements.
teams.RemoveAt(0); // To exclude the first team.
int teamSize = teams.Count;
for (int round = 0; round < rounds; round++)
{
int teamIdx = round % teamSize;
Team baseTeam1 = teams[teamIdx];
Team baseTeam2 = teamList[0];
// save each team to a match
for (int idx = 1; idx < halfSize; idx++)
{
int firstTeamIdx = (round + idx) % teamSize;
int secondTeamIdx = (round + teamSize - idx) % teamSize;
Team subTeam1 = teams[firstTeamIdx];
Team subTeam2 = teams[secondTeamIdx];
// save each team to a match
}
}
Sometimes asking the question helps figure out the answer. As it turns out, my current algorithm was creating what I wanted, just in opposite order. What I did to fix was create a new varible inside the first for loop called actualRound:
int actualRound = rounds - round; // this will reverse the round order

When I put a number larger than 1 in my binary-to-decimal converter, I get the error startIndex cannot be larger than length of string

I'm trying to create a program that converts a 5 digit binary number to decimal. As it stands, the conversion works perfectly, but I'm having trouble with giving an error message if the user inputs a number larger than 1.
for (int i = 4; i>=0; i--)
{
digit = txt_input.Text.Substring(i,1);
num = Convert.ToInt32(digit);
//If a digit is 1 or 0
if (num <= 1)
{
total += num * (Math.Pow(2, x));
x += 1;
goahead = 1;
}
//If a digit is not 1 or 0
if (num > 1)
{
lst_output.Items.Add("All digits must be either 1 or 0.");
i = 10;
goahead = 0;
}
}
When the user inputs 1's or 0's the program works as intended, but when a number larger than 1 is inputted, I get the error "startIndex cannot be larger than length of string" on line 3.
If a number with more or less than 5 digits is inputted, the user gets a message saying that the number must be 5 digits long. So as far as I can tell, the problem isn't the size of the startIndex. Especially since, no matter what the user inputs, startIndex remains unchanged.
Imagine your input is 10103.
Now pay attention to this part of the code:
if (num > 1)
{
lst_output.Items.Add("All digits must be either 1 or 0.");
i = 10;
goahead = 0;
}
Why are you making i = 10 here?
So if you input is the above string, in the first iteration you'd go into the if statement above, add the message to lst_output, then set i to 10. Then you go back to the for loop and the i >= 0 condition is still true so you go inside the for loop once again. Now your i = 1, but your string is of length 5.
So;
digit = txt_input.Text.Substring(i,1);
Here now you're trying to take a substring of length 1 that starts at the index = 10, from a string that is only 5 characters long.
Of course it would throw
startIndex cannot be larger than length of string.
Parameter name: startIndex.

Largest sum of upper-left quadrant of matrix that can be formed by reversing rows and columns

I'm working on a HackerRank problem that's finding the largest sum of the elements in upper-left quadrant of a 2N x 2N matrix after reversing rows and columns. For example, if the matrix is
M = [
112 42 83 119
56 125 56 49
15 78 101 43
62 98 114 108
];
then the largest sum that can be formed from reversing rows and columns is 119 + 114 + 56 + 125 = 414 after getting the matrix
M' = [
119 114 42 112
56 125 101 49
15 78 56 43
62 98 83 108
];
from reversing column 2 and then row 0.
I have not figured out an easy solution, but I have come up with some facts that might be helpful:
It is not possible to get any configuration from reversing rows and columns. Therefore, the answer cannot be to simply sort all the elements and sum the top NxN of them.
Furthermore, it is not possible to move any 1 element to any other position. For example, the only possibly places for the element at (N-1,N-1) to be moved are (0,N-1),(N-1,0),(0,0).
It requires 1 row reversal to get an element from the upper-right or bottom-left quadrant to the upper-left quadrant, and 2 reversals to get an element from the bottom-right quadrant to the upper-left quadrant.
It's not possible to come up with a solution that simply looks at each element in the upper-left quadrant and checks whether it can be replaced by a larger element in the range of elements that can be moved in it's place (e.g. M[0,1]=42 can be replaced by M[0,2]=83 or M[3,2]=114 or M[3,1]=98) because you have to also consider the other elements that get dragged along in the process.
Other than those facts, I cannot think of anything that helps me construct a simple solution. Is there any obvious fact that I am missing? I stayed up past midnight thinking about this last night. :)
Let's develop your observation about the fact that an element (N - 1, N - 1) can be only in (0, 0), (N - 1, 0) or (0, N - 1) position.
Consider an (r, c) element. One can observe that it can only be in one of the following four positions: (r, c), (N - r - 1, c), (r, N - c - 1) or (N - 1 - r, N - 1 - c)
One can show that there is always a sequence of operations that places the largest of the four numbers located in the vertices of the rectangle described above to the upper-left quadrant without changing the rest of it (to prove it, one can just consider all cases and provide an explicit construction to do it. It's quite long but straightforward, so I'll not post it here).
These two observation give the following solution:
int sum = 0;
for (int i = 0; i < n / 2; i++)
for (int j = 0; j < n / 2; j++)
sum += max(a[i][j], a[i][n - j - 1], a[n - i - 1][j], a[n - i - 1][n - j - 1]);
find the maximum upper-left-quadrant Sum value of the values of the cells,
for a square matrix.
The key point here is that every cell in a square matrix can be replaced
with only 3 other cells (by reversing a line, or a column - by transposing the matrix, reversing the line, and then transposing again),
hence to calculate (without changing the matrix) the max value of the upper-left-quadrant,
we only need to calculate the max value possible for every cell in the upper-left-quadrant.
In the (double) 'for' loop:
scanning the upper-left-quadrant cells,
fo each cell, comparing its value with the other 3 available-for-replacement values.
using '//' to receive an int ('/' will give a float)
In the following 'Sum += ..' code:
We can add the current cell [i, j] value (from the upper-left-quadrant) to the sum,
or, add other cell value, for any cell that can be replaced with [i, j] within the matrix.
Any cell in a square matrix can be replaced with only 3 other cells,
hence, we choose the max value between the cell itself and the other 3.
def maxSum(mat):
R = C = len(mat)
Sum = 0
for i in range(0, R // 2):
for j in range(0, C // 2):
r1, r2 = i, R - i - 1
c1, c2 = j, C - j - 1
Sum += max(mat[r1][c1], mat[r1][c2],
mat[r2][c1], mat[r2][c2])
return Sum
# Testing
if __name__ == "__main__":
mat = [[112, 42, 83, 119],
[56, 125, 56, 49],
[15, 78, 101, 43],
[62, 98, 114, 108]]
print(maxSum(mat)) # 414
exit()
In cases, where no shortcuts come to mind, it is always possible to delegate. Not only to stackoverflow users, but also to the CPU. I.e. brute force search.
Brute force works for this small matrix - given a depth of 4 is already more than enough and given that the branching factor of the tree is (2 * N) where N is the number or rows and columns respectively. (N rows can be reversed and N columns.)
Here, for the 4x4 matrix in the question, a respective solution:
let data =
let values =
[|
112; 42 ; 83; 119;
56 ; 125; 56; 49;
15 ; 78 ; 101; 43;
62 ; 98 ; 114; 108
|]
Array2D.init 4 4 (fun r c -> values.[4 * r + c])
let upperQuadrantSum (m : int[,]) =
[ for r in 0..1 do for c in 0..1 do yield (r,c) ]
|> List.sumBy (fun (r,c) -> m.[r,c])
let reverseRow row (m : int[,]) =
Array2D.init 4 4 (fun r c -> if r = row then m.[r,3-c] else m.[r,c])
let reverseCol col (m : int[,]) =
Array2D.init 4 4 (fun r c -> if c = col then m.[3-r,c] else m.[r,c])
let possibleActions =
[ reverseRow 0; reverseRow 1; reverseRow 2; reverseRow 3;
reverseCol 0; reverseCol 1; reverseCol 2; reverseCol 3;
]
let maximize metric maxDepth m0 =
let rec search depth m =
let value = metric m
if depth = maxDepth
then value
else
possibleActions
|> List.map (fun a -> let m1 = a m in max (metric m1) (search (depth+1) m1))
|> List.max
|> fun msearch -> max value msearch
search 0 m0
let solve = maximize upperQuadrantSum
In fsi, issuing:
solve 7 data;;
val it : int = 414
Of course, as stated in the other answer, once an optimization comes to mind,
it is nice to have the brute force solution in order to verify that both produce
the same result:
let inline solve1 m =
let n = Array2D.length1 m
let candidates r c =
[ r,c ; n-1-r,c ; r,n-1-c ; n-1-r,n-1-c ]
[
for r in 0..n/2-1 do
for c in 0..n/2-1 do
yield (candidates r c |> List.map (fun (r,c) -> m.[r,c]) |> List.max)
] |> List.sum
solve1 data
Sorry for not writing the code in C#, but a .fsx file and fsi are so much easier than creating another C# application...
LOL! I failed misserably this challenge many times by trying to come up with the algorithm to solve all the paths to the solution(kind of sneaky instructions). Here my way to solve it:
#Turn it into numpy for maximum pleasure
matrix=np.array(matrix)
#Measure its leangth
l=len(matrix)
ml=int(l/2)
#Move throught the four "corners" or "the-only-four-places-where-you-can-find-the-maximum-of-each-quadrant's-element"
max_vals = \
[
max(
matrix[i,j],
matrix[i,-(j+1)],
matrix[-(i+1),j],
matrix[-(i+1),-(j+1)]
)
for j in range(ml)
for i in range(ml)
]
#Return the sum of values
sum(max_vals)

Categories

Resources