How do I draw this tree pattern in python? - python

Given a height 1<=h<=15, how do I go about drawing this tree? I'll need to be able to traverse it later to solve some questions.
For h = 1, just the root labeled 1.
For h = 2,
3
1 2
For h = 3,
7
3 6
1 2 4 5
etc.
All that really strikes so far has been trying to find a relation from the top-down (for the left side tree, the left node will be (parent-1)/2 and the right child is parent-1 but this isn't a consistent pattern), but I can't seem to find anything . Since i need to be able to generate the tree, I'm not sure how to use a heap-structure either. I'm not sure where to start on recursion either. Any ideas are welcome.

Your tree could be drawn recursively, but here is non-recursive code.
def ruler(n):
result = 1
while not (n & 1):
n >>= 1
result += 1
return result
def printtree(h):
widthofnum = len(str(2**h - 1))
for row in range(h, 0, -1):
maxcol = 2**(h - row)
width = 2**(row-1) * (widthofnum + 1) - 1
valincr = 2**row - 2
val = valincr + 1
for col in range(1, maxcol + 1):
print(str(val).center(width), end=' ')
val += ruler(col) + valincr
print()
printtree(3)
That prints
7
3 6
1 2 4 5
while printtree(5) gives
31
15 30
7 14 22 29
3 6 10 13 18 21 25 28
1 2 4 5 8 9 11 12 16 17 19 20 23 24 26 27
The spacing may not be ideal for larger numbers, but it works. Note that each line ends in at least one space, for code simplicity. The print statement means this is Python 3.x code. This non-recursive code lets us print from top-to-bottom, left-to-right without any backtracking or storage of strings. However, that complicates the calculations involved.
One key to that code is the discrete ruler function, which can be defined as "the exponent of the largest power of 2 which divides 2n." It is more visually seen as the height of consecutive marks on an inch ruler. This determines the increases in values between numbers in a row. The rest of the code should be straightforward.

Related

how do I find a coordinates given a number in Spiral pattern? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
given a spiral of numbers in which the numbers are arranged in the form of a triangle, i need to write a function that takes a number and returns the coordinates of this number
15
16 14
17 3 13
18 4 2 12
19 5 0> 1 11
20 6 7 8 9 10
21 22 23 24 25 26 27 28
for example 17 the result is (-2, 2) in x and y
I already did a similar task, but there the spiral was square and the program received coordinates (x, y) as input and returned a number. in short, there I calculated the size of the square and the offset.
I will be glad for any help
TL;DR: Working code at the bottom
First consider how many numbers you have in each triangle:
The first contains 3 numbers in each edge
The second contains 6 numbers in each edge
The third contains 9 numbers in each edge
So there is our pattern. Triangle i contains 9i numbers and the before we do anything else we need to divide our number by 9 and find the triangle root of the result (and round it down):
Once you figure out the right triangle, there are three things left to do:
You need to find the starting point
This is trivial as the "last point" of triangle i will always be (2i, i).
You need to find the right edge
You already know that your triangle has i-long edges so by taking the sum of your remainders (from the original divmod and from rooting) and dividing it by 3 you can find the right edge.
You need to find the right point on this edge
This bit is trivial - you have 3 types of edges, horizontal, vertical and diagonal. Depending on the type you have to apply your "final residual value" to the "origin of the edge":
(-r, -r) for the diagonal
(0, r) for the vertical
(r, 0) for the horizontal
Relative to the max point of the previous triangle to get to the right edge you just have to apply a cumulative sum of these transpositions:
(-r, -r) for the diagonal
(-i, -i+r) for the vertical
(-i+r, 0) for the horizontal
Putting it all together
def triangle_root(x):
return int((8 * x + 1) ** 0.5 - 1) // 2
def spiral(v):
# Identify the current triangle
i = min(v, triangle_root(max(0, (v - 1) / 9)) + 1)
# Compute the coordinates for the max value of this triangle
xi, yi = 2 * i, i
# Compute the point index in the current triangle
# In other words, subtract the previous triangle max
r = v - 9 * (i - 1) * i // 2
# Compute the edge length for the current triangle
length = 3 * max(1, i)
# Compute the current edge and the location in that edge
edge, r = divmod(r, length)
# Apply the relevant transform depending on the edge
if edge == 1: # vertical
dx, dy = -length, r - length
elif edge == 2: # horizontal
dx, dy = r - length, 0
else: # diagonal
dx, dy = -r, -r
return xi + dx, yi + dy
No code, but I would start with something like the following:
rearrange the numbers to understand the structure of the triangle-spiral
0
1 2
3 4 5
6 7 8 9
10 11 12 13 14
15 16 17 18 19 20
21 22 23 24 25 26 27
...
Please note that if we take complete lines and arrange them back to spiral form, we will arrive at complete triangles.
Add the coordinates (I hope I understand them correctly.)
0 0 0, 0
1 1 2 1, 0 0, 1
2 3 4 5 -1, 2 -1, 1 -1, 0
3 6 7 8 9 -1,-1 0,-1 1,-1 2,-1
4 10 11 12 13 14 3,-1 2, 0 1, 1 0, 2 -1, 3
5 15 16 17 18 19 20 -2, 4 -2, 3 -2, 2 -2, 1 -2, 0 -2,-1
6 21 22 23 24 25 26 27 -2,-2 ...
...
I have also added a row number r in front: three rows form a complete "turn" in the spiral.
You can see the coordinate pattern within the rows, it depends of course on how it can be divided by 3:
rows divisible by 3 start at -r/3, -r/3 and increment x
rows with remainder 1 start at 2*(r-1)/3+1, -(r-1)/3, decrement x and increment y
rows with remainder 2 start at -(r+1)/3, 2*(r+1)/3 and decrement y
Figure out in which row we actually are
The last number n in row r is "n = {sum i for i from 0 to r+1} = (r+1)(r+2)/2". We solve this for r and arrive at:
r = -3/2 + sqrt(9/4 + 2n)
Only the positive solution is relevant.
If we insert a number n like 12, we get r = 3.6 which means we are somewhere in row 4 as expected, please check the row numbers.
Put things together
Calculate the current row number.
Calculate the position within the row by subtracting the last number of the previous row.
This is n_prev = r*(r+1)/2 in general and n_prev = 4*5/2 = 10 in the example with n=12.
The position within the row for the example is pos = 12-10 = 2
Calculate the remainder of the current row number on division by 3. For the example we have 4 = 3*1 + 1
Now calculate the coordinates by selecting the appropriate formula. For the example we have row 4, remainder 1 and position 2, so we need
[2*(r-1)/3+1, -(r-1)/3] + pos*[-1, 1] = [2*3/3+1, -3/3] + [-2,2] = [1,1]
Again, please check with your initial spiral-triangle.

Table of Squares and Cubes

I am learning Python on my own and I am stuck on a problem from a book I purchased. I can only seem to get the numbers correctly, but I cannot get the title. I was wondering if this has anything to do with the format method to make it look better? This is what I have so far:
number = 0
square = 0
cube = 0
for number in range(0, 6):
square = number * number
cube = number * number * number
print(number, square, cube)
What I am returning:
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
I would like my desired output to be this:
number square cube
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
Here we can specify the width of the digits using format in paranthesis
print('number square cube')
for x in range(0, 6):
print('{0:6d}\t {1:7d}\t {2:3d}'.format(x, x*x, x*x*x))
This would result in
number square cube
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
You need to print the header row. I used tabs \t to space the numbers our properly and f-stings because they are awesome (look them up).
number = 0
square = 0
cube = 0
# print the header
print('number\tsquare\tcube')
for number in range(0, 6):
square = number * number
cube = number * number * number
# print the rows using f-strings
print(f'{number}\t{square}\t{cube}')
Output:
number square cube
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
The only thing this doesn't do is right-align the columns, you'd have to write some custom printing function for that which determines the proper width in spaces of the columns based on each item in that column. To be honest, the output here doesn't make ANY difference and I'd focus on the utility of your code rather than what it looks like when printing to a terminal.
There is a somewhat more terse method you might consider that also uses format, as you guessed. I think this is worth learning because the Format Specification Mini-Language can be useful. Combined with f-stings, you go from eight lines of code to 3.
print('number\tsquare\tcube')
for number in range(0, 6):
print(f'{number:>6}{number**2:>8}{number**3:>6}')
The numbers here (e.g.:>6) aren't special but are just there to get you the output you desired. The > however is, forcing the number to be right-aligned within the space available.

3x3 magic square with unknown magic constant (sum)

I am trying to fill missing fields in a 3x3 matrix (square) in order to form a magic square (row, columns both diagonals sum are the same, filled with any none repeating positive integers ).
an example of such square will be like :
[_ _ _]
[_ _ 18]
[_ 28 _]
Since it doesn't follow the basic rules of the normal magic square where its integers are limited to 1-9(from 1 to n^2). , the magic constant (sum) is not equal to 15
(n(n^2+1)/2) rather it's unknown and has many possible values.
I tried a very naïve way where I generated random numbers in the empty fields with an arbitrary max of 99 then I took the whole square passed it into a function that checks if it's a valid magic square.
It basically keeps going forever till it finds the combination of numbers in the right places.
Needless to say, this solution was dumb, it keeps going for hours before it finds the answer if ever.
I also thought about doing an exhaustive number generation (basically trying every combination of numbers) till I find the right one but this faces the same issue.
So I need help figuring out an algorithm or some way to limit the range of random number generated
3 by 3 magic squares are a vector space with these three basis elements:
1 1 1 0 1 -1 -1 1 0
1 1 1 -1 0 1 1 0 -1
1 1 1 1 -1 0 0 -1 1
You can introduce 3 variables a, b, c that represent the contribution from each of the 3 basis elements, and write equations for them given your partial solution.
For example, given your example grid you'll have:
a + b - c = 18
a - b - c = 28
Which immediately gives 2b = 10 or b=-5. And a-c = 23, or c=a-23.
The space of solutions looks like this:
23 2a-28 a+5
2a-18 a 18
a-5 28 2a-23
You can see each row/column/diagonal adds up to 3a.
Now you just need to find integer solutions for a and c that satisfy your positive and non-repeating constraints.
For example, a=100, b=-5, c=77 gives:
23 172 105
182 100 18
95 28 177
The minimal sum magic square with positive integer elements occurs for a=15, and the sum is 3a=45.
23 2 20
12 15 18
10 28 7
It happens that there are no repeats here. If there were, we'd simply try the next larger value of a and so on.
A possible approach is translating the given numbers to other values. A simple division is not possible, but you can translate with (N-13)/5. Then you have a partial filled in square:
- - - 2 7 6
- - 1 for which there is a solution 9 5 1
- 3 - 4 3 8
When you translate these numbers back with (N*5)+13, you obtain:
23 48 43
58 38 18 which sums up to 114 in all directions (5 * 15) + (3 * 13)
33 28 53

How do I create a horizontal multiplication table in Python?

So far I have tried to create a table of the first 6 multiples of 2 that should give:
2 4 6 8 10 12
My code for this currently looks like:
i = 1
while i <= 6:
print(2*i ,' \t' , )
i = i + 1
But this outputs them vertically, not horizontally so:
2
4
6
8
10
12
There is also a tab after each number.
You can use a simple for-loop as they are more Pythonic for this application than while loops.
So just loop through the numbers between 1 and 6 and print that number multiplied by 2 with a space instead of the new-line character. Finally, you can call one more print at the end to move to the next line after they have all been printed.
for i in range(1, 7):
print(i * 2, end=' ')
print()
which outputs:
2 4 6 8 10 12
If you wanted do this whole thing in one-line, you could use a generator and string.join(). You may not fully understand this, but the following produces the same result:
print(" ".join(str(i*2) for i in range(1, 7)))
which gives:
2 4 6 8 10 12
Note that one last thing is that this method doesn't produce a uniformly spaced table. To show what I mean by "uniformly spaced", here are some examples:
not uniformly spaced:
1234 1 123 12 12312 123
uniformly spaced:
1234 1 123 12 12312 123
To make the output print nicely like above, we can use .ljust:
print("".join(str(i*2).ljust(3) for i in range(1, 7)))
which gives a nicer table:
2 4 6 8 10 12
Finally, if you wanted to make this into a function that is more general purpose, you could do:
def tbl(num, amnt):
print("".join(str(i*num).rjust(len(str(num*amnt))+1) for i in range(1,amnt+1)))
and some examples of this function:
>>> tbl(3, 10)
3 6 9 12 15 18 21 24 27 30
>>> tbl(9, 5)
9 18 27 36 45
>>> tbl(10, 10)
10 20 30 40 50 60 70 80 90 100
Change your print statement to be like this: print(2*i, end=' \t') The end key argument sets what the ending character should be. By default, it's a newline, as you know.

Can anyone help me figure out the parsing error in this code?

The output of this code is quite similar but not exactly what it's supposed to be.
The code is:
def printMultiples(n):
i = 1
while (i <= 10):
print(n*i, end = ' ')
i += 1
n = 1
while (i<= 3):
printMultiples(n)
n += 1
The output is:
1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30
Whereas it should be like:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
How should this code be modified?
add an empty print at the end of the printMultiples, outside the while (i <= 10): loop.
Your problem is that you are not printing a new line after each list of multiples. You could solve this by putting at the end of your printMultiples function outside of the loop the line
print()
To make the columns line up, you will need to completely change your approach. Currently, printMultiples() cannot know how many spaces to put after each number because it doesn't know how many times it will be called in the outer while loop.
What you might do is:
create a two dimensional array of string representations for each multiple (without printing anything yet) - the str() function will be useful for this
for each column, check the length of the longest number in that column (it will always be the last one) and add one
print each row, adding the appropriate number of spaces after each string to match the number of spaces required for that column
A simpler approach, if you're only interested in columnar output and not the precise spacing, would be to print each number with enough space after it to accommodate the largest number you expect to output. So you might get:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
(Note how there are three spaces after each number in the first three columns even though you don't need all three spaces.)
Changing your existing code to do that would be easier. See Format String Syntax for details.
If you already know you wish to pad numbers to be of width 3, then a suitable (and more pythonic) printMultiples is
def printMultiples(n):
txt = "".join(["{0: <3d}".format(n*i) for i in range(1, 11)])
print(txt)
Better would be to allow the width to change. And you could then pass a width you prefer as, eg, the width of the largest number you expect
def printMultiples(n, width=3):
txt = "".join(["{0: <{1}d}".format(n*i, width) for i in range(1, 11)])
print(txt)
width = len(str(4 * 10)) + 1
for i in range(1, 4):
printMultiples(i, width )

Categories

Resources