I want to print my binary tree in the following manner:
10
6 12
5 7 11 13
I have written code for insertion of nodes but can't able to write for printing the tree. so please help on this . My code is :
class Node:
def __init__(self,data):
self.data=data
self.left=None
self.right=None
self.parent=None
class binarytree:
def __init__(self):
self.root=None
self.size=0
def insert(self,data):
if self.root==None:
self.root=Node(data)
else:
current=self.root
while 1:
if data < current.data:
if current.left:
current=current.left
else:
new=Node(data)
current.left=new
break;
elif data > current.data:
if current.right:
current=current.right
else:
new=Node(data)
current.right=new
break;
else:
break
b=binarytree()
Here's my attempt, using recursion, and keeping track of the size of each node and the size of children.
class BstNode:
def __init__(self, key):
self.key = key
self.right = None
self.left = None
def insert(self, key):
if self.key == key:
return
elif self.key < key:
if self.right is None:
self.right = BstNode(key)
else:
self.right.insert(key)
else: # self.key > key
if self.left is None:
self.left = BstNode(key)
else:
self.left.insert(key)
def display(self):
lines, *_ = self._display_aux()
for line in lines:
print(line)
def _display_aux(self):
"""Returns list of strings, width, height, and horizontal coordinate of the root."""
# No child.
if self.right is None and self.left is None:
line = '%s' % self.key
width = len(line)
height = 1
middle = width // 2
return [line], width, height, middle
# Only left child.
if self.right is None:
lines, n, p, x = self.left._display_aux()
s = '%s' % self.key
u = len(s)
first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s
second_line = x * ' ' + '/' + (n - x - 1 + u) * ' '
shifted_lines = [line + u * ' ' for line in lines]
return [first_line, second_line] + shifted_lines, n + u, p + 2, n + u // 2
# Only right child.
if self.left is None:
lines, n, p, x = self.right._display_aux()
s = '%s' % self.key
u = len(s)
first_line = s + x * '_' + (n - x) * ' '
second_line = (u + x) * ' ' + '\\' + (n - x - 1) * ' '
shifted_lines = [u * ' ' + line for line in lines]
return [first_line, second_line] + shifted_lines, n + u, p + 2, u // 2
# Two children.
left, n, p, x = self.left._display_aux()
right, m, q, y = self.right._display_aux()
s = '%s' % self.key
u = len(s)
first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s + y * '_' + (m - y) * ' '
second_line = x * ' ' + '/' + (n - x - 1 + u + y) * ' ' + '\\' + (m - y - 1) * ' '
if p < q:
left += [n * ' '] * (q - p)
elif q < p:
right += [m * ' '] * (p - q)
zipped_lines = zip(left, right)
lines = [first_line, second_line] + [a + u * ' ' + b for a, b in zipped_lines]
return lines, n + m + u, max(p, q) + 2, n + u // 2
import random
b = BstNode(50)
for _ in range(50):
b.insert(random.randint(0, 100))
b.display()
Example output:
__50_________________________________________
/ \
________________________43_ ________________________99
/ \ /
_9_ 48 ____________67_____________________
/ \ / \
3 11_________ 54___ ______96_
/ \ \ \ / \
0 8 ____26___________ 61___ ________88___ 97
/ \ / \ / \
14_ __42 56 64_ 75_____ 92_
/ \ / / \ / \ / \
13 16_ 33_ 63 65_ 72 81_ 90 94
\ / \ \ / \
25 __31 41 66 80 87
/ /
28_ 76
\
29
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def printTree(node, level=0):
if node != None:
printTree(node.left, level + 1)
print(' ' * 4 * level + '-> ' + str(node.value))
printTree(node.right, level + 1)
t = Node(1, Node(2, Node(4, Node(7)),Node(9)), Node(3, Node(5), Node(6)))
printTree(t)
output:
-> 7
-> 4
-> 2
-> 9
-> 1
-> 5
-> 3
-> 6
What you're looking for is breadth-first traversal, which lets you traverse a tree level by level. Basically, you use a queue to keep track of the nodes you need to visit, adding children to the back of the queue as you go (as opposed to adding them to the front of a stack). Get that working first.
After you do that, then you can figure out how many levels the tree has (log2(node_count) + 1) and use that to estimate whitespace. If you want to get the whitespace exactly right, you can use other data structures to keep track of how many spaces you need per level. A smart estimation using number of nodes and levels should be enough, though.
I am leaving here a stand-alone version of #J. V.'s code. If anyone wants to grab his/her own binary tree and pretty print it, pass the root node and you are good to go.
If necessary, change val, left and right parameters according to your node definition.
def print_tree(root, val="val", left="left", right="right"):
def display(root, val=val, left=left, right=right):
"""Returns list of strings, width, height, and horizontal coordinate of the root."""
# No child.
if getattr(root, right) is None and getattr(root, left) is None:
line = '%s' % getattr(root, val)
width = len(line)
height = 1
middle = width // 2
return [line], width, height, middle
# Only left child.
if getattr(root, right) is None:
lines, n, p, x = display(getattr(root, left))
s = '%s' % getattr(root, val)
u = len(s)
first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s
second_line = x * ' ' + '/' + (n - x - 1 + u) * ' '
shifted_lines = [line + u * ' ' for line in lines]
return [first_line, second_line] + shifted_lines, n + u, p + 2, n + u // 2
# Only right child.
if getattr(root, left) is None:
lines, n, p, x = display(getattr(root, right))
s = '%s' % getattr(root, val)
u = len(s)
first_line = s + x * '_' + (n - x) * ' '
second_line = (u + x) * ' ' + '\\' + (n - x - 1) * ' '
shifted_lines = [u * ' ' + line for line in lines]
return [first_line, second_line] + shifted_lines, n + u, p + 2, u // 2
# Two children.
left, n, p, x = display(getattr(root, left))
right, m, q, y = display(getattr(root, right))
s = '%s' % getattr(root, val)
u = len(s)
first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s + y * '_' + (m - y) * ' '
second_line = x * ' ' + '/' + (n - x - 1 + u + y) * ' ' + '\\' + (m - y - 1) * ' '
if p < q:
left += [n * ' '] * (q - p)
elif q < p:
right += [m * ' '] * (p - q)
zipped_lines = zip(left, right)
lines = [first_line, second_line] + [a + u * ' ' + b for a, b in zipped_lines]
return lines, n + m + u, max(p, q) + 2, n + u // 2
lines, *_ = display(root, val, left, right)
for line in lines:
print(line)
print_tree(root)
__7
/ \
___10_ 3
/ \
_19 13
/ \
9 8_
/ \ \
4 0 12
Simple solution with no recursion
def PrintTree(root):
def height(root):
return 1 + max(height(root.left), height(root.right)) if root else -1
nlevels = height(root)
width = pow(2,nlevels+1)
q=[(root,0,width,'c')]
levels=[]
while(q):
node,level,x,align= q.pop(0)
if node:
if len(levels)<=level:
levels.append([])
levels[level].append([node,level,x,align])
seg= width//(pow(2,level+1))
q.append((node.left,level+1,x-seg,'l'))
q.append((node.right,level+1,x+seg,'r'))
for i,l in enumerate(levels):
pre=0
preline=0
linestr=''
pstr=''
seg= width//(pow(2,i+1))
for n in l:
valstr= str(n[0].val)
if n[3]=='r':
linestr+=' '*(n[2]-preline-1-seg-seg//2)+ '¯'*(seg +seg//2)+'\\'
preline = n[2]
if n[3]=='l':
linestr+=' '*(n[2]-preline-1)+'/' + '¯'*(seg+seg//2)
preline = n[2] + seg + seg//2
pstr+=' '*(n[2]-pre-len(valstr))+valstr #correct the potition acording to the number size
pre = n[2]
print(linestr)
print(pstr)
Sample output
1
/¯¯¯¯¯¯ ¯¯¯¯¯¯\
2 3
/¯¯¯ ¯¯¯\ /¯¯¯ ¯¯¯\
4 5 6 7
/¯ ¯\ /¯ /¯
8 9 10 12
I enhanced Prashant Shukla answer to print the nodes on the same level in the same line without spaces.
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def __str__(self):
return str(self.value)
def traverse(root):
current_level = [root]
while current_level:
print(' '.join(str(node) for node in current_level))
next_level = list()
for n in current_level:
if n.left:
next_level.append(n.left)
if n.right:
next_level.append(n.right)
current_level = next_level
t = Node(1, Node(2, Node(4, Node(7)), Node(9)), Node(3, Node(5), Node(6)))
traverse(t)
Just use this small method of print2DTree:
class bst:
def __init__(self, value):
self.value = value
self.right = None
self.left = None
def insert(root, key):
if not root:
return bst(key)
if key >= root.value:
root.right = insert(root.right, key)
elif key < root.value:
root.left = insert(root.left, key)
return root
def insert_values(root, values):
for value in values:
root = insert(root, value)
return root
def print2DTree(root, space=0, LEVEL_SPACE = 5):
if (root == None): return
space += LEVEL_SPACE
print2DTree(root.right, space)
# print() # neighbor space
for i in range(LEVEL_SPACE, space): print(end = " ")
print("|" + str(root.value) + "|<")
print2DTree(root.left, space)
root = insert_values(None, [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15])
print2DTree(root)
Results:
code Explanation:
by using the BFS get the lists of list contains elements of each level
number of white spaces at any level = (max number of element in tree)//2^level
maximum number of elements of h height tree = 2^h -1; considering root level height as 1
print the value and white spaces
find my Riple.it link here print-bst-tree
def bfs(node,level=0,res=[]):
if level<len(res):
if node:
res[level].append(node.value)
else:
res[level].append(" ")
else:
if node:
res.append([node.value])
else:
res.append([" "])
if not node:
return
bfs(node.left,level+1,res)
bfs(node.right,level+1,res)
return res
def printTree(node):
treeArray = bfs(node)
h = len(treeArray)
whiteSpaces = (2**h)-1
def printSpaces(n):
for i in range(n):
print(" ",end="")
for level in treeArray:
whiteSpaces = whiteSpaces//2
for i,x in enumerate(level):
if i==0:
printSpaces(whiteSpaces)
print(x,end="")
printSpaces(1+2*whiteSpaces)
print()
#driver Code
printTree(root)
#output
class magictree:
def __init__(self, parent=None):
self.parent = parent
self.level = 0 if parent is None else parent.level + 1
self.attr = []
self.rows = []
def add(self, value):
tr = magictree(self)
tr.attr.append(value)
self.rows.append(tr)
return tr
def printtree(self):
def printrows(rows):
for i in rows:
print("{}{}".format(i.level * "\t", i.attr))
printrows(i.rows)
printrows(self.rows)
tree = magictree()
group = tree.add("company_1")
group.add("emp_1")
group.add("emp_2")
emp_3 = group.add("emp_3")
group = tree.add("company_2")
group.add("emp_5")
group.add("emp_6")
group.add("emp_7")
emp_3.add("pencil")
emp_3.add("pan")
emp_3.add("scotch")
tree.printtree()
result:
['company_1']
['emp_1']
['emp_2']
['emp_3']
['pencil']
['pan']
['scotch']
['company_2']
['emp_5']
['emp_6']
['emp_7']
As I came to this question from Google (and I bet many others did too), here is binary tree that has multiple children, with a print function (__str__ which is called when doing str(object_var) and print(object_var)).
Code:
from typing import Union, Any
class Node:
def __init__(self, data: Any):
self.data: Any = data
self.children: list = []
def insert(self, data: Any):
self.children.append(Node(data))
def __str__(self, top: bool=True) -> str:
lines: list = []
lines.append(str(self.data))
for child in self.children:
for index, data in enumerate(child.__str__(top=False).split("\n")):
data = str(data)
space_after_line = " " * index
if len(lines)-1 > index:
lines[index+1] += " " + data
if top:
lines[index+1] += space_after_line
else:
if top:
lines.append(data + space_after_line)
else:
lines.append(data)
for line_number in range(1, len(lines) - 1):
if len(lines[line_number + 1]) > len(lines[line_number]):
lines[line_number] += " " * (len(lines[line_number + 1]) - len(lines[line_number]))
lines[0] = " " * int((len(max(lines, key=len)) - len(str(self.data))) / 2) + lines[0]
return '\n'.join(lines)
def hasChildren(self) -> bool:
return bool(self.children)
def __getitem__(self, pos: Union[int, slice]):
return self.children[pos]
And then a demo:
# Demo
root = Node("Languages Good For")
root.insert("Serverside Web Development")
root.insert("Clientside Web Development")
root.insert("For Speed")
root.insert("Game Development")
root[0].insert("Python")
root[0].insert("NodeJS")
root[0].insert("Ruby")
root[0].insert("PHP")
root[1].insert("CSS + HTML + Javascript")
root[1].insert("Typescript")
root[1].insert("SASS")
root[2].insert("C")
root[2].insert("C++")
root[2].insert("Java")
root[2].insert("C#")
root[3].insert("C#")
root[3].insert("C++")
root[0][0].insert("Flask")
root[0][0].insert("Django")
root[0][1].insert("Express")
root[0][2].insert("Ruby on Rails")
root[0][0][0].insert(1.1)
root[0][0][0].insert(2.1)
print(root)
This is part of my own implementation of BST. The ugly part of this problem is that you have to know the space that your children occupies before you can print out yourself. Because you can have very big numbers like 217348746327642386478832541267836128736..., but also small numbers like 10, so if you have a parent-children relationship between these two, then it can potentially overlap with your other child. Therefore, we need to first go through the children, make sure we get how much space they are having, then we use that information to construct ourself.
def __str__(self):
h = self.getHeight()
rowsStrs = ["" for i in range(2 * h - 1)]
# return of helper is [leftLen, curLen, rightLen] where
# leftLen = children length of left side
# curLen = length of keyStr + length of "_" from both left side and right side
# rightLen = children length of right side.
# But the point of helper is to construct rowsStrs so we get the representation
# of this BST.
def helper(node, curRow, curCol):
if(not node): return [0, 0, 0]
keyStr = str(node.key)
keyStrLen = len(keyStr)
l = helper(node.l, curRow + 2, curCol)
rowsStrs[curRow] += (curCol -len(rowsStrs[curRow]) + l[0] + l[1] + 1) * " " + keyStr
if(keyStrLen < l[2] and (node.r or (node.p and node.p.l == node))):
rowsStrs[curRow] += (l[2] - keyStrLen) * "_"
if(l[1]):
rowsStrs[curRow + 1] += (len(rowsStrs[curRow + 2]) - len(rowsStrs[curRow + 1])) * " " + "/"
r = helper(node.r, curRow + 2, len(rowsStrs[curRow]) + 1)
rowsStrs[curRow] += r[0] * "_"
if(r[1]):
rowsStrs[curRow + 1] += (len(rowsStrs[curRow]) - len(rowsStrs[curRow + 1])) * " " + "\\"
return [l[0] + l[1] + 1, max(l[2] - keyStrLen, 0) + keyStrLen + r[0], r[1] + r[2] + 1]
helper(self.head, 0, 0)
res = "\n".join(rowsStrs)
#print("\n\n\nStart of BST:****************************************")
#print(res)
#print("End of BST:****************************************")
#print("BST height: ", h, ", BST size: ", self.size)
return res
Here's some examples of running this:
[26883404633, 10850198033, 89739221773, 65799970852, 6118714998, 31883432186, 84275473611, 25958013736, 92141734773, 91725885198, 131191476, 81453208197, 41559969292, 90704113213, 6886252839]
26883404633___________________________________________
/ \
10850198033__ 89739221773___________________________
/ \ / \
6118714998_ 25958013736 65799970852_______________ 92141734773
/ \ / \ /
131191476 6886252839 31883432186_ 84275473611 91725885198
\ / /
41559969292 81453208197 90704113213
Another example:
['rtqejfxpwmggfro', 'viwmdmpedzwvvxalr', 'mvvjmkdcdpcfb', 'ykqehfqbpcjfd', 'iuuujkmdcle', 'nzjbyuvlodahlpozxsc', 'wdjtqoygcgbt', 'aejduciizj', 'gzcllygjekujzcovv', 'naeivrsrfhzzfuirq', 'lwhcjbmcfmrsnwflezxx', 'gjdxphkpfmr', 'nartcxpqqongr', 'pzstcbohbrb', 'ykcvidwmouiuz']
rtqejfxpwmggfro____________________
/ \
mvvjmkdcdpcfb_____________________________ viwmdmpedzwvvxalr_______________
/ \ \
iuuujkmdcle_________ nzjbyuvlodahlpozxsc_ ykqehfqbpcjfd
/ \ / \ /
aejduciizj_____________ lwhcjbmcfmrsnwflezxx naeivrsrfhzzfuirq_ pzstcbohbrb wdjtqoygcgbt_
\ \ \
gzcllygjekujzcovv nartcxpqqongr ykcvidwmouiuz
/
gjdxphkpfmr
Here's a 2-pass solution with no recursion for general binary trees where each node has a value that "fits" within the allotted space (values closer to the root have more room to spare). (Pass 0 computes the tree height).
'''
0: 0
1: 1 2
2: 3 4 5 6
3: 7 8 9 a b c d e
h: 4
N: 2**4 - 1 <--| 2**0 + 2**1 + 2**2 + 2**3
'''
import math
def t2_lvl( i): return int(math.log2(i+1)) if 0<i else 0 # #meta map the global idx to the lvl
def t2_i2base(i): return (1<<t2_lvl(i))-1 # #meta map the global idx to the local idx (ie. the idx of elem 0 in the lvl at idx #i)
def t2_l2base(l): return (1<< l) -1 # #meta map the lvl to the local idx (ie. the idx of elem 0 in lvl #l)
class Tree2: # #meta a 2-tree is a tree with at most 2 sons per dad
def __init__(self, v=None):
self.v = v
self.l = None
self.r = None
def __str__(self): return f'{self.v}'
def t2_show(tree:Tree2): # #meta 2-pass fn. in the 1st pass we compute the height
if not tree: return
q0 = [] # perm queue
q1 = [] # temp queue
# pass 0
h = 0 # height is the number of lvls
q0.append((tree,0))
q1.append((tree,0))
while q1:
n,i = q1.pop(0)
h = max(h, t2_lvl(i))
if n.l: l=(n.l, 2*i+1); q0.append(l); q1.append(l)
if n.r: r=(n.r, 2*i+2); q0.append(r); q1.append(r)
h += 1 # nlvls
N = 2**h - 1 # nelems (for a perfect tree of this height)
W = 1 # elem width
# pass 1
print(f'\n\x1b[31m{h} \x1b[32m{len(q0)}\x1b[0m')
print(f'{0:1x}\x1b[91m:\x1b[0m',end='')
for idx,(n,i) in enumerate(q0):
l = t2_lvl(i) # lvl
b = (1<<l)-1 # base
s0 = (N // (2**(l+1)))
s1 = (N // (2**(l+0)))
s = 3+1 + s0 + (i-b)*(s1+1) # absolute 1-based position (from the beginning of line)
w = int(2**(h-l-2)) # width (around the element) (to draw the surrounding #-)
# print(f'{i:2x} {l} {i-b} {s0:2x} {s1:2x} {s:2x} {w:x} {n.v:02x}')
if 0<idx and t2_lvl(q0[idx-1][1])!=l: print(f'\n{l:1x}\x1b[91m:\x1b[0m',end='') # new level: go to the next line
print(f"\x1b[{s-w}G{w*'-'}\x1b[1G", end='')
print(f"\x1b[{s}G{n.v:1x}\x1b[1G", end='') # `\x1b[XG` is an ANSI escape code that moves the cursor to column X
print(f"\x1b[{s+W}G{w*'-'}\x1b[1G", end='')
print()
And an example:
tree = Tree2(0)
tree.l = Tree2(1)
tree.r = Tree2(2)
tree.l.l = Tree2(3)
tree.r.l = Tree2(4)
tree.r.r = Tree2(5)
tree.l.l.l = Tree2(3)
tree.r.l.l = Tree2(6)
tree.r.l.r = Tree2(7)
tree.l.l.l.l = Tree2(3)
tree.r.l.l.l = Tree2(8)
tree.r.l.l.r = Tree2(9)
t2_show(tree)
Output:
5 12
0: --------0--------
1: ----1---- ----2----
2: --3-- --4-- --5--
3: -3- -6- -7-
4: 3 8 9
Another output example:
7 127
0: --------------------------------0--------------------------------
1: ----------------1---------------- ----------------2----------------
2: --------3-------- --------4-------- --------5-------- --------6--------
3: ----7---- ----8---- ----9---- ----a---- ----b---- ----c---- ----d---- ----e----
4: --f-- --0-- --1-- --2-- --3-- --4-- --5-- --6-- --7-- --8-- --9-- --a-- --b-- --c-- --d-- --e--
5: -f- -0- -1- -2- -3- -4- -5- -6- -7- -8- -9- -a- -b- -c- -d- -e- -f- -0- -1- -2- -3- -4- -5- -6- -7- -8- -9- -a- -b- -c- -d- -e-
6: f 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e
Record Each Level Separately using Breadth First Approach
You can use a breadth first traversal and record node values in a dictionary using level as key. This helps next when you want to print each level in a new line. If you maintain a count of nodes processed, you can find current node's level (since it's a binary tree) using -
level = math.ceil(math.log(count + 1, 2) - 1)
Sample Code
Here's my code using the above method (along with some helpful variables like point_span & line_space which you can modify as you like). I used my custom Queue class, but you can also use a list for maintaining queue.
def pretty_print(self):
q, current, count, level, data = Queue(), self.root, 1, 0, {}
while current:
level = math.ceil(math.log(count + 1, 2) - 1)
if data.get(level) is None:
data[level] = []
data[level].append(current.value)
count += 1
if current.left:
q.enqueue(current.left)
if current.right:
q.enqueue(current.right)
current = q.dequeue()
point_span, line_space = 8, 4
line_width = int(point_span * math.pow(2, level))
for l in range(level + 1):
current, string = data[l], ''
for c in current:
string += str(c).center(line_width // len(current))
print(string + '\n' * line_space)
And here's how the output looks:
Similar question is being answered over here This may help following code will print in this format
>>>
1
2 3
4 5 6
7
>>>
Code for this is as below :
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
a = ' '
while thislevel:
nextlevel = list()
a = a[:len(a)/2]
for n in thislevel:
print a+str(n.value),
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7)),Node(9)), Node(3, Node(5), Node(6)))
traverse(t)
Edited code gives result in this format :
>>>
1
2 3
4 9 5 6
7
>>>
This is just a trick way to do what you want their maybe a proper method for that I suggest you to dig more into it.
Related
I've been puking trying to understand reversing a linked list with incursion:
class LinkedList:
def __init__(self):
self.head = None # Head of list
# Method to reverse the list
def reverse(self, head):
# If head is empty or has reached the list end
if head is None or head.next is None:
return head
# Reverse the rest list
rest = self.reverse(head.next)
# Put first element at the end
head.next.next = head
head.next = None
# Fix the header pointer
return rest
So I start with a simple recursion like
def sum(x):
if x == 1:
print("at x = ", x, "k = ", 2.5)
return 2.5
else:
k = x * sum(x-1)
k +=1.5
print("with x =", x, "we have k =",k)
return k
sum(6)
I thought the steps will begin from 6 downwards:
k = 6 * 5 + 1.5
k = ((6 * 5) + 1.5) * 4 + 1.5)
k = ((6 * 5) + 1.5) * 4 + 1.5) * 3 + 1.5
k = ((6 * 5) + 1.5) * 4 + 1.5) * 3 + 1.5) * 2 + 1.5
k = ((6 * 5) + 1.5) * 4 + 1.5) * 3 + 1.5) * 2 + 1.5) * 2.5
But in fact it's the other way around:
at x = 1 k = 2.5
with x = 2 we have k = 6.5
with x = 3 we have k = 21.0
with x = 4 we have k = 85.5
with x = 5 we have k = 429.0
with x = 6 we have k = 2575.5
2575.5
So if that's how recursion works, coming back to the reversing linked-list with recursion, supposing we have a linked list:
1 --> 2 --> 3 --> 4 --> 5 --> 6 --> None.
I understand that when:
* head.next = 6 -> rest = self.reverse(6) -> head.next (6.next) is None then return 5.
* head.next.next (6.next.next) = 5.
* head.next (5.next) = None
So we have 6 --> 5 --> None. Then will work all the way back to 1 --> None?
I am want to replace a specific part of the string while using textwrap. But I am getting an unwanted line break. I have tried a lot of ways but still, it is not working. here is my code.
import textwrap
import math
def wrap(string, max_width):
wrapper = textwrap.TextWrapper(width = max_width)
word_list = wrapper.fill(text = string)
return word_list
height, width = map(int,input().split())
square = height * width
i = 0
x = []
while i < square:
x.append("-")
i += 1
k = 0
while k < math.floor(height / 2):
line = math.floor(width / 2) + width * k
x[line] = '|'
x[line + 1]= "."
x[line - 1] = "."
for h in range(1, k + 1):
f = h * 3
line_plus = line + f
line_minus = line - f
x[line_plus] = '|'
x[line_minus] = '|'
x[line_minus - 1] = '.'
x[line_plus - 1] = '.'
x[line_minus + 1] = '.'
q = line_plus + 1
x[q] = '.'
k += 1
a = 0
while a < math.floor(height / 2):
line = math.floor(width / 2) + width * a
line_end = (math.floor(width / 2) + width * a) * (-1)
x[line_end - 1] = '|'
if line > width:
x[line_end + 2] = '|'
x[line_end - 4] = '|'
a += 1
listToStr = ''.join([str(elem) for elem in x])
welcome_pos = math.floor(height / 2) * width + (math.floor(width / 2) - math.floor(7 / 2))
s = listToStr[ 0: welcome_pos] + "welcome" + listToStr[welcome_pos + 7:]
print(wrap(listToStr, width) + "\n")
print(wrap(s, width))
my input is 7 21
Output:
---------.|.---------
------.|..|..|.------
---.|..|..|..|..|.
----------welcome----
----------|--|--|----
----------|--|--|----
-------------|-------
---
this is my output. But it is giving a space at line 3 which I don't want. I don't know why this is happening. Please help me.
Maybe this is what you want?
code:
#(above the same)
print(wrap(listToStr,width*height))
print(wrap(s,width*height))
result:
5 4
-..|..|..||--|--||--
-..|..|welcome--||--
Project Euler Problem 15
Starting in the top left corner of a 2×2 grid, there are 6 routes (without backtracking) to the bottom right corner.
How many routes are there through a 20×20 grid?
Start from the bottom right and go up by adding top and left numbers
table = {}
table["01"] = 1
table["10"] = 1
def find_cost(x, y):
top_pos = str(x) + str(y - 1)
left_pos = str(x - 1) + str(y)
current_pos = str(x) + str(y)
if top_pos in table and left_pos in table: # if it's in a table then add it
table[current_pos] = table[left_pos] + table[top_pos]
return table[current_pos]
elif x == 1: # if the leftmost, then add 1 in a table
table[left_pos] = 1
table[current_pos] = 1 + find_cost(x, y - 1)
return table[current_pos]
elif y == 1: # the same for y
table[top_pos] = 1
table[current_pos] = 1 + table[left_pos]
return table[current_pos]
else: # if I don't have anything, then call it for left and top
table[current_pos] = find_cost(x - 1, y) + find_cost(x, y - 1)
return table[current_pos]
Hint: to which cell corresponds table["123"]? To x = 1 and y = 23 or x = 12 and y = 3?
You need to be able to identify cells uniquely from the key of the table. So try to construct the key with a separator, for example:
top_pos = str(x) + ":" + str(y - 1)
left_pos = str(x - 1) + ":" + str(y)
current_pos = str(x) + ":" + str(y)
and initialize it like
table["0:1"] = 1
table["1:0"] = 1
It works as some of you suggested, but now I'm getting a bunch of new errors.
What I am trying to do is trying to read the initial coordinates of the polymer chain from as csv file, which looks like following:
-0.350000 , 0.000000 , 0.000000 \
-0.007593 , 0.075808 , 0.540372 \
-0.134408 , 0.115877 , 1.384276
In my code, I have to polymer chains that are separated by some distance and I want to have their initial coordinates from the data file.
Here is the error message:
Here is now complete of code:
#Define an object called 'monomer' which consists of a position (list with 3 entries)
class monomer:
def __init__(self, pos):
# assign the given position to the 'pos' attribute
self.pos = pos
#self.m = np.loadtxt('traj_T_4.csv')
#classmethod
def from_file(cls, filename):
instances = []
with open(filename, 'r') as file:
for line in file:
pos = str(map(float, line.split(',')))
instances.append(cls(pos))
return instances
def LJ(self, other):
# Define the LJ interaction between one and another monomer
# Calculate the distance between position of one and the other monomer
rij =self.distance(other)
sig_by_r6 = np.power(sigma**2 / rij, 6)
sig_by_r12 = np.power(sigma**2 / rij, 12)
return 4*epsilon*(sig_by_r12 - sig_by_r6)
def FENE(self, other):
rij =self.distance(other)
fene = (-0.5 * K * np.power(R,2) * np.log(1 - ((np.sqrt(rij) - r0) / R)**2))
if not np.isfinite(fene): # Make sure, that NaN (or - infinity) values (because of the log) are never passed to the energy calculation, as the programme behaves uncontrollably then
return float("inf") # Rather return infinity, since this will always fail the energy comparison
else:
return fene
def distance(self, other):
return np.linalg.norm(list(np.array(self.pos) - np.array(other.pos)))
def shift(self, vector):
# Move a monomer by 'vector'
self.pos += vector
# Define an object called 'polymer', which is a chain (list) of monomer objects
class polymer:
def __init__(self, base, N):
self.chain = []
# append each monomer to the polymer's chain
# base (list of 2) represents the initial x and y value of all monomers
for i in range(N):
self.chain.append( monomer([base[0], base[1], i*0.7]) )
def FENE_Energy(self):
# Define polymer FENE energy as sum of FENE interactions between bonded monomers
fene = 0.0
for i in range(N-1):
fene += self.chain[i].FENE(self.chain[i+1])
return fene
def LJ_Energy(self):
LJ = 0.0
for i in range(N):
for j in range(N):
if np.absolute(i-j) > 1 and self.chain[i].distance(self.chain[j]) < rcutoff: # LJ only for non-bonded monomers, i.e. distance is greater than 1
LJ += self.chain[i].LJ(self.chain[j])
return LJ/2.
def Energy(self):
return self.LJ_Energy() + self.FENE_Energy()
def end_to_end_dist(self):
"""
Figure it out! It is not correct
"""
R = 0.0
for i in range(N):
R = np.linalg.norm(self.chain[i].pos[0] - self.chain[i].pos[1])
return R
def com(self):
cm = [0.0, 0.0, 0.0]
for i in range(N):
cm[0] += self.chain[i].pos[0]
cm[1] += self.chain[i].pos[1]
cm[2] += self.chain[i].pos[2]
cm[0] /= N
cm[1] /= N
cm[2] /= N
return cm
def rg(self):
r_gyration = 0.0
cm = self.com()
rgx = 0.0
rgy = 0.0
rgz = 0.0
for i in range(N):
rgx += (cm[0] - self.chain[i].pos[0])**2
rgy += (cm[1] - self.chain[i].pos[1])**2
rgz += (cm[2] - self.chain[i].pos[2])**2
rgx /= N**2
rgy /= N**2
rgz /= N**2
r_gyration += np.sqrt(rgx + rgy + rgz)
return r_gyration
def print_chain(self):
for i in range(N):
print(self.chain[i].pos)
#print("{0:.6f}".format(float(str(self.chain[i].pos[0]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[1]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[2]))) + "\n")
def traj(self):
for i in range(shifts):
print(self.chain[i].move)
def save(self):
with open('traj_T_04.csv', 'w') as f:
for i in range(N):
f.write("{0:.6f}".format(float(str(self.chain[i].pos[0]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[1]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[2]))) + "\n")
def save_1(self):
with open('traj1_T_04.csv', 'w') as f:
for i in range(N):
f.write("{0:.6f}".format(float(str(self.chain[i].pos[0]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[1]))) + " , " + "{0:.6f}".format(float(str(self.chain[i].pos[2]))) + "\n")
def move(self): # Method returns a 'polymer' object, which is either the same as put in or a shifted one
backup = copy.deepcopy(self) # "backup = self" does not work as expected, as 'backup' becomes a mere synonym of 'self', but not an independent (immutable) object, as intended
monomer_index = np.random.randint(low=1, high=N) # choose a random monomer but 0, since it is grafted
direction = np.random.rand(3) - [0.5, 0.5, 0.5] # random vector consists of movement between [-0.5, -0.5, -0.5] and [0.5, 0.5, 0.5]
self.chain[monomer_index].shift(direction)
if self.chain[monomer_index].pos[2] < 0.0:
return backup
rnd = np.random.rand(1)
deltaE = self.Energy() - backup.Energy()
if np.exp(-(1/k_B*T)*deltaE) < rnd:
return backup
else:
return self # return the shifted polymer
if __name__ == "__main__":
#list_of_monomers = polymer(monomer.from_file('traj_T_4.csv'), monomer.from_file('traj1_T_4.csv'))
#list_of_monomers = monomer.from_file('traj1_T_4.csv')
K = 40.0
R = 0.3
r0 = 0.7
sigma = r0/2**6
rcutoff = 2.5*sigma
epsilon = 1.0
max_delta = 0.21 # -sigma/10 to sigma/10
N = 20
k_B = 1
T = 4.0
shifts = 100
# Declare two variables to be 'polymers'
pol1 = polymer(np.loadtxt('traj_T_4.csv', delimiter=","), N)
#pol1 = polymer([-r0/2, 0.0], N)
pol2 = polymer(np.loadtxt('traj1_T_4.csv', delimiter=" , "), N)
#pol2 = polymer([ r0/2, 0.0], N)
for j in range(shifts):
pol1 = pol1.move()
pol1.save()
for i in range(shifts):
pol2 = pol2.move()
pol2.save_1()
I am currently doing a python exercise for my University studies. I am very stuck at this task:
The taylor polynomial of degree N for the exponential function e^x is given by:
N
p(x) = Sigma x^k/k!
k = 0
Make a program that (i) imports class Polynomial (found under), (ii) reads x and a series of N values from the command line, (iii) creates a Polynomial instance representing the Taylor polynomial, and (iv) prints the values of p(x) for the given N values as well as the exact value e^x. Try the program out with x = 0.5, 3, 10 and N = 2, 5, 10, 15, 25.
Polynomial.py
import numpy
class Polynomial:
def __init__(self, coefficients):
self.coeff = coefficients
def __call__(self, x):
"""Evaluate the polynomial."""
s = 0
for i in range(len(self.coeff)):
s += self.coeff[i]*x**i
return s
def __add__(self, other):
# Start with the longest list and add in the other
if len(self.coeff) > len(other.coeff):
result_coeff = self.coeff[:] # copy!
for i in range(len(other.coeff)):
result_coeff[i] += other.coeff[i]
else:
result_coeff = other.coeff[:] # copy!
for i in range(len(self.coeff)):
result_coeff[i] += self.coeff[i]
return Polynomial(result_coeff)
def __mul__(self, other):
c = self.coeff
d = other.coeff
M = len(c) - 1
N = len(d) - 1
result_coeff = numpy.zeros(M+N+1)
for i in range(0, M+1):
for j in range(0, N+1):
result_coeff[i+j] += c[i]*d[j]
return Polynomial(result_coeff)
def differentiate(self):
"""Differentiate this polynomial in-place."""
for i in range(1, len(self.coeff)):
self.coeff[i-1] = i*self.coeff[i]
del self.coeff[-1]
def derivative(self):
"""Copy this polynomial and return its derivative."""
dpdx = Polynomial(self.coeff[:]) # make a copy
dpdx.differentiate()
return dpdx
def __str__(self):
s = ''
for i in range(0, len(self.coeff)):
if self.coeff[i] != 0:
s += ' + %g*x^%d' % (self.coeff[i], i)
# Fix layout
s = s.replace('+ -', '- ')
s = s.replace('x^0', '1')
s = s.replace(' 1*', ' ')
s = s.replace('x^1 ', 'x ')
#s = s.replace('x^1', 'x') # will replace x^100 by x^00
if s[0:3] == ' + ': # remove initial +
s = s[3:]
if s[0:3] == ' - ': # fix spaces for initial -
s = '-' + s[3:]
return s
def simplestr(self):
s = ''
for i in range(0, len(self.coeff)):
s += ' + %g*x^%d' % (self.coeff[i], i)
return s
def _test():
p1 = Polynomial([1, -1])
p2 = Polynomial([0, 1, 0, 0, -6, -1])
p3 = p1 + p2
print p1, ' + ', p2, ' = ', p3
p4 = p1*p2
print p1, ' * ', p2, ' = ', p4
print 'p2(3) =', p2(3)
p5 = p2.derivative()
print 'd/dx', p2, ' = ', p5
print 'd/dx', p2,
p2.differentiate()
print ' = ', p5
p4 = p2.derivative()
print 'd/dx', p2, ' = ', p4
if __name__ == '__main__':
_test()
Now I'm really stuck at this, and I would love to get an explaination! I am supposed to write my code in a separate file. I'm thinking about making an instance of the Polynomial class, and sending in the list in argv[2:], but that doesn't seem to be working. Do I have to make a def to calculate the taylor polynomial for the different values of N before sending it in to the Polynomial class?
Any help is great, thanks in advance :)
Not quite finished, but this answers your main question I believe. Put class Polynomial in poly.p and import it.
from poly import Polynomial as p
from math import exp,factorial
def get_input(n):
''' get n numbers from stdin '''
entered = list()
for i in range(n):
print 'input number '
entered.append(raw_input())
return entered
def some_input():
return [[2,3,4],[4,3,2]]
get input from cmd line
n = 3
a = get_input(n)
b = get_input(n)
#a,b = some_input()
ap = p(a)
bp = p(b)
print 'entered : ',a,b
c = ap+bp
print 'a + b = ',c
print exp(3)
x = ap
print x
sum = p([0])
for k in range(1,5):
el = x
for j in range(1,k):
el el * x
print 'el: ',el
if el!=None and sum!=None:
sum = sum + el
print 'sum ',sum
output
entered : [2, 3, 4] [4, 3, 2]
a + b = 6*1 + 6*x + 6*x^2
20.0855369232
2*1 + 3*x + 4*x^2
sum 2*1 + 3*x + 4*x^2
el: 4*1 + 12*x + 25*x^2 + 24*x^3 + 16*x^4
sum 6*1 + 15*x + 29*x^2 + 24*x^3 + 16*x^4
el: 4*1 + 12*x + 25*x^2 + 24*x^3 + 16*x^4
el: 8*1 + 36*x + 102*x^2 + 171*x^3 + 204*x^4 + 144*x^5 + 64*x^6
sum 14*1 + 51*x + 131*x^2 + 195*x^3 + 220*x^4 + 144*x^5 + 64*x^6
el: 4*1 + 12*x + 25*x^2 + 24*x^3 + 16*x^4
el: 8*1 + 36*x + 102*x^2 + 171*x^3 + 204*x^4 + 144*x^5 + 64*x^6
el: 16*1 + 96*x + 344*x^2 + 792*x^3 + 1329*x^4 + 1584*x^5 + 1376*x^6 + 768*x^7 + 256*x^8
sum 30*1 + 147*x + 475*x^2 + 987*x^3 + 1549*x^4 + 1728*x^5 + 1440*x^6 + 768*x^7 + 256*x^8
I solved the task in the following way, though im not sure if it answers question (iv).
The output just compares the exact value of e**x to the calculated value from module Polynomial.
from math import factorial, exp
from Polynomial import *
from sys import *
#Reads x and N from the command line on the form [filename.py, x-value, N-value]
x = eval(argv[1])
N = eval(argv[2])
#Creating list of coefficients on the form [1 / i!]
list_coeff = [1./factorial(i) for i in range(N)]
print list_coeff
#Creating an instance of class Polynomial
p1 = Polynomial(list_coeff)
print 'Calculated value of e**%f = %f ' %(x, p1.__call__(x))
print 'Exact value of e**%f = %f'% (x, exp(x))
"""Test Execution
Terminal > python Polynomial_exp.py 0.5 5
[1.0, 1.0, 0.5, 0.16666666666666666, 0.041666666666666664]
Calculated value of e**0.500000 = 1.648438
Exact value of e**0.500000 = 1.648721
"""