I have four given variables:
group size
total of groups
partial sum
1-D tensor
and I want to add zeros when the sum within a group reached the partial sum. For example:
groupsize = 4
totalgroups = 3
partialsum = 15
d1tensor = torch.tensor([ 3, 12, 5, 5, 5, 4, 11])
The expected result is:
[ 3, 12, 0, 0, 5, 5, 5, 0, 4, 11, 0, 0]
I have no clue how can I achieve that in pure pytorch. In python it would be something like this:
target = [0]*(groupsize*totalgroups)
cursor = 0
current_count = 0
d1tensor = [ 3, 12, 5, 5, 5, 4, 11]
for idx, ele in enumerate(target):
subgroup_start = (idx//groupsize) *groupsize
subgroup_end = subgroup_start + groupsize
if sum(target[subgroup_start:subgroup_end]) < partialsum:
target[idx] = d1tensor[cursor]
cursor +=1
Can anyone help me with that? I have already googled it but couldn't find anything.
Some logic, Numpy and list comprehensions are sufficient here.
I will break it down step by step, you can make it slimmer and prettier afterwards:
import numpy as np
my_val = 15
block_size = 4
total_groups = 3
d1 = [3, 12, 5, 5, 5, 4, 11]
d2 = np.cumsum(d1)
d3 = d2 % my_val == 0 #find where sum of elements is 15 or multiple
split_points= [i+1 for i, x in enumerate(d3) if x] # find index where cumsum == my_val
#### Option 1
split_array = np.split(d1, split_points, axis=0)
padded_arrays = [np.pad(array, (0, block_size - len(array)), mode='constant') for array in split_array] #pad arrays
padded_d1 = np.concatenate(padded_arrays[:total_groups]) #put them together, discard extra group if present
#### Option 2
split_points = [el for el in split_points if el <len(d1)] #make sure we are not splitting on the last element of d1
split_array = np.split(d1, split_points, axis=0)
padded_arrays = [np.pad(array, (0, block_size - len(array)), mode='constant') for array in split_array] #pad arrays
padded_d1 = np.concatenate(padded_arrays)
I would like to know if I have generated the 3 arrays in the manner below, how can I sum all the numbers up from all 3 arrys without summing up the ones that appear in each array.
(I would like to only som upt 10 once but I cant add array X_1 andX_2 because they both have 10 and 20, I only want to som up those numbers once.)
Maybe this can be done by creating a new array out of the X_1, X_2 and X_3 what leave out doubles?
def get_divisible_by_n(arr, n):
return arr[arr%n == 0]
x = np.arange(1,21)
X_1=get_divisible_by_n(x, 2)
#we get array([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20])
X_2=get_divisible_by_n(x, 5)
#we get array([ 5, 10, 15, 20])
X_3=get_divisible_by_n(x, 3)
#we get array([3, 6, 9, 12, 15, 18])
it is me again!
here is my solution using numpy, cuz i had more time this time:
import numpy as np
arr = np.arange(1,21)
divisable_by = lambda x: arr[np.where(arr % x == 0)]
n_2 = divisable_by(2)
n_3 = divisable_by(3)
n_5 = divisable_by(5)
what_u_want = np.unique( np.concatenate((n_2, n_3, n_5)) )
# [ 2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]
Not really efficient and not using numpy but here is one solution:
def get_divisible_by_n(arr, n):
return [i for i in arr if i % n == 0]
x = [i for i in range(21)]
X_1 = get_divisible_by_n(x, 2)
X_2 = get_divisible_by_n(x, 5)
X_3 = get_divisible_by_n(x, 3)
X_all = X_1+X_2+X_3
y = set(X_all)
print(sum(y)) # 142
I have list [1, 2, 5, 6, 9, 10, 14, 19], how can i get any number range index.
For example:
l = [1, 2, 5, 6, 9, 10, 14, 19]
value = 11
range_index = get_range_index(l)
range_index = (5, 6) # need like this
# give a value = 11, need to get value index like (5, 6), because 10 < value < 14.
# the list size may be very very long,can there have good method?
This i try to get left value and calculate index by returned left value.
It's not very good and not high performance.
def get_left_point(self, data, value):
if len(data) == 1:
return data[0]
mid_index, mid_value = len(data) // 2, data[len(data) // 2]
if value >= float(mid_value):
ret = self.get_left_point(data[mid_index:], value)
else:
ret = self.get_left_point(data[:mid_index], value)
return ret
my_range = (100, 101)
[x for x in l if (my_range[0] <= x) and (x <= my_range[1])]
### import math
def mean(values):
return sum(values)*1.0/len(values)
def std():
pass
print(std())
def std(values):
length = len(values)
if length < 2:
return("Standard deviation requires at least two data points")
m = mean(values)
total_sum = 0
for i in range(length):
total_sum += (values[i]-m)**2
under_root = total_sum*1.0/length
return math.sqrt(under_root)
vals = [5]
stan_dev = std(vals)
print(stan_dev)
values = [1, 2, 3, 4, 5]
stan_dev = std(values)
print(stan_dev)
__________________________________________________________________________
lst = [3, 19, 21, 1435, 653342]
sum = reduce((lambda x, y: x +y), lst)
print (sum)
# list = [3, 19, 21, 1435, 653342]
i need to be able to get the stDev without using sum or len
i need to 'unpack' the stDev ???
You can do it with two loops (there are shorter ways but this is simple):
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Calculate the mean first
N, X = 0, 0
for xi in arr:
N += 1
X += xi
mean = X/N
# Calculate the standard deviation
DSS = 0
for xi in arr:
DSS += (xi - mean)**2
std = (DSS/N)**(1/2)
Outputs 4.5 for mean and 2.872 for std.
I'm completely new to Python, thus the question. I'm trying to solve a standard interview question, which is finding a peak in an array. A peak is defined as a number which is greater than it's left and right neighbor. I'm trying to find the largest such peak.
This is my code:
def main():
arr = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1]
print(find_peak(arr))
def find_peak(arr):
return _find_peak(arr, 0, len(arr))
def _find_peak(arr, start, stop):
mid = (start + stop) // 2
if arr[mid] > arr[mid - 1] and arr[mid] > arr[mid + 1]:
return arr[mid]
elif arr[mid] < arr[mid - 1]:
_find_peak(arr, 0, mid - 1)
elif arr[mid] < arr[mid + 1]:
_find_peak(arr, mid + 1, stop)
if __name__ == '__main__':
main()
The output of this program is None, where as the expected output is 24. Any help appreciated.
Data
arr = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1]
A one-liner:
One line should be enough:
max_peak = max(x2 for x1, x2, x3 in zip(arr, arr[1:], arr[2:]) if x1 < x2 > x3)
In a loop
Maybe easier to understand when you are new to Python:
peak = float('-inf')
for x1, x2, x3 in zip(arr, arr[1:], arr[2:]):
if x1 < x2 > x3:
peak = max(peak, x2)
print(peak)
Output:
24
All peaks
You can also use a one-liner to get all peaks:
>>> [x2 for x1, x2, x3 in zip(arr, arr[1:], arr[2:]) if x1 < x2 > x3]
[13, 24]
and get the greatest one with max() on the result.
Explanation
Let's have a look at some of the components of the solution. I am working with Python 3 here, as everybody should. ;)
You can slice lists.
>>> arr = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1]
This gives you all of the list but the first element:
>>> arr[1:]
[12, 13, 8, 2, 16, 24, 11, 5, 1]
Here its starts with element three:
>>> arr[2:]
[13, 8, 2, 16, 24, 11, 5, 1]
The zip() function zips multiple sequences together. To visualize what happens, you can convert the zip object into a list:
>>> list(zip(arr, arr[1:], arr[2:]))
[(7, 12, 13),
(12, 13, 8),
(13, 8, 2),
(8, 2, 16),
(2, 16, 24),
(16, 24, 11),
(24, 11, 5),
(11, 5, 1)]
Python supports tuple unpacking. This allows to assign individual names to all members of a tuple:
>>> x1, x2, x3 = (7, 12, 13)
>>> x1
7
>>> x2
12
>>> x3
13
Another nice feature is the comparison of more than two objects:
>>> 10 < 12 > 8
True
This is equivalent to:
>>> (10 < 12) and (12 > 8)
True
Python offers list comprehensions:
>>> [x * 2 for x in range(2, 6)]
[4, 6, 8, 10]
Generator expression work in a similar way but don't produce a list but an iterator and can be consumed without using lots of memory:
>>> sum(x * 2 for x in range(2, 6))
28
you are missing a return statement for your two elif cases
I think the 13 also is a peak (greater than 12 and 8).
Try this approach:
def main():
arr = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1]
print(find_peaks(arr))
def find_peaks(arr):
return list(_search(arr))
def _search(arr):
last = len(arr) - 1
for i, e in enumerate(arr):
if not any((i > 0 and arr[i-1] > e, i < last and arr[i+1] > e)):
yield e
if __name__ == '__main__':
main()
If you don’t understand anything, ask!
Another approach – using only one function:
def main():
arr = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1]
print(find_peaks(arr))
def find_peaks(arr):
last = len(arr) - 1
return [
e for i, e in enumerate(arr)
if not any((i > 0 and arr[i-1] > e, i < last and arr[i+1] > e))
]
if __name__ == '__main__':
main()
I don't think you can find a peak in O(log N) time, because by definition the items cannot be in order, and there is no way to predict the peaky-ness of any item in a list given other items, except that comparing item N with item N+1 is presumably reflexive - it tells you that either N or N+1 might be a peak. That gets you to N/2 compares, which must then be followed by N/2 more compares to check the other side of the peak.
Here's a local_maxima(iterable) function that you can use with max() to find peaks. It treats start/end elements as peaks if they are greater than their one neighbor.
data = [7, 12, 13, 8, 2, 16, 24, 11, 5, 1, None, 2, None, 3, 4, None, 5, 1, None]
firstpeak = [12, 7, 9, 8]
lastpeak = [1, 2, 3, 4]
def local_maxima(it):
"""Find local maxima in iterable _it_. Compares with None using
`is (not) None`, and using operator `<`."""
peaking = False
last = None
for item in it:
# Deal with last item peaking
if peaking and (item is None or item < last):
yield last
peaking = False
elif item is None:
peaking = False
elif last is None or last < item:
peaking = True
else:
peaking = False
last = item
if peaking:
yield last
print([x for x in local_maxima(data)])
print("Highest:", max(local_maxima(data)))
print([x for x in local_maxima(firstpeak)])
print("Highest:", max(local_maxima(firstpeak)))
print([x for x in local_maxima(lastpeak)])
print("Highest:", max(local_maxima(lastpeak)))