input a none-regular matrix in python - python

link: https://cw.felk.cvut.cz/courses/a4b33alg/task.php?task=pary_py&idu=2341
I want to input the matrix split by space by using:
def neighbour_pair(l):
matrix = [[int(row) for row in input().split()] for i in range(l)]
but the program told me
TypeError: 'str' object cannot be interpreted as an integer
It seems the .split() didn't work but I don't know why.
here is an example of the input matrix:
13 5
7 50 0 0 1
2 70 10 11 0
4 30 9 0 0
6 70 0 0 0
1 90 8 12 0
9 90 0 2 1
13 90 0 6 0
5 30 4 3 0
12 80 0 0 1
10 50 0 0 1
11 50 0 0 0
3 80 1 13 0
8 70 7 0 1
The input is a binary tree with N nodes, the nodes are labeled by numbers 1 to N in random order, each label is unique. Each node contains an integer key in the range from 0 to (2^31)−1.
The first line of input contains two integers N and R separated by space. N is the number of nodes in the tree, R is the label of the tree root.
Next, there are N lines. Each line describes one node and the order of the nodes is arbitrary. A node is specified by five integer values. The first value is the node label, the second value is the node key, the third and the fourth values represent the labels of the left and right child respectively, and the fifth value represents the node color, white is 0, black is 1. If any of the children does not exist there is value 0 instead of the child label at the corresponding place. The values on the line are separated by a space.

This is the range() complaining that your l variable is a string:
>>> range('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
I suspect you are reading the l from the standard in as well, cast it to integer:
l = int(input())
matrix = [[int(row) for row in input().split()] for i in range(l)]

I agree with #alecxe. It seems that your error is in reference to the string being used as l in your range(l) function. If I put a static int in the range() function it seems to work. 3 followed by three rows of input, will give me the below output.
>>> l = input() # define the number of rows expected the input matrix
>>> [[int(row) for row in input().split()] for i in range(int(l))]
13 5
7 50 0 0 1
2 70 10 11 0
output
[[13, 5], [7, 50, 0, 0, 1], [2, 70, 10, 11, 0]]
Implemented as a method, per the OP request in the comments below:
def neighbour_pair():
l = input()
return [[int(row) for row in input().split()] for i in range(int(l))]
print( neighbour_pair() )
# input
# 3
# 13 5
# 7 50 0 0 1
# 2 70 10 11 0
# output
[[13, 5], [7, 50, 0, 0, 1], [2, 70, 10, 11, 0]]
Still nothing wrong with this implementation...

Related

Python: How to print a number pyramid and display the multiples of 3 and 0 in remaining space [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
In place of integers not divisible by 3, I need 0s.
For example:
1
2 3
4 5 6
7 8 9 10
the final output should be:
0
0 3
0 0 6
0 0 9 0
I agree with #S3DEV that you should have at least tried it yourself and posted your attempts and described what specific problems you still struggle with.
But since I am not your mother or your teacher and I was intrigued by that exercise, here is my solution:
def render_level(
start: int,
stop: int,
divisor: int = 1,
number_width: int = 1
) -> str:
"""
Returns a string of numbers from `start` to `stop - 1` separated by spaces.
Every number in the range not divisible by `divisor` will be replaced by 0.
At least `number_width` characters will be reserved for each number.
"""
return " ".join(
f"{num if not num % divisor else 0:{number_width}}"
for num in range(start, stop)
)
def print_pyramid(num_levels: int, divisor: int = 1) -> None:
"""
Prints a numbers pyramid with the height `num_levels` to stdout.
Every number not divisible by `divisor` will be replaced by 0.
"""
last_num = num_levels * (num_levels + 1) // 2
number_width = len(str(last_num))
last_level = render_level(
last_num - num_levels + 1,
last_num + 1,
divisor=divisor,
number_width=number_width,
)
last_level_width = len(last_level)
start_num = 1
for i in range(1, num_levels):
level = render_level(
start_num,
start_num + i,
divisor=divisor,
number_width=number_width
)
indentation = (last_level_width - len(level)) // 2
print(" " * indentation, level, sep="")
start_num += i
print(last_level)
if __name__ == '__main__':
print_pyramid(5, 3)
This is the output:
0
0 3
0 0 6
0 0 9 0
0 12 0 0 15
You can also call print_pyramid with any other divisor instead of 3. Calling print_pyramid(6, 2) will give the following output:
0
2 0
4 0 6
0 8 0 10
0 12 0 14 0
16 0 18 0 20 0
And you can call it without a divisor argument. Then it will print just a regular numbers pyramid. Calling print_pyramid(9) will give you:
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 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
EDIT: Had it the other way around with the 0s. Fixed it now.
Although a coding attempt has not been provided, the intent of this answer is not a 'code-drop' but for educational purposes, with documentation links provided for each concept.
The full solution:
vals = [0 if i % 3 else i for i in range(1, 16)]
j = 0
for i in range(1, 6):
print(*vals[j:j+i])
j += i
Output:
0
0 3
0 0 6
0 0 9 0
0 12 0 0 15
Breaking it down:
This interesting task can be accomplished in two, very simple steps:
Define a list of integers which are divisible by three, with non-divisible integers being replaced by zero.
Iterate these values and print the triangle.
Step 1:
Create a list if values to be used.
Using list comprehension and the modulo operator, a list of integers which are divisible by three can be created:
vals = [0 if i % 3 else i for i in range(1, 16)]
Output:
[0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 15]
Step 2:
Iterate the values and print the triangle.
Note: Although a pyramid is mentioned in the title, a triangle example is provided in the question.
The variables i and j are used to slice (or extract) the required values from the list. The 'splat' operator (*) is used in the print function to expand (or unpack) the list into individual list values for printing.
j = 0
for i in range(1, 6):
print(*vals[j:j+i])
j += i

Find the shortest path fast

I want to make the shortest path between many points.
I generate an 8x8 matrix, with random values like:
[[ 0 31 33 0 43 10 0 0]
[31 0 30 0 0 13 0 0]
[33 30 0 11 12 5 6 0]
[ 0 0 11 0 15 0 38 11]
[43 0 12 15 0 39 0 0]
[10 13 5 0 39 0 3 49]
[ 0 0 6 38 0 3 0 35]
[ 0 0 0 11 0 49 35 0]]
Now I want to take the first list and see which is the smaller number. The see where it is in the list and take its position. Next I clear the first list to forget the first point. And put the next position in a new list of path. Then it will do the same for the new point. And at the final when all points are in my list of path it shows me the shortest way.
indm=0
lenm=[]
prochain=max(matrixF[indm])
chemin=[]
long=len(chemin)
while long != n:
for i in range (n):
if matrixF[indm,i] <= prochain and matrixF[indm,i]!=0:
pluspetit=matrixF[indm,i]
prochainpoint=np.where(matrixF == pluspetit)
chemin.append(prochainpoint)
indm=prochainpoint
for i in range (n):
matrixF[indm,i]=0
long=len(chemin)
print(chemin)
print(matrixF)
But I got this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
This line computes all the indices where matrixF == pluspetit:
prochainpoint=np.where(matrixF == pluspetit)
Problem is, there's more than one, so on your first pass through, prochainpoint ends up as (array([0, 5]), array([5, 0])). You then set indm to prochainpoint, so on your next pass, instead of getting a single value with matrixF[indm,i], you retrieve a 2x2 array of (repeated) values, as if you'd done:
np.array([[matrixF[0,1], matrixF[5,1]]
[matrixF[5,1], matrixF[0,1]])
Comparing this to prochain (still a scalar value) produces a 2x2 array of boolean results, which you then try to test for truthiness, but numpy doesn't want to guess at whether you mean "are they all true?" or "are any of them true?", so it dumps that decision back on you with the error message.
I'm assuming the problem is with prochainpoint=np.where(matrixF == pluspetit), where you get many results when you presumably only want one, but I'm not clear what the real intent of the line is, so you'll have to figure out what you really intended to do there and replace it with something that consistently computes a single value.

Sort on 2 columns which are inter

I have a dataframe :
start end
1 10
26 50
6 15
1 5
11 25
I expect following dataframe :
start end
1 10
11 25
26 50
1 5
6 15
here sort order is noting but end of nth row must be start+1 of n+1th row.If not found, search for other starts where start is one.
can anyone suggest what combination of sort and group by can I use to convert above dataframe in required format?
You could transform the df to a list and then do:
l=[1,10,26,50,6,15,1,5,11,25]
result=[]
for x in range(int(len(l)/2)):
result.append(sorted([l[2*x],l[2*x+1]])[1])
result.append(sorted([l[2*x],l[2*x+1]])[0])
This will give you result:
[1, 10, 26, 50, 6, 15, 1, 5, 11, 25]
To transform the original df to list you can do:
startcollist=df['start'].values.tolist()
endcollist=df['end'].values.tolist()
l=[]
for index, each in enumerate(originaldf):
l.append(each)
l.append(endcollist[index])
You can then transform result back to a dataframe:
df=pd.DataFrame({'start':result[1::2], 'end':result[0::2]})
Giving the result:
end start
0 10 1
1 50 26
2 15 6
3 5 1
4 25 11
The expression result[1::2] gives every odd element of result, result[0::2] gives every even element. For explanation, see here: https://stackoverflow.com/a/12433705/8565438

Python SQL Data to Array (like csv)

currently I am trying to read my SQL-Data to an array in python.
I am new to python so please be kind ;)
My csv-export can be read easily:
data = pd.read_csv('esoc_data.csv', header = None)
x = data[[1,2,3,4,5,6,7,8,9,10,11,12]]
This one picks the second column (starting from 1, not 0) till 12th column of my dataset. I need this data in this exact format!
Now I want to do the same with the data I get from my SQL-fetch.
names = [i for i in cursor.fetchall()]
This one gives me my data with all (0-12) columns and separated by ","
Result:
[(name#mail.com', 13, 13, 0, 24, 2, 0, 20, 3, 0, 31, 12, 2), (...)]
Now .. how do I get this into my "specific" format I mentioned before?
I just need the numbers like this:
1 2 3 4 5 6 7 8 9 10 11 12
0 13 13 0 24 2 0 20 3 0 31 12 2
1 21 0 0 24 0 0 32 0 0 30 0 0
2 9 7 0 26 31 0 19 27 0 30 32 2
I'm sorry if this is peanuts for you.
You can run a multi-loop for this, something like
def our_method():
parent_list = list()
for name in names:
child_list = list()
for index, item in enumerate(name):
if index != 0:
child_list.append(item)
parent_list.append(child_list)
return parent_list

Identify clusters linked by delta to the left and different delta to the right

Consider the sorted array a:
a = np.array([0, 2, 3, 4, 5, 10, 11, 11, 14, 19, 20, 20])
If I specified left and right deltas,
delta_left, delta_right = 1, 1
Then this is how I'd expect the clusters to be assigned:
# a = [ 0 . 2 3 4 5 . . . . 10 11 . . 14 . . . . 19 20
# 11 20
#
# [10--|-12] [19--|-21]
# [1--|--3] [10--|-12] [19--|-21]
# [-1--|--1] [3--|--5] [9--|-11] [18--|-20]
# +--+--|--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# [2--|--4] [13--|-15]
#
# │ ╰──┬───╯ ╰┬─╯ │ ╰┬─╯
# │ cluster 2 Cluster 3 │ Cluster 5
# Cluster 1 Cluster 4
NOTE: Despite the interval [-1, 1] sharing an edge with [1, 3], neither interval includes an adjacent point and therefore do not constitute joining their respective clusters.
Assuming the cluster assignments were stored in an array named clusters, I'd expect the results to look like this
print(clusters)
[1 2 2 2 2 3 3 3 4 5 5 5]
However, suppose I change the left and right deltas to be different:
delta_left, delta_right = 2, 1
This means that for a value of x it should be combined with any other point in the interval [x - 2, x + 1]
# a = [ 0 . 2 3 4 5 . . . . 10 11 . . 14 . . . . 19 20
# 11 20
#
# [9-----|-12] [18-----|-21]
# [0-----|--3] [9-----|-12] [18-----|-21]
# [-2-----|--1][2-----|--5] [8-----|-11] [17-----|-20]
# +--+--|--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# [1 ----|--4] [12-----|-15]
#
# ╰─────┬─────╯ ╰┬─╯ │ ╰┬─╯
# cluster 1 Cluster 2 │ Cluster 4
# Cluster 3
NOTE: Despite the interval [9, 12] sharing an edge with [12, 15], neither interval includes an adjacent point and therefore do not constitute joining their respective clusters.
Assuming the cluster assignments were stored in an array named clusters, I'd expect the results to look like this:
print(clusters)
[1 1 1 1 1 2 2 2 3 4 4 4]
We will leverage np.searchsorted and logic to find cluster edges.
First, let's take a closer look at what np.searchsorted does:
Find the indices into a sorted array a such that, if the corresponding elements in v were inserted before the indices, the order of a would be preserved.
What I'll do is execute np.searchsorted with a using a - delta_left. Let's look at that for delta_left = 1
# a =
# [ 0 2 3 4 5 10 11 11 14 19 20 20]
#
# a - delta_left
# [-1 1 2 3 4 9 10 10 13 18 19 19]
-1 would get inserted at position 0 to maintain order
1 would get inserted at position 1 to maintain order
2 would get inserted at position 1 as well, indicating that 2 might be in the same cluster as 1
3 would get inserted at position 2 indicating that 3 might be in the same cluster as 2
so on and so forth
What we notice is that only when an element less delta would get inserted at its current position would we consider a new cluster starting.
We do this again for the right side with a difference. The difference is that by default if a bunch of elements are the same, np.searchsorted assumes to insert into the front of values. To identify the ends of clusters, I'm going to want to insert after the identical elements. Therefore I'll use the paramater side='right'
If ‘left’, the index of the first suitable location found is given. If ‘right’, return the last such index. If there is no suitable index, return either 0 or N (where N is the length of a).
Now the logic. A cluster can only begin if a prior cluster has ended, with the exception of the first cluster. We'll then consider a shifted version of the results of our second np.searchsorted
Let's now define our function
def delta_cluster(a, dleft, dright):
# use to track whether searchsorted results are at correct positions
rng = np.arange(len(a))
edge_left = a.searchsorted(a - dleft)
starts = edge_left == rng
# we append 0 to shift
edge_right = np.append(0, a.searchsorted(a + dright, side='right')[:-1])
ends = edge_right == rng
return (starts & ends).cumsum()
demonstration
with left, right deltas equal to 1 and 1
print(delta_cluster(a, 1, 1))
[1 2 2 2 2 3 3 3 4 5 5 5]
with left, right deltas equal to 2 and 1
print(delta_cluster(a, 2, 1))
[1 1 1 1 1 2 2 2 3 4 4 4]
Extra Credit
What if a isn't sorted?
I'll utilize information learned from this post
def delta_cluster(a, dleft, dright):
s = a.argsort()
size = s.size
if size > 1000:
y = np.empty(s.size, dtype=np.int64)
y[s] = np.arange(s.size)
else:
y = s.argsort()
a = a[s]
rng = np.arange(len(a))
edge_left = a.searchsorted(a - dleft)
starts = edge_left == rng
edge_right = np.append(0, a.searchsorted(a + dright, side='right')[:-1])
ends = edge_right == rng
return (starts & ends).cumsum()[y]
demonstration
b = np.random.permutation(a)
print(b)
[14 10 3 11 20 0 19 20 4 11 5 2]
print(delta_cluster(a, 2, 1))
[1 1 1 1 1 2 2 2 3 4 4 4]
print(delta_cluster(b, 2, 1))
[3 2 1 2 4 1 4 4 1 2 1 1]
print(delta_cluster(b, 2, 1)[b.argsort()])
[1 1 1 1 1 2 2 2 3 4 4 4]

Categories