Print a Pretty Tree - python-3.x

I have extracted a list from a tree using BFS
solution= [[6], [0, 7], [None, 3, None, 8], [2, 5, None, 9], [1, None, 4, None, None, None], [None, None, None, None]]
How do i print it as a horizontal tree?
I was trying to print it using
def _print_tree(n=0,height,solution):
if n > height:
return
for j in range(len(solution[n])):
if solution[n][j]== None:
print(' ' * (2 ** (height - n + 1) - 1),end='')
else:
print(' ' * (2 ** (height - n + 1) - 1), end='')
print(' ',solution[n][j], end='')
But it gives

I've played around and here is the result
nonechar = 'N'
spacechar = '_'
solution = [[6], [0, 7], [None, 3, None, 8], [2, 5, None, 9], [1, None, 4, None, None, None], [None, None, None, 4],[None, 3]]
for i in range(1, len(solution)):
for j in range(len(solution[i-1])):
if (solution[i-1][j] == None):
solution[i].insert(2*j, None)
solution[i].insert(2*j+1, None)
N = len(solution[-1]) * 2 - 1
offset = (N - 1) / 2
spacing = 0
for i in range(len(solution)):
line = spacechar * int(offset)
for j in range(len(solution[i])):
if (solution[i][j] == None):
line += nonechar
else:
line += str(solution[i][j])
if (j != len(solution[i]) - 1):
line += spacechar * int(spacing)
line += spacechar * int(offset)
print(line)
spacing = offset
offset = (offset - 1) / 2
What I basically did is fill the solution list with the missing data so that each next sub-list has two times more values than the previous one. For each j-th element of the i-th sub-list there are values under [i+1][2*j] and [i+1][2*j+1]. Then I just print out the result using ASCII art, having calculated required offsets and spacing. The limitations here are that you can only use digits 0-9 in order not to screw up my tree. You'll have to figure out the way to solve it on your own :)
Oh, yeah. The output looks like this (feel free to change characters for missing values and spaces):
_______________________________________________________________6_______________________________________________________________
_______________________________0_______________________________________________________________7_______________________________
_______________N_______________________________3_______________________________N_______________________________8_______________
_______N_______________N_______________2_______________5_______________N_______________N_______________N_______________9_______
___N_______N_______N_______N_______1_______N_______4_______N_______N_______N_______N_______N_______N_______N_______N_______N___
_N___N___N___N___N___N___N___N___N___N___N___N___N___4___N___N___N___N___N___N___N___N___N___N___N___N___N___N___N___N___N___N_
N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_3_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N_N

Related

Remove all elements from an array python

1) The question I'm working on:
Write an algorithm for a function called removeAll which takes 3 parameters: an array of array type, a count of elements in the array, and a value. As with the remove method we discussed in class, elements passed the count of elements are stored as None. This function should remove all occurrences of value and then shift the remaining data down. The last populated element in the array should then be set to None. The function then returns the count of “valid” (i.e. non-removed) data elements left. This function should do the removal “by hand” and SHOULD NOT use the remove method.
2) Below I have what I think works for the question, but it seems inefficient and repetitive. Is there any way to simplify it?
'''
def myremove(mylist, elements, val):
for i in range(elements): # Changes all val that needs to be removed to None
if mylist[i] == val:
mylist[i] = None
for i in range(elements):
if mylist[i] is None: # Moves elements remaining left
for j in range(i, elements- 1):
mylist[j] = mylist[j + 1]
mylist[elements- 1] = None
while mylist[0] is None: # If the first element is None move left until it is not
for j in range(i, elements - 1):
mylist[j] = mylist[j + 1]
mylist[elements - 1] = None
for i in range(elements): # Counts remaining elements
if mylist[i] is None:
elements -= 1
return mylist, elements
"""
"""
# Testing the function
print(removeAll([8, 'N', 24, 16, 1, 'N'], 6, 'N'))
print(removeAll([1, 'V', 3, 4, 2, 'V'], 6, 3))
print(removeAll([0, 'D', 5, 6, 9, 'D'], 6, 'N'))
print(removeAll(['X', 'X', 7, 'X', 'C', 'X'], 6, 'X'))
"""
"""
OUTPUT
([8, 24, 16, 1, None, None], 4)
([1, 'V', 4, 2, 'V', None], 5)
([0, 'D', 5, 6, 9, 'D'], 6)
([7, 'C', None, None, None, None], 2)
"""
You can just sort the list based on whether or not the value equals the hole value.
l = [8, 'N', 24, 16, 1, 'N']
sorted(l, key=lambda x: x == 'N')
output:
[8, 24, 16, 1, 'N', 'N']
If you need None instead of the hole value in the output, use a list comprehension and then sort based on None first.
l = [i if i != 'N' else None for i in [8, 'N', 24, 16, 1, 'N']]
sorted(l, key=lambda x: x == None)
[8, 24, 16, 1, None, None]
Then all thats left is to add in the count which you can just get by counting how many elements are None and subtract that from your input parameter.
def myremove(mylist, elements, val):
ret_list = sorted([i if i != val else None for i in mylist], key=lambda x: x == None)
return ret_list, elements - ret_list.count(None)

Counting instances of N in an array using Recursion in Python

I would like to count the number of instances of a given number N in an array using recursion. For example, given:
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
and N = 1, the function should return 5.
This problem can be solved using the .counter attribute as shown here. However, I am looking to not use any in-built functions or attributes.
Here's my attempt to solve this using recursion but I get a count of 1 and not 5. What am I doing wrong?
def count_val(array, n, count=0):
if len(array) == 0:
return None
# Base Case
if len(array) == 1:
if array[0] == n:
count += 1
else:
count_val(array[1:], n, count)
if array[0] == n:
count += 1
return count
print(count_val2(array, 1))
1
I think for an empty array, the value should be 0 (len == 0 should be the base case), and, you don't need to have a count parameter if you just return the count, your function could be reduced to this:
def count_val(array, n):
if len(array) == 0:
return 0
return (array[0] == n) + count_val(array[1:], n)
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
print(count_val(array, 1))
Output:
5
You can have it as a one-liner as well (as suggested by #blhsing):
def count_val(array, n):
return len(array) and (array[0] == n) + count_val(array[1:], n)
What am I doing wrong?
The function you wrote will always keep only the last few characters, so after a while it will be [1, 8, 1], after that [8, 1] and after that [1], which returns 1. The array never contains just any of the other 1s.
An easy way to do this is to loop over all elements in a list and test if they are equal to N.
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
def count_val(array, n):
if len(array) == 0:
return 0
count=0
for i in array:
if i==n:
count += 1
return count
print(count_val(array, 1))
This returns 5.

All test cases passed except one which is throwing key error

We are given a directed graph, with nodes labeled 0, 1, ..., n-1 and each edge is either red or blue, and there could be self-edges or parallel edges.
Each [i, j] in red_edges denotes a red directed edge from node i to node j. Similarly, for blue_edges.
Return an array 'answer' of length n, where each answer[X] is the length of the shortest path from node 0 to node X such that the edge colors alternate along the path (or -1 if such a path doesn't exist).
I'm not getting where's the problem in the code.
n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
d={}
result=[-1]*(n)
for i in red_edges:
if i[0] not in d:
d[i[0]]=[i[1]]
else:
d[i[0]].append(i[1])
if i[0]==0:
result[i[1]]=1
#print(d)
for j in blue_edges:
if j[0] not in d:
d[j[0]]=[j[1]]
else:
d[j[0]].append(j[1])
if j[0]==0:
result[j[1]]=1
elif j[0]!=0:
if j[0] in d[0]: #This is Line 24 which is throwing error.
result[j[1]]=2
else:
pass
if 0 in d[0]:
result[0]=1
else:
result[0]=0
#print(d)
print(result)
Key in 'd' is equal to the starting node and value in a key-value pair has a list in which all the endpoints corresponding to that key are inserted.
Moreover, in each for loop, I'm also preparing my result array if any edge is present between node zero and node equal to the index of the result array. e.g, I'll insert 1 in result array for index 1 if it has a direct link with node zero else I'll keep it as -1. And if any index has indirect link( as in test case 2: blue_edges =[[2,1]]) then I'll check in d[0] if first element of blue_edges is present. If it is present then I'll insert 2 else -1.
expected=actual=[0,1,-1]
expected=actual=[0,1,-1]
expected=actual=[0,1,1]
expected=[0,-1,-1] but in 4th case it is throwing an error.
Line 24: KeyError: 0
I switched to using defaultdict(list) so that if d is empty for some value, you'll just get an empty list.
In your case - it eliminates the error and logically matches the if.
it also help clean up many if/elses.
try this:
from collections import defaultdict
cases = [
(3, [[0, 1], [1, 2]], []),
(3, [[0, 1]], [[2, 1]]),
(3, [[0, 1]], [[1, 2]]),
(3, [[1, 0]], [[2, 1]]),
]
for n, red_edges, blue_edges in cases:
d = defaultdict(list)
result = [-1] * n
result[0] = 0
for src, dst in red_edges:
d[src].append(dst)
if src == 0:
result[dst] = 1
for src, dst in blue_edges:
d[src].append(dst)
if src == 0:
result[dst] = 1
else:
if src in d[0]:
result[dst] = 2
print(result)
Output:
[0, 1, -1]
[0, 1, -1]
[0, 1, 2]
[0, -1, -1]

What is wrong with the syntax for this insertion sort and bubble sort code?

I am currently taking discrete structures and algorithms and have to work with python for the first time.
I am having a little trouble with the syntax and having a problem with my bubble sort and insertion sort function printing
def insertion_sort(numbers):
numbers = [1, 5, 9, 3, 4, 6]
for index in range(1, len(numbers)):
value = numbers[index]
i = index - 1
while i >= 0:
if value < numbers[i]:
numbers[i+1] = numbers[i]
numbers[i] = value
i = i - 1
print(numbers)
else:
break
def bubble_sort(numbers):
for i in range(0, len(numbers) - 1, 1):
for j in range(0, len(numbers) - 1 - i, 1):
if numbers[j] < numbers[j + 1]:
temp = numbers[j]
numbers[j] = numbers[j + 1]
numbers[j + 1] = temp
numbers = [1, 5, 9, 3, 4, 6]
print(numbers)
You've defined two functions but never call them. Therefore, they are not getting executed.
You've defined your two functions such that they expect a numbers parameter. So you need to call them with a list of numbers as input. eg. insertion_sort([1, 5, 9, 3, 4, 6])
Your functions are not returning any value. So they are simply taking the numbers list parameter, and sorting it. In order to access the result from outside the function, you need to add return numbers at the end of each function.
All in all, your code should look something like this:
def insertion_sort(numbers):
for index in range(1, len(numbers)):
value = numbers[index]
i = index - 1
while i >= 0:
if value < numbers[i]:
numbers[i+1] = numbers[i]
numbers[i] = value
i = i - 1
else:
break
return numbers
def bubble_sort(numbers):
for i in range(0, len(numbers) - 1, 1):
for j in range(0, len(numbers) - 1 - i, 1):
if numbers[j] < numbers[j + 1]:
temp = numbers[j]
numbers[j] = numbers[j + 1]
numbers[j + 1] = temp
return numbers
numberstosort = [1, 5, 9, 3, 4, 6]
print(insertion_sort(numberstosort))
print(bubble_sort(numberstosort))
This will print the output of each function. Output:
[1, 3, 4, 5, 6, 9]
[9, 6, 5, 4, 3, 1]

calculate the sum of the intervals based on the binary array

I have two matrix:
Binary A = [[1, 0, 1, 0], [0, 0, 1, 0]];
Matrix of values B = [[100, 200, 300, 400], [400, 300, 100, 200]];
I want to calculate the sum of the intervals that are formed by the rows of the matrix A. For my exmpl. result will be follow: R = [[300, 0, 700, 0], [0, 0, 300, 0]] (generally, it is not necessary to set zeros [[300, 700], [300]] - it's right solution too)
I already wrote the code, but very very terrible (although it works correctly)
def find_halfsum(row1, row2):
i = 0
result = []
count = 0
for j in range(len(row1)):
if row1[j] == 1 and count == 0:
i = j
count += 1
elif row1[j] == 1:
count += 1
if count == 2:
if j == i + 1:
result.append(row2[i])
else:
result.append(sum(row2[i:j]))
i = j
count = 1
if j == len(row1) - 1:
result.append(sum(row2[i:j + 1]))
return result
Someone knows beautiful solutions (which will be faster)(preferably with the help of a numpy)?
Thanks
Not familiar with python, but I don't think you need that many lines
define halfSum(matrixA, matrixB):
sum = 0;
for i in range(len(matrixA)):
if matrixA[i] == 1:
sum += matrixB[i]
return sum;
You can use numpy.add.reduceat:
>>> A = np.array([[1, 0, 1, 0], [0, 0, 1, 0]])
>>> B = np.array([[100, 200, 300, 400], [400, 300, 100, 200]])
>>>
>>> [np.add.reduceat(b, np.flatnonzero(a)) for a, b in zip(A, B)]
[array([300, 700]), array([300])]

Resources