Count sets of increasing trend in a list - python-3.x

I have to count the number of subsets where there is an increasing trend based on user input of the list and the length of the subset.
List:[1,2,3,4,5,6,7,8,9]
k: The length of the trend.
for example...if k=3 and the data points increase for three consecutive numbers, then it is counted as one.
Here the input is the list and the length of the list and k
Example:
Input: List:{1,2,3,4,5,6}
k=3
Output: 4. {(1,2,3),(2,3,4),(3,4,5),(4,5,6)}

You can use the following :
def group_by_trend(data, k):
return [data[i*k :min((i+1)*k, len(data))]
for i in range(round((len(data)+1)/k))]
# test
k = 3
List = [1,2,3,4,5,6,7,8,9]
print(group_by_trend(List, k))
output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Related

LIS on two arrays

I feel lost on how to approach this question,
Given two integer array of size 𝑛
, 𝑚
, I want to merge these two arrays into one such that order of element in each array doesn't change and size of their Longest Increasing Subsequence become maximum.
Once we choose an element of A or B, we cannot choose an earlier element of that sequence
My goal is to find maximum possible length of longest increasing subsequence.
This is what I have so far:
def sequences(a, b, start_index=0, min_val=None):
limits = a[start_index], b[start_index]
lower = min(limits)
higher = max(limits)
if min_val is not None and min_val > lower:
lower = min_val
options = range(lower, higher + 1)
is_last = start_index == len(a) - 1
for val in options:
if is_last:
yield [val]
else:
for seq in sequences(a, b, start_index+1, min_val=val+1):
yield [val, *seq]
for seq in sequences([1,3,1,6], [6,5,4,4]):
print(seq)
However, this results in: [1, 3, 4, 5], [1, 3, 4, 6], [2, 3, 4, 5], [2, 3, 4, 6].
The expected output should be:
array1: [1,3,1,6]
array2: [6,5,4,4]
We take 1(from array1), 3(from array1), 4(from array2), 6(from array1)
Giving us LIS: [1,3,4,6].
We got this by not choosing an earlier element from a sequence once we are at a certain value.
How do I stop it from unwanted recursion?

Get a smaller list of lists from a list of lists of equal length based on criteria using Python

Good evening,
I have a table in the format of a list of lists. Each list is of the same length. I would like to obtain a smaller list based on the unique values of the numbers (1 list per number whichever shows up first).
tbl = [[1, 'aaa'], [2, 'aab'], [3, 'aac'], [4, 'GGC'], [4, 'GGH'], [6, 'GGS'], [7, 'aad']]
I've tried the following snippet of code:
tbl_simple = [list(x) for x in set(tuple(x) for x in tbl)]
But this line treats the whole list as one big unique value and I end up with the same table. I would like to filter on just the condition of the number (or some column of my choosing). The final result would look like this:
[[1, 'aaa'], [2, 'aab'], [3, 'aac'], [4, 'GGC'], [6, 'GGS'], [7, 'aad']]
Thank you for any assistance.
An easy non-one liner would be:
output = []
seen = set()
for num, letters in tbl:
if num in seen:
continue
output.append([num, letters])
seen.add(num)
Still thinking about a one-liner.

Building a list of random multiplication examples

I have two 100-element lists filled with random numbers between 1 and 10.
I want to make a list of multiplications of randomly selected numbers that proceeds until a product greater than 50 is generated.
How can I obtain such a list where each element is a product and its two factors?
Here is the code I tried. I think it has a lot of problems.
import random
list1 = []
for i in range(0,1000):
x = random.randint(1,10)
list1.append(x)
list2 = []
for i in range(0,1000):
y = random.randint(1,10)
list2.append(y)
m=random.sample(list1,1)
n=random.sample(list2,1)
list3=[]
while list3[-1][-1]<50:
c=[m*n]
list3.append(m)
list3.append(n)
list3.append(c)
print(list3)
The output I want
[[5.12154, 4.94359, 25.3188], [1.96322, 3.46708, 6.80663], [9.40574,
2.28941, 21.5336], [4.61705, 9.40964, 43.4448], [9.84915, 3.0071, 29.6174], [8.44413, 9.50134, 80.2305]]
To be more descriptive:
[[randomfactor, randomfactor, product],......,[[randomfactor,
randomfactor, greater than 50]]
Prepping two lists with 1000 numbers each with numbers from 1 to 10 in them is wasted memory. If that is just a simplification and you want to draw from lists you got otherwise, simply replace
a,b = random.choices(range(1,11),k=2)
by
a,b = random.choice(list1), random.choice(list2)
import random
result = []
while True:
a,b = random.choices(range(1,11),k=2) # replace this one as described above
c = a*b
result.append( [a,b,c] )
if c > 50:
break
print(result)
Output:
[[9, 3, 27], [3, 5, 15], [8, 5, 40], [5, 9, 45], [9, 3, 27], [8, 5, 40], [8, 8, 64]]
If you need 1000 random ints between 1 and 10, do:
random_nums = random.choices(range(1,11),k=1000)
this if much faster then looping and appending single integers 1000 times.
Doku:
random.choices(iterable, k=num_to_draw)
random.choice(iterable)

Select numbers from a list with given probability p

Lets say I have a list of numbers [1, 2, 3, ..., 100]. Now I want to select numbers from the list where each number is either accepted or rejected with a given probability 0 < p < 1 . The accepted numbers are then stored in a separate list. How can I do that?
The main problem is choosing the number with probability p. Is there an inbuilt function for that?
The value of p is given by the user.
You can use random.random() and a list comprehension:
import random
l = [1,2,3,4,5,6,7,8,9]
k = [x for x in l if random.random() > 0.23] # supply user input value here as 0.23
print(l)
print(k)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 3, 4, 5, 6, 7]
to check each element of the list if it has a probability of > 0.23 of staying in the list.
Sidenote:
random.choices() has the ability to accept weights:
random.choices(population, weights=None, *, cum_weights=None, k=1)
but those only change the probability inside the given list for drawing one of the elements (absolute or relative weights are possible) - thats not working for "independent" probabilities though.

Returning the N largest values' indices in a multidimensional array (can find solutions for one dimension but not multi-dimension)

I have a numpy array X, and I'd like to return another array Y whose entries are the indices of the n largest values of X i.e. suppose I have:
a =np.array[[1, 3, 5], [4, 5 ,6], [9, 1, 7]]
then say, if I want the first 5 "maxs"'s indices-here 9, 7 , 6 , 5, 5 are the maxs, and their indices are:
b=np.array[[2, 0], [2 2], [ 2 1], [1 1], [0 , 2])
I've been able to find some solutions and make this work for a one dimensional array like
c=np.array[1, 2, 3, 4, 5, 6]:
def f(a,N):
return np.argsort(a)[::-1][:N]
But have not been able to generate something that works in more than one dimension. Thanks!
Approach #1
Get the argsort indices on its flattened version and select the last N indices. Then, get the corresponding row and column indices -
N = 5
idx = np.argsort(a.ravel())[-N:][::-1] #single slicing: `[:N-2:-1]`
topN_val = a.ravel()[idx]
row_col = np.c_[np.unravel_index(idx, a.shape)]
Sample run -
# Input array
In [39]: a = np.array([[1,3,5],[4,5,6],[9,1,7]])
In [40]: N = 5
...: idx = np.argsort(a.ravel())[-N:][::-1]
...: topN_val = a.ravel()[idx]
...: row_col = np.c_[np.unravel_index(idx, a.shape)]
...:
In [41]: topN_val
Out[41]: array([9, 7, 6, 5, 5])
In [42]: row_col
Out[42]:
array([[2, 0],
[2, 2],
[1, 2],
[1, 1],
[0, 2]])
Approach #2
For performance, we can use np.argpartition to get top N indices without keeping sorted order, like so -
idx0 = np.argpartition(a.ravel(), -N)[-N:]
To get the sorted order, we need one more round of argsort -
idx = idx0[a.ravel()[idx0].argsort()][::-1]

Resources