Related
I just would like to understand the passages of how this piece of code operates:
llist = [5, 2, 1, 4, 3]
for i in range(len(llist)):
for j in range(i+1):
if llist[j] < llist[i]:
temp = llist[i]
llist[i] = llist[j]
llist[j] = temp
print(llist)
I tried to meticulously go through every passage of the nested loop, but I can't understand how at the end of all that new-variable-assigning the elements of the list get sorted from highest to lowest.
Thank you very much to anyone who can help
With a bit of printing:
llist = [5, 2, 1, 4, 3]
for i in range(len(llist)):
print()
print(f'current pivot is {llist[i]} on position {i}')
for j in range(i+1):
if llist[j] < llist[i]:
print('-----------------------------------------------------------------')
print((f'\t {llist[j]} in position {j} and {llist[i]} on position {i} are in'
' the wrong order'))
print(f'\t before swapping our list is : {llist}')
temp = llist[i]
llist[i] = llist[j]
llist[j] = temp
print(f'\t after swapping we have {llist}')
print('-----------------------------------------------------------------')
print(f'list at the end of iteration: {llist}')
You get:
current pivot is 5 on position 0
list at the end of iteration: [5, 2, 1, 4, 3]
current pivot is 2 on position 1
list at the end of iteration: [5, 2, 1, 4, 3]
current pivot is 1 on position 2
list at the end of iteration: [5, 2, 1, 4, 3]
current pivot is 4 on position 3
-----------------------------------------------------------------
2 in position 1 and 4 on position 3 are in the wrong order
before swapping our list is : [5, 2, 1, 4, 3]
after swapping we have [5, 4, 1, 2, 3]
-----------------------------------------------------------------
-----------------------------------------------------------------
1 in position 2 and 2 on position 3 are in the wrong order
before swapping our list is : [5, 4, 1, 2, 3]
after swapping we have [5, 4, 2, 1, 3]
-----------------------------------------------------------------
list at the end of iteration: [5, 4, 2, 1, 3]
current pivot is 3 on position 4
-----------------------------------------------------------------
2 in position 2 and 3 on position 4 are in the wrong order
before swapping our list is : [5, 4, 2, 1, 3]
after swapping we have [5, 4, 3, 1, 2]
-----------------------------------------------------------------
-----------------------------------------------------------------
1 in position 3 and 2 on position 4 are in the wrong order
before swapping our list is : [5, 4, 3, 1, 2]
after swapping we have [5, 4, 3, 2, 1]
-----------------------------------------------------------------
list at the end of iteration: [5, 4, 3, 2, 1]
So we you can see, every time it finds that a number on the list has another number to its left that is smaller than the number at hand, then it swaps them.
For 5, it does nothing as there are no numbers to its left.
For 2, it does nothing as 5 is the only number to the left and it's > 2.
For 1, it does nothing as 5 and 2 are the only numbers to the left and they are both > 1.
For 4, it finds 2 as a number to its left, so we swap them and have:
[5,2,1,4,3] -> [5,4,1,2,3]
So now we continue and find 1 to the left of 2 (since now 2 is in the 3rd position), so we swap again
[5,4,1,2,3] -> [5,4,2,1,3]
Does that help?
This is an assignment; I have worked over it and somewhere get stuck;
This is the input from text file:
min: 1,2,3,5,6
max: 1,2,3,5,6
avg: 1,2,3,5,6
p90: 1,2,3,4,5,6,7,8,9,10
sum: 1,2,3,5,6
min: 1,5,6,14,24
max: 2,3,9
p70: 1,2,3
This is the required output to the text file:
The min of [1, 2, 3, 5, 6] is 1
The max of [1, 2, 3, 5, 6] is 6
The avg of [1, 2, 3, 5, 6] is 3.4
The 90th percentile of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] is 9
The sum of [1, 2, 3, 5, 6] is 17
The min of [1, 5, 6, 14, 24] is 1
The max of [2, 3, 9] is 9
The 70th percentile of [1, 2, 3] is 2
This is my work-out to the text file:
The min of [1, 5, 6, 14, 24] is 1
The max of [2, 3, 9] is 9
The avg of [1, 2, 3, 5, 6] is 3.4
The p90 of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] is 9.0
The sum of [1, 2, 3, 5, 6] is 17
The p70 of [1, 2, 3] is 2.1
Logics
I wrote a function to read from a file and insert the keys:values into dictionary;
Below is the dictionary
OrderedDict([('min', [1, 5, 6, 14, 24]), ('max', [2, 3, 9]), ('avg', [1, 2, 3, 5, 6]), ('p90', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), ('sum', [1, 2, 3, 5, 6]), ('p70', [1, 2, 3])])
From here I compute the required and write the results to the file
My question; how can I make the keys min and max duplicate in the dictionary as you can see the have been overwritten
The problem is, that the keys in a dictionary are unique. That means, a dictionary can only have one entry with the key 'min'. That's why your first entry with the key 'min' gets overwritten by the second.
To solve this I would recommend to change the structure type from Dictionary to something else (like a nested List).
list = []
list.append(['min', [1, 2, 3, 5, 6]])
you will get a list of rows, each containing the function (like 'min') and the number array.
More about Lists
Given an m x n matrix I want to split it into square a x a (a = 3 or a = 4) matrices of arbitrary offset (minimal offset = 1, max offset = block size), like Mathematica's Partition function does:
For example, given a 4 x 4 matrix A like
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
If I give 3 x 3 blocks and offset = 1, I want to get the 4 matrices:
1 2 3
5 6 7
9 10 11
2 3 4
6 7 8
10 11 12
5 6 7
9 10 11
13 14 15
6 7 8
10 11 12
14 15 16
If matrix A is A = np.arange(1, 37).reshape((6,6)) and I use 3 x 3 blocks with offset = 3, I want as output the blocks:
1 2 3
7 8 9
3 14 15
4 5 6
10 11 12
16 17 18
19 20 21
25 26 27
31 32 33
22 23 24
28 29 30
34 35 36
I'm ok with matrix A being a list of lists and I think that I don't need NumPy's functionality. I was surprised that neither array_split nor numpy.split provide this offset option out of the box, is it more straightforward to code this in pure Python with slicing or should I look into NumPy's strides? I want the code to be highly legible.
As you hint, there is a way of doing this with strides
In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4))
In [901]: M
Out[901]:
array([[[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]],
[[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]]])
In [902]: M.reshape(4,3,3) # to get it in form you list
Out[902]:
array([[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]],
[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]])
A problem with strides is that it is advanced, and hard to explain to someone without much numpy experience. I figured out the form without much trial and error, but I've been hanging around here too long. :) ).
But this iterative solution is easier to explain:
In [909]: alist=[]
In [910]: for i in range(2):
...: for j in range(2):
...: alist.append(A[np.ix_(range(i,i+3),range(j,j+3))])
...:
In [911]: alist
Out[911]:
[array([[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]]),
array([[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]),
array([[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]]),
array([[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]])]
Which can be turned into an array with np.array(alist). There's nothing wrong with using this if it is clearer.
One thing to keep in mind about the as_strided approach is that it is a view, and changes to M may change A, and a change in one place in M may modify several places in M. But that reshaping M may turn it into a copy. So overall it's safer to read values from M, and use them for calculations like sum and mean. In place changes can be unpredictable.
The iterative solution produces copies all around.
The iterative solution with np.ogrid instead of np.ix_ (otherwise the same idea):
np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)])
both ix_ and ogrid are just easy ways constructing the pair of vectors for indexing a block:
In [970]: np.ogrid[0:3, 0:3]
Out[970]:
[array([[0],
[1],
[2]]), array([[0, 1, 2]])]
The same thing but with slice objects:
np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)])
The list version of this would have similar view behavior as the as_strided solution (the elements of the list are views).
For the 6x6 with non-overlapping blocks, try:
In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i
...: n range(0,6,3)])
Out[1016]:
array([[[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15]],
[[ 4, 5, 6],
[10, 11, 12],
[16, 17, 18]],
[[19, 20, 21],
[25, 26, 27],
[31, 32, 33]],
[[22, 23, 24],
[28, 29, 30],
[34, 35, 36]]])
Assuming you want contiguous blocks, the inner slices/ranges don't change, just the stepping for the outer i and j
In [1017]: np.arange(0,6,3)
Out[1017]: array([0, 3])
I'm trying to write a 4X4 grid in python where the last two rows contain the same numbers as the first two rows.
The end result should be exactly this:
0 1 2 3
4 5 6 7
0 1 2 3
4 5 6 7
The goal is to make a game where the above grid is traversable. I've tried list comprehensions and concatenating two lists and it's not producing the right answers.
Concatenating two lists should work. The code for concatenating two lists
l1 = [1, 2, 3, 4]
l2 = [5, 6, 7, 8]
l3 = [l1 , l2];
l4 = l3+l3
print l4
should yield [[1, 2, 3, 4], [5, 6, 7, 8], [1, 2, 3, 4], [5, 6, 7, 8]]
I'm trying to avoid an IF in the following mapping function:
X Y
1 11
2 10
3 9
4 8
5 7
6 6
7 5
8 4
9 3
10 2
11 1
12 12
It's basically Y = (12 - X), except when X = 12. In this case, Y = 12.
The Y vector is the reverse of the X vector shifted by one position. Is there a way to write this function using min and max or something like this in order to avoid a conditional?
I'm not attached to any programming language here
y = 12 - x%12;
works for all x from 1 to 12 inclusive. % is the C-style modulus operator, giving the remainder from dividing x by 12. That's zero if x is 12, and x for 1 to 11.
Ruby answer:
x = (1..12).to_a
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = x.map{|n| 12 - n % 12}
#=> [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 12]
This can be extended to work for any length by using n.max instead of 12.