Sorting of lists in number ranges - python-3.x

list = [1,2,,3,4,5,6,1,2,56,78,45,90,34]
range = ["0-25","25-50","50-75","75-100"]
I am coding in python. I want to sort a list of integers in range of numbers and store them in differrent lists.How can i do it?
I have specified my ranges in the the range list.

Create a dictionary with max-value of each bin as key. Iterate through your numbers and append them to the list that's the value of each bin-key:
l = [1,2,3,4,5,6,1,2,56,78,45,90,34]
# your range covers 25 a piece - and share start/endvalues.
# I presume [0-25[ ranges
def inRanges(data,maxValues):
"""Sorts elements of data into bins that have a max-value. Max-values are
given by the list maxValues which holds the exclusive upper bound of the bins."""
d = {k:[] for k in maxValues} # init all keys to empty lists
for n in data:
key = min(x for x in maxValues if x>n) # get key
d[key].append(n) # add number
return d
sortEm = inRanges(l,[25,50,75,100])
print(sortEm)
print([ x for x in sortEm.values()])
Output:
{25: [1, 2, 3, 4, 5, 6, 1, 2], 50: [25, 45, 34],
75: [56], 100: [78, 90]}
[[1, 2, 3, 4, 5, 6, 1, 2], [25, 45, 34], [56], [78, 90]]

Another stable bin approach for your special case (regular intervaled bins) would be to use a calculated key - this would get rid of the key-search in each step.
Stable search means the order of numbers in the list is the same as in the input data:
def inRegularIntervals(data, interval):
"""Sorts elements of data into bins of regular sizes.
The size of each bin is given by 'interval'."""
# init dict so keys are ordered - collection.defaultdict(list)
# would be faster - but this works for lists of a couple of
# thousand numbers if you have a quarter up to one second ...
# if random key order is ok, shorten this to d = {}
d = {k:[] for k in range(0, max(data), interval)}
for n in data:
key = n // interval # get key
key *= interval
d.setdefault(key, [])
d[key ].append(n) # add number
return d
Use on random data:
from random import choices
data = choices(range(100), k = 50)
data.append(135) # add a bigger value to see the gapped keys
binned = inRegularIntervals(data, 25)
print(binned)
Output (\n and spaces added):
{ 0: [19, 9, 1, 0, 15, 22, 4, 9, 12, 7, 12, 9, 16, 2, 7],
25: [25, 31, 37, 45, 30, 48, 44, 44, 31, 39, 27, 36],
50: [50, 50, 58, 60, 70, 69, 53, 53, 67, 59, 52, 64],
75: [86, 93, 78, 93, 99, 98, 95, 75, 88, 82, 79],
100: [],
125: [135], }
To sort the binned lists in place, use
for k in binned:
binned[k].sort()
to get:
{ 0: [0, 1, 2, 4, 7, 7, 9, 9, 9, 12, 12, 15, 16, 19, 22],
25: [25, 27, 30, 31, 31, 36, 37, 39, 44, 44, 45, 48],
50: [50, 50, 52, 53, 53, 58, 59, 60, 64, 67, 69, 70],
75: [75, 78, 79, 82, 86, 88, 93, 93, 95, 98, 99],
100: [],
125: [135]}

Related

randomly sample from a high dimensional array along with a specific dimension

There has a 3-dimensional array x of shape (2000,60,5). If we think it represents a video, the 2000 can represent 2000 frames. I would like to randomly sample it along with the first dimension, i.e., get a set of frame samples. For instance, how to get an array of (500,60,5) which is randomly sampled from x along with the first dimension?
You can pass x as the first argument of the choice method. If you don't want repeated frames in your sample, use replace=False.
For example,
In [10]: x = np.arange(72).reshape(9, 2, 4) # Small array for the demo.
In [11]: x
Out[11]:
array([[[ 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],
[28, 29, 30, 31]],
[[32, 33, 34, 35],
[36, 37, 38, 39]],
[[40, 41, 42, 43],
[44, 45, 46, 47]],
[[48, 49, 50, 51],
[52, 53, 54, 55]],
[[56, 57, 58, 59],
[60, 61, 62, 63]],
[[64, 65, 66, 67],
[68, 69, 70, 71]]])
Sample "frames" from x with the choice method of NumPy random generator instance.
In [12]: rng = np.random.default_rng()
In [13]: rng.choice(x, size=3)
Out[13]:
array([[[40, 41, 42, 43],
[44, 45, 46, 47]],
[[40, 41, 42, 43],
[44, 45, 46, 47]],
[[16, 17, 18, 19],
[20, 21, 22, 23]]])
In [14]: rng.choice(x, size=3, replace=False)
Out[14]:
array([[[ 8, 9, 10, 11],
[12, 13, 14, 15]],
[[32, 33, 34, 35],
[36, 37, 38, 39]],
[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]]])
Note that the frames will be in random order; if you want to preserve the order, you could use choice to generate an array of indices, then use the sorted indices to pull the frames out of x.

How can I optimize Largest Prime factor in given Number?

Constraints
1<=T<=10
10<=N<=10^2
Input
2
10
17
Output
5
17
This is my code
n=int(input())
for f in range(n):
b=[]
a=int(input())
for i in range(1,a+1):
if i>1:
for j in range(2,i):
if (i%j)==0:
break
else:
if a%i==0:
b.append(i)
print(max(b))
Explanation
10 are {2,5}, so answer 5
17 is 17 itself.
In the Constraints,
if T means there are at most 10 test cases,
and N means the range of the given number is between 10 to 100,
One of the most optimized ways is to create an initialized list in the code and print the pre-computed answer for every input read. :)
answer = [0, 1, 2, 3, 2, 5, 3, 7, 2, 3,
5, 11, 3, 13, 7, 5, 2, 17, 3, 19,
5, 7, 11, 23, 3, 5, 13, 3, 7, 29,
5, 31, 2, 11, 17, 7, 3, 37, 19, 13,
5, 41, 7, 43, 11, 5, 23, 47, 3, 7,
5, 17, 13, 53, 3, 11, 7, 19, 29, 59,
5, 61, 31, 7, 2, 13, 11, 67, 17, 23,
7, 71, 3, 73, 37, 5, 19, 11, 13, 79,
5, 3, 41, 83, 7, 17, 43, 29, 11, 89,
5, 13, 23, 31, 47, 19, 3, 97, 7, 11, 5]
Create a list of primes under 100.
Run a loop for each 'i' starting from 'a' to 'a/2-1' only, and check if 'i' divides 'a' completely and is present in 'primes'.
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
n=int(input())
for f in range(n):
a=int(input())
for i in range(a,int(a/2-1),-1):
if(a%i==0 and i in primes):
print(i)
break
If you dont want to create list of primes manually, you can use this first to create primes list through for loop:
import math
def isPrime(n):
if (n <= 1):
return False
#check from sqrt(n) to 2
for i in range(int(math.sqrt(n)),1,-1):
if (n % i == 0):
return False
return True
primes = []
for i in range(100):
if(isPrime(i)):
primes.append(i)
n=int(input())
for f in range(n):
a=int(input())
for i in range(a,int(a/2-1),-1):
if(a%i==0 and i in primes):
print(i)
break

Generate 2 random integer list of different size

I am trying to generate 2 list with different size consisting with random numbers. I can generate 2 list with random numbers, but how to achieve 2 different length of lists?
import random
list1 = random.sample(xrange(100), 10)
list2 = random.sample(xrange(100), 10)
print(list1)
print(list2)
Need to generate the lists with 2 random different sizes as well, as if both the lists are completely random.
Try the below code. Hope this would help.
If you want to create random number list of two different sizes. Then you can explicitly, pass the size of the list as a second argument, as given below.
import random
list1 = random.sample(xrange(100), 100)
list2 = random.sample(xrange(100), 10)
print(list1)
print(list2)
Ouput will be :
[46, 73, 13, 89, 44, 23, 74, 8, 19, 79, 36, 80, 85, 42, 82, 39, 61, 15, 27, 68, 67, 30, 11, 21, 86, 16, 63, 95, 17, 90, 37, 81, 20, 71, 93, 99, 40, 6, 47, 92, 58, 35, 12, 2, 10, 98, 87, 50, 51, 97, 70, 65, 78, 22, 72, 45, 59, 0, 52, 14, 1, 84, 43, 24, 54, 31, 18, 69, 7, 75, 53, 25, 57, 94, 83, 66, 3, 5, 88, 32, 4, 28, 29, 55, 9, 77, 60, 62, 41, 76, 48, 56, 34, 91, 33, 96, 49, 38, 26, 64]
[82, 58, 74, 61, 21, 77, 53, 35, 44, 59]
Now if you want to randomly decide the size of the list, the pass a random number as a second argument, by using randint function
import random
list1 = random.sample(range(100), random.randint(1,101))
list2 = random.sample(range(100), random.randint(1,101))
print(list1)
print(list2)
Output would be:
[93, 60, 82, 53, 16, 42, 0, 68, 88, 11, 89, 62, 38, 14, 27, 8, 45, 25, 83, 97, 94]
[30, 5, 19, 11, 14, 6, 7, 86, 16, 53, 71, 12, 90, 32]
You can try something like this, which would randomly generate the size between 1 and 10.
import random
list1 = random.sample(range(100), random.randint(1,10))
list2 = random.sample(range(100), random.randint(1,10))
print(list1)
print(list2)
This will generate random length of the lists. Hope it helps !
You need to randomize the second Parameter as well to become lists of random size:
import random
list1 = random.sample(range(100), random.randint(1,10))
list2 = random.sample(range(100), random.randint(1,10))
print(list1)
print(list2)

how can i find the highest even and odd number in 2D matrix using python3

how can i do this using simple code in python3
matrix = [[98, 19, 1, 46, 51, 33, 3, 33, 80, 40], [26, 88, 79, 10, 63, 76, 18, 49, 47, 44], [18, 53, 8, 96, 40, 53, 73, 8, 31, 43], [8, 40, 31, 98, 19, 39, 15, 9, 58, 32], [76, 45, 1, 5, 15, 14, 20, 88, 51, 48]
You can flatten your list via itertools.chain.from_iterable, then get the largest even and odd using %==0 for evens and %!=0 for odds:
import itertools
flat = list(itertools.chain.from_iterable(matrix))
even_max = max(i for i in flat if i%2==0)
odd_max = max(i for i in flat if i%2!=0)
>>> even_max
98
>>> odd_max
79
If you prefer to avoid itertools, you can flatten your 2d matrix by list comprehension:
flat = [v for i in matrix for v in i]
even_max = max(i for i in flat if i%2==0)
odd_max = max(i for i in flat if i%2!=0)
More options, with numpy (might be overkill for your matrix, but could be beneficial if your matrix were huge):
import numpy as np
m = np.array(matrix)
even_max = max(m[m%2==0])
odd_max = max(m[m%2!=0])

Extract random 2d windows of a 2d numpy array

import numpy as np
arr = np.array(range(60)).reshape(6,10)
arr
> array([[ 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, 28, 29],
> [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
> [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
> [50, 51, 52, 53, 54, 55, 56, 57, 58, 59]])
What I need:
select_random_windows(arr, number_of windows= 3, window_size=3)
> array([[[ 1, 2, 3],
> [11, 12, 13],
> [21, 22, 23]],
>
> [37, 38, 39],
> [47, 48, 49],
> [57, 58, 59]],
>
> [31, 32, 33],
> [41, 42, 43],
> [51, 52, 53]]])
In this hypothetical case I'm selecting 3 windows of 3x3 within the main array (arr).
My actual array is a raster and I basically need a bunch (on the thousands) of little 3x3 windows.
Any help or even a hint will be much appreciated.
I actually haven't found any practical solution yet...since many many hours
THX!
We can leverage np.lib.stride_tricks.as_strided based scikit-image's view_as_windows to get sliding windows. More info on use of as_strided based view_as_windows.
from skimage.util.shape import view_as_windows
def select_random_windows(arr, number_of_windows, window_size):
# Get sliding windows
w = view_as_windows(arr,window_size)
# Store shape info
m,n = w.shape[:2]
# Get random row, col indices for indexing into windows array
lidx = np.random.choice(m*n,number_of_windows,replace=False)
r,c = np.unravel_index(lidx,(m,n))
# If duplicate windows are allowed, use replace=True or np.random.randint
# Finally index into windows and return output
return w[r,c]
Sample run -
In [209]: arr
Out[209]:
array([[ 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, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]])
In [210]: np.random.seed(0)
In [211]: select_random_windows(arr, number_of_windows=3, window_size=(2,4))
Out[211]:
array([[[41, 42, 43, 44],
[51, 52, 53, 54]],
[[26, 27, 28, 29],
[36, 37, 38, 39]],
[[22, 23, 24, 25],
[32, 33, 34, 35]]])
You can try [numpy.random.choice()][1]. It takes a 1D or an ndarray and creates a single element or an ndarray by sampling the elements from the given ndarray. You also have an option of providing the size of the array you want as the output.

Resources