Related
I have a 3 dimensional numpy array (temp_X) like:
[ [[23,34,45,56],[34,45,67,78],[23,45,67,78]],
[[12,43,65,43],[23,54,67,87],[12,32,34,43]],
[[43,45,86,23],[23,45,56,23],[12,23,65,34]] ]
I want to remove the 1st element of each 3rd sub-array (highlighted values).
shown below is the code that i tried:
for i in range(len(temp_X)):
temp_X = np.delete(temp_X[i][(len(temp_X[i]) - 1)], [0])
Somehow when I run the code the whole array gets deleted except for 3 values. Any help is much appreciated. Thank you in advance.
With a as the 3D input array, here's one way -
m = np.prod(a.shape[1:])
n = m-a.shape[-1]
out = a.reshape(a.shape[0],-1)[:,np.r_[:n,n+1:m]]
Alternative to last step with boolean-indexing -
out = a.reshape(a.shape[0],-1)[:,np.arange(m)!=n]
Sample input, output -
In [285]: a
Out[285]:
array([[[23, 34, 45, 56],
[34, 45, 67, 78],
[23, 45, 67, 78]],
[[12, 43, 65, 43],
[23, 54, 67, 87],
[12, 32, 34, 43]],
[[43, 45, 86, 23],
[23, 45, 56, 23],
[12, 23, 65, 34]]])
In [286]: out
Out[286]:
array([[23, 34, 45, 56, 34, 45, 67, 78, 45, 67, 78],
[12, 43, 65, 43, 23, 54, 67, 87, 32, 34, 43],
[43, 45, 86, 23, 23, 45, 56, 23, 23, 65, 34]])
Here's another with mask creation to mask along the last two axes -
mask = np.ones(a.shape[-2:],dtype=bool)
mask[-1,0] = 0
out = np.moveaxis(a,0,-1)[mask].T
I have list of list of integers as shown below:
flst = [[19],
[21, 31],
[22],
[23],
[9, 25],
[26],
[27, 29],
[28],
[27, 29],
[2, 8, 30],
[21, 31],
[5, 11, 32],
[33]]
I want to get the list of integers in increasing order as shown below:
out = [19, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33]
I want to compare every list item with the item/s in next list and get item which is greater than the preceding item:
for ex:
In the list first item is [19] and next list items are [21,31]. Both elements are greater than [19] but [21] is near to [19], so it should be selected.
I'm learning python and tried the following code:
for i in range(len(flst)-2):
for j in flst[i+1]:
if j in range(flst[j], flst[j+2]):
print(j)
Went through many codes for incremental order in stackoverflow, but unable to find any solution.
Try this:
flst[0]=flst[0][0]
for c in range(len(flst)-1):
flst[c+1]=sorted([n for n in flst[c+1] if n>flst[c]],key=lambda x: x-flst[c])[0]
Output (in flst): [19, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33]
as close to one line as I could get
func = lambda x, t=[]: ([t.append(min([i for i in c if i > max([0]+t)])) for (index, c) in enumerate(x)], sorted(t))[1]
func(flst)
[19, 21, 23, 25, 26, 27, 29, 29, 30, 31, 31, 32, 33]
How can I return an array of palindrome numbers in a given array? Not palindromic numbers like 11, 22, 33, 44, &c., but the numbers that are palindromic to other number in the same array. Assume all elements are positive and the result should not return single digit numbers (example below)
Let's say I have array = [13, 31, 51, 79, 83, 97]. Since 13 & 31 and 79 & 97 are palindromes, I want it to return array_pali = [13, 31, 79, 97]
def pali_array(array)
array_reverse = array.map{|el| el.to_s.reverse.to_i}
array_pali = array & array_reverse
return array_pali
end
My initial plan is to come up with a reverse of that array, array_reverse = array.map{|el| el.to_s.reverse.to_i} and intersect them: array & array_reverse
A problem that occur is, if I want to return array of prime numbers from 2-100 as given:
array = [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]
and I reversed it:
array_reverse = array.map{|el| el.to_s.reverse.to_i}
=> [2, 3, 5, 7, 11, 31, 71, 91, 32, 92, 13, 73, 14, 34, 74, 35, 95, 16, 76, 17, 37, 97, 38, 98, 79]
It returns:
array & array_reverse
=> [2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, 97]
The problem with this approach:
2, 3, 5, 7, and 11 are not palindromes to other elements. The reverse of single digit number is that number itself and it causes the code to return all single digit numbers, and all palindromic number (like 11, 22, 33). It should return only [13, 17, 31, 37, 71, 73, 79, 97]
How can I make it to return only elements that are palindromic to other element in the same array?
Here's a very naive and lazy implementation. Doesn't preserve original order of elements. Should be O(N).
I hope the code is self-explanatory.
array = [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]
require 'set'
seen_numbers = Set.new
result = []
array.each do |elem|
next if elem < 10
normal_str = elem.to_s
rev_str = normal_str.reverse
if seen_numbers.include?(rev_str)
result << rev_str.to_i
result << elem
end
seen_numbers << normal_str
end
result # => [13, 31, 17, 71, 37, 73, 79, 97]
Think this works if you want an alternative:
array = [13, 31, 51, 79, 83, 97]
array.combination(2)
.select {|pair| pair.first.to_s == pair.last.to_s.reverse }
.flatten
#=> [13, 31, 79, 97]
Use Array#combination to get every pair combo then we select only those palindrome-pairs. Then just flatten your array.
arr = [7, 13, 31, 51, 31, 60, 70, 13, 79, 83, 79, 97]
Notice that there are various duplicate values in arr.
arr.reject { |n| n < 10 || (n%10).zero? }.
group_by { |n| n.to_s.each_char.sort }.
values.
reject { |arr| arr.size == 1 }.
flat_map { |arr| arr.group_by(&:itself).values.min_by(&:size) }
#=> [13, 13, 97]
The matching values are easy enough to calculate if required.
|| (n%10).zero? was added just to speed things up a bit.
The steps are as follows.
a = arr.reject { |n| n < 10 || (n%10).zero? }
#=> [13, 31, 51, 31, 13, 79, 83, 79, 97]
b = a.group_by { |n| n.to_s.each_char.sort }
#=> {["1", "3"]=>[13, 31, 31, 13], ["1", "5"]=>[51],
# ["7", "9"]=>[79, 79, 97], ["3", "8"]=>[83]}
c = b.values
#=> [[13, 31, 31, 13], [51], [79, 79, 97], [83]]
d = c.reject { |arr| arr.size == 1 }
#=> [[13, 31, 31, 13], [79, 79, 97]]
d.flat_map { |arr| arr.group_by(&:itself).values.min_by(&:size) }
#=> [13, 13, 97]
Consider the last step. flat_map passes the first element of d to its block and sets the block variable to that value:
arr = d[0]
#=> [13, 31, 31, 13]
and performs the block calculation:
e = arr.group_by(&:itself)
#=> {13=>[13, 13], 31=>[31, 31]}
f = e.values
#=> [[13, 13], [31, 31]]
f.min_by(&:size)
#=> [13, 13]
Next,
arr = d[1]
#=> [79, 79, 97]
e = arr.group_by(&:itself)
#=> {79=>[79, 79], 97=>[97]}
f = e.values
#=> [[79, 79], [97]]
f.min_by(&:size)
#=> [97]
flat_map therefore returns
[*[13, 13], *[97]]
#=> [13, 13, 97]
I have 100 3x3x3 matrices that I would like to multiply with another large matrix of size 3x5x5 (similar to convolving one image with multiple filters, but not quite).
For the sake of explanation, this is what my large matrix looks like:
>>> x = np.arange(75).reshape(3, 5, 5)
>>> x
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, 72, 73, 74]]])
In memory, I assume all sub matrices in the large matrix are stored in contiguous locations (please correct me if I'm wrong). What I want to do is, from this 3x5x5 matrix, I want to extract 3 5x3 columns from each sub-matrix of the large matrix and then join them horizontally to get a 5x9 matrix (I apologise if this part is not clear, I can explain in more detail if need be). If I were using numpy, I'd do:
>>> k = np.hstack(np.vstack(x)[:, 0:3].reshape(3, 5, 3))
>>> k
array([[ 0, 1, 2, 25, 26, 27, 50, 51, 52],
[ 5, 6, 7, 30, 31, 32, 55, 56, 57],
[10, 11, 12, 35, 36, 37, 60, 61, 62],
[15, 16, 17, 40, 41, 42, 65, 66, 67],
[20, 21, 22, 45, 46, 47, 70, 71, 72]])
However, I'm not using python so I do not have any access to the numpy functions that I need in order to reshape the data blocks into a form I want to carry out multiplication... I can only directly call the cblas_sgemm function (from the BLAS library) in C, where k corresponds to input B.
Here's my call to cblas_sgemm:
cblas_sgemm( CblasRowMajor, CblasNoTrans, CblasTrans,
100, 5, 9,
1.0,
A, 9,
B, 9, // this is actually wrong, since I don't know how to specify the right parameter
0.0,
result, 5);
Basically, the ldb attribute is the offender here, because my data is not blocked the way I need it to be. I have tried different things, but I am not able to get cblas_sgemm to understand how I want it to read and understand my data.
In short, I don't know how to tell cblas_sgemm to read x like k.Is there a way I can smartly reshape my data in python before sending it to C, so that cblas_sgemm can work the way I want it to?
I will transpose k by setting CblasTrans, so during multiplication, B is 9x5. My matrix A is of shape 100x9. Hope that helps.
Any help would be appreciated. Thanks!
In short, I don't know how to tell cblas_sgemm to read x like k.
You can't. You'll have to make a copy.
Consider k:
In [20]: k
Out[20]:
array([[ 0, 1, 2, 25, 26, 27, 50, 51, 52],
[ 5, 6, 7, 30, 31, 32, 55, 56, 57],
[10, 11, 12, 35, 36, 37, 60, 61, 62],
[15, 16, 17, 40, 41, 42, 65, 66, 67],
[20, 21, 22, 45, 46, 47, 70, 71, 72]])
In a two-dimensional array, the spacing of the elements in memory must be the same in each axis. You know from how x was created that the consecutive elements in memory are 0, 1, 2, 3, 4, ..., but your first row of k contains 0, 1, 2, 25, 26, ..... The is no spacing between 1 and 2 (i.e. the memory address increases by the size of one element of the array), but there is a large jump in memory between 2 and 25. So you'll have to make a copy to create k.
Having said that, there is an alternative method to efficiently achieve your desired final result using a bit of reshaping (without copying) and numpy's einsum function.
Here's an example. First define x and A:
In [52]: x = np.arange(75).reshape(3, 5, 5)
In [53]: A = np.arange(90).reshape(10, 9)
Here's my understanding of what you want to achieve; A.dot(k.T) is the desired result:
In [54]: k = np.hstack(np.vstack(x)[:, 0:3].reshape(3, 5, 3))
In [55]: A.dot(k.T)
Out[55]:
array([[ 1392, 1572, 1752, 1932, 2112],
[ 3498, 4083, 4668, 5253, 5838],
[ 5604, 6594, 7584, 8574, 9564],
[ 7710, 9105, 10500, 11895, 13290],
[ 9816, 11616, 13416, 15216, 17016],
[11922, 14127, 16332, 18537, 20742],
[14028, 16638, 19248, 21858, 24468],
[16134, 19149, 22164, 25179, 28194],
[18240, 21660, 25080, 28500, 31920],
[20346, 24171, 27996, 31821, 35646]])
Here's how you can get the same result by slicing x and reshaping A:
In [56]: x2 = x[:,:,:3]
In [57]: A2 = A.reshape(-1, 3, 3)
In [58]: einsum('ijk,jlk', A2, x2)
Out[58]:
array([[ 1392, 1572, 1752, 1932, 2112],
[ 3498, 4083, 4668, 5253, 5838],
[ 5604, 6594, 7584, 8574, 9564],
[ 7710, 9105, 10500, 11895, 13290],
[ 9816, 11616, 13416, 15216, 17016],
[11922, 14127, 16332, 18537, 20742],
[14028, 16638, 19248, 21858, 24468],
[16134, 19149, 22164, 25179, 28194],
[18240, 21660, 25080, 28500, 31920],
[20346, 24171, 27996, 31821, 35646]])
I have a string of digits:
s = "12345678910"
As you can see it is the numbers 1 through 10 listed in increasing order. I want to convert it to an array of those numbers:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
How can I do it?
How about this:
a = ["123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"]
b = a.first.each_char.map {|n| n.to_i }
if b.size > 8
c = b[0..8]
c += b[9..b.size].each_slice(2).map(&:join).map(&:to_i)
end
# It would yield as follows:
[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, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
For later numbers beyond 99, modify existing predicate accordingly.
Assuming a monotonic sequence, here's my run at it.
input = a.first.chars
output = []
previous_int = 0
until input.empty?
temp = []
temp << input.shift until temp.join.to_i > previous_int
previous_int = temp.join.to_i
output << previous_int
end
puts output.to_s
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Assumptions
the first (natural) number extracted from the string is the first character of the string converted to an integer;
if the number n is extracted from the string, the next number extracted, m, satisfies n <= m (i.e., the sequence is monotonically non-decreasing);
if n is extracted from the string, the next number extracted will have as few digits as possible (i.e., at most one greater than the number of digits in n); and
there is no need to check the validity of the string (e.g., "54632" is invalid).
Code
def split_it(str)
return [] if str.empty?
a = [str[0]]
offset = 1
while offset < str.size
sz = a.last.size
sz +=1 if str[offset,sz] < a.last
a << str[offset, sz]
offset += sz
end
a.map(&:to_i)
end
Examples
split_it("12345678910")
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
split_it("12343636412252891407189118901")
#=> [1, 2, 3, 4, 36, 36, 41, 225, 289, 1407, 1891, 18901]