I want to get idexes of elemenent into 2d array by square shape
Some more info:
Let's pretend that i need get indexes of one element of 2d array
22 33 15
65 32 16
84 26 12
Index of '33' is 01
I want get all nearest elements of it, its: 22, 65, 32, 16, 15 and indexes is: 00, 10, 11, 12, 02
So, i want get indexes like that of any element of array
So x2, for 00 elemnts its 3 neighbor, for 01 its 5 and for 11 its 8 neighbors
And some more:
How can i handle out of index value?
Sorry for my bad english
Try this:
# example 2d arr
arr = [[22, 33, 15], [65, 32, 16], [84, 26, 12]]
# print
for row in arr:
for col in row:
print(col, end = " ")
print()
def getNeighbours(x, y, arr):
string = f'({x}, {y}): {arr[y][x]}'
neighbours = []
# get lengths for if check
col_length = len(arr)
row_length = len(arr[0])
# distance options for x, y; loop
for x_distance in [-1, 0, 1]:
for y_distance in [-1, 0, 1]:
# +0 and +0 == cur_position, so exclude
# new x/y < 0 would be out of bounds, so exclude
# new x/y == respective length would be out of bounds, so exclude
# all else ok, hence: 'if not'
if not ((x_distance == 0 and y_distance == 0) or \
(y+y_distance < 0 or y+y_distance == col_length) or \
(x+x_distance < 0 or x+x_distance == row_length)):
neighbours.append(arr[y+y_distance][x+x_distance])
return string, neighbours
# tests
result = getNeighbours(1, 0, arr)
print(result)
result = getNeighbours(1, 1, arr)
print(result)
result = getNeighbours(2, 1, arr)
print(result)
Output:
22 33 15
65 32 16
84 26 12
('(1, 0): 33', [22, 65, 32, 15, 16])
('(1, 1): 32', [22, 65, 84, 33, 26, 15, 16, 12])
('(2, 1): 16', [33, 32, 26, 15, 12])
Update: if speed is a concern, go with the numpy solution offered by Mechanic Pig.
To clarify the if logic a little bit, we could also have written something like this:
# distance options for x, y; loop
for x_distance in [-1, 0, 1]:
for y_distance in [-1, 0, 1]:
# x, y coordinates for a potential neighbour
new_x = x + x_distance
new_y = y + y_distance
if (x_distance == 0 and y_distance == 0):
# this will lead to the element itself, so ignore
continue
elif new_x < 0 or new_x == row_length:
# new_x should fall in range(row_length), so ignore
continue
elif new_y < 0 or new_y == col_length:
# same for y: new_y should fall in range(col_length), so ignore
continue
else:
# any other combination of ( new_x, new_y ) is OK; append element
neighbours.append(arr[new_y][new_x])
Since we simply want to continue after if and 2x elif, we could refactor this and say: if not (cond1 or cond2 or cond3): neighbours.append(), as above.
Consider using numpy.
import numpy as np
arr = np.array([[22, 33, 15], [65, 32, 16], [84, 26, 12]])
row, col = 0, 1
rows, cols = np.indices(arr.shape)
mask = np.maximum(np.abs(rows - row), np.abs(cols - col)) == 1
print(rows[mask], cols[mask])
# [0 0 1 1 1] [0 2 0 1 2]
print(arr[rows[mask], cols[mask]])
# [22 15 65 32 16]
I think you can master it with a little study. It's much faster than loop, and you don't need to consider the boundary problem.
Related
I am a high school student. By observing the inputted sequence, I want to create a program that creates general formulas on quadratic to a polynomial with nth power equations. This posted code will function as a means of validation for inputted sequences. If you have a better code, please help me. Thank You!
The same concept was shown below,
here is my code
def shrink(numbers):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers)
if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
print(n2)
if(len(n2) > 1):
return shrink(n2)
return n
#shrink([1, 8, 27, 64, 125, 216])
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
shrink(b)
"""
The output will be:
[7, 19, 37, 61, 91]
[12, 18, 24, 30]
[6, 6, 6]
[0, 0]
[0]
"""
#I want the output from the top to be like this!
d = [
[7, 19, 37, 61, 91],
[12, 18, 24, 30],
[6, 6, 6],
[0, 0],
[0]
]
if d[2][0] == d[2][1]:
print('cubic sequence')
During the first call you initialize a list variable which you update and pass to the recursive call
def shrink(numbers,return_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
return_list.append(n2)
if(len(n2) > 1):
return shrink(n2,return_list)
else:
return return_list
print(shrink([1, 8, 27, 64, 125, 216]))
If you want the values of n1 as well :
def shrink(numbers,n1_list = [], n2_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
n1_list.append(n1)
n2_list.append(n2)
# print(n2)
if(len(n2) > 1):
return shrink(n2,n1_list,n2_list)
else:
return n1_list,n2_list
print(shrink([1, 8, 27, 64, 125, 216]))
Thank You Atharva Gundawar.
If you want the list to be inputted, this is the answer:
Take note that input list should be separated by space and not by a comma.
Sample input: 1 8 27 64 125 216
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
c = shrink(b)
print(shrink(b))
print(c[2][0])
print(c[2][1])
if c[2][0] == c[2][1]:
print('cubic sequence')
Input:
1 8 27 64 125 216
Output:
[[7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0], [7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0]]
6
6
cubic sequence
This is the correct answer to eradicate the loop:
https://stackoverflow.com/posts/70423499/revisions
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
input_user = input("Enter data:")
b = input_user.split()
for num in range(len(b)):
b[num] = int(b[num])
c = shrink(b)
print(c)
If the length of the given array is 6 and the value of k is 7 then the resultant array should be like this [20, 30, 40, 50, 60, 10]. My work.
source = [10, 20, 30, 40, 50, 60]
def rotateLeft(array, k):
tempArray = [0] * len(array)
flag = k
j = len(array)
temp = k - len(array) - 1
temp2 = len(array) - 1
for i in range(j):
tempArray[i] = source[i]
if i + k < j:
source[i] = source[i + k]
source[flag] = tempArray[i]
flag += 1
//Before this everything is alright.
elif k > len(array):
while temp2 >= temp:
source[temp2] = source[temp2 - temp]
temp2 -= 1
print(source)
rotateLeft(source, 7)
Output is [10, 20, 30, 40, 50, 60]. Expected [20, 30, 40, 50, 60, 10].
Can anyone help!!Thank you.
How about using modulus division
k=k%len(array)
This would make k the number of places that the array needs to move by. Since after this operation 0 <= k < len(array) you can shift the array with
array = array[k:] + array [:k]
The objective is to obtain distribution lists that allow, for example, to test scenarios by weighting variables with different familiar weights whose sum is equal to 100 (and therefore assimilable to percentages).
The method I propose below works but may not be the best. Feel free to suggest any improvement.
Function for integer compositions into n parts:
def comppercents(n):
y = [0] * n
y[0] = 100
while True:
yield(y)
v = y[-1]
if (100 ==v ):
break
y[-1] = 0
j = -2
while (0==y[j]):
j -= 1
y[j] -= 10
y[j+1] = 10 + v
for x in comppercents(3):
print(x)
[100, 0, 0]
[90, 10, 0]
[90, 0, 10]
[80, 20, 0]
...
[0, 20, 80]
[0, 10, 90]
[0, 0, 100]
(66 variants)
from itertools import groupby
def comb_100(n):
global L_combination_100
L_combination_100= []
# adds in L_combination_100 all the possible lists (without the order mattering) whose sum of the elements is 10
find_raw_combination([i+1 for i in list(range(10))]*10,10)
# we remove all duplicate lists
for i in range(len(L_combination_100)):
L_combination_100[i].sort()
L_combination_100.sort()
L_combination_100 = list(k for k,_ in groupby(L_combination_100)) # groupby from itertools
# We remove all lists that have too many elements (> n)
L_combination_100 = [i if len(i)<=n else [] for i in L_combination_100]
L_combination_100 = [x for x in L_combination_100 if x != []]
# We add 0's to lists that don't have n items
# All items within each list are multiplied by 10 to obtain a sum equal to 100
for i,l in enumerate(L_combination_100) :
if len(l) != n:
L_combination_100[i].extend([0]*(n-len(l)))
L_combination_100[i] = [ii*10 for ii in L_combination_100[i]]
#That's how we got our final list of lists/combinations. We have to be careful that the order doesn't matter in these lists.
return L_combination_100
#Strongly inspired from https://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum
def find_raw_combination(numbers, target, partial=[]): # need global variable L_combination_100
s = sum(partial)
# check if the partial sum is equals to target
if s == target:
L_combination_100.append(partial) if partial not in L_combination_100 else L_combination_100
if s >= target:
return # reach if we get the number
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
find_raw_combination(remaining, target, partial + [n])
Example :
comb_100(3)
Output :
[[10, 10, 80],
[10, 20, 70],
[10, 30, 60],
[10, 40, 50],
[10, 90, 0],
[20, 20, 60],
[20, 30, 50],
[20, 40, 40],
[20, 80, 0],
[30, 30, 40],
[30, 70, 0],
[40, 60, 0],
[50, 50, 0],
[100, 0, 0]]
I have a 2D array of integer value:
[[26, 9, 24, 13],
[16, 14, 39, 29]]
I need to select the number >= 14, ends in 9 or 4, and not 39. It returns 1 if the criteria meets, otherwise return 0, i.e.
[[0, 0, 1,0],
[0,0,0,1]]
updated: code suggested by Tomothy32
result = result = [[int(x >= 14 and x % 10 in (4, 9) and x != 19) for x in sl] for sl in X]
another nested loop approach
def test(X):
out = [[0]*len(X[0]) for _ in range(len(X))]
for i in range(len(X)):
for j in range(len(X[i])):
check = X[i][j]
if check>=14 and check%5==4 and check!=39:
out[i][j] = 2
return out
You can use a list comprehension:
x = [[26, 9, 43, 13],
[16, 14, 39, 29]]
result = [[int(x >= 14 and x % 10 == 9 and x != 39) for x in sl] for sl in x]
print(result)
# [[0, 0, 0, 0], [0, 0, 0, 1]]
To get the last digit, use the remainder/modulo operator.
Change this statements:
if element >=14 and element !=39:
to
if element >=14 and element !=39 and element%10==9:
Check nested list elementwise for multiple conditions and return 0 or 1 if condition is not met or is met.
I have to check
at least 14
cannot be equal to= 19
if the element ends in 4 or 9
For example, age array of
[[22, 13, 31, 13],
[17, 14, 24, 22]]
will have the output array as
[[0, 0, 0, 0],
[0, 1, 1, 0]]
I've tried flattening the list and then checking each condition, but it's not working.
flat_list = [item for sublist in age for item in sublist]
x=14
[not x for x in flat_list]
There's a faster numpy solution:
((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int)
Code:
import numpy as np
arr = np.array([[22, 13, 31, 13],
[17, 14, 24, 22]])
print(((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int))
# [[0 0 0 0]
# [0 1 1 0]]
You could do it with list comprehensions like so:
somelist = [[22, 13, 31, 13],
[17, 14, 24, 22]]
result = [[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]
result
[[0, 0, 0, 0], [0, 1, 1, 0]]
Where x%10 will get the last digit in each number, allowing the direct comparison. By grouping the two conditions, you can more logically lay out what you want to do, though this gets a bit messy for a list comprehension.
A better way (at the potential expense of speed) might be to use map:
def check_num(num):
value_check = num >= 14 and num != 19
last_num_check = num % 10 == 4 or num % 10 == 9
return int(value_check and last_num_check)
somelist = [[22, 13, 31, 13],
[17, 14, 24, 22]]
result = [[x for x in map(check_num, sublist)] for sublist in somelist]
result
[[0, 0, 0, 0], [0, 1, 1, 0]]
Timing the difference between operations:
List Comprehension
python -m timeit -s 'somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]'
1000000 loops, best of 3: 1.35 usec per loop
Map
python -m timeit -s 'from somefunc import check_num; somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[x for x in map(check_num, sublist)] for sublist in somelist]'
100000 loops, best of 3: 3.37 usec per loop
C.Nvis has a good answer with list comprehension. You can also solve this using nested for loops
def is_valid(x):
return (x == 14) or (x%10 == 4) or (x%10 == 9)
out = []
for sublist in matrix:
out_sublist = []
for i in sublist:
if (is_valid(i)):
out_sublist.append(1)
else:
out_sublist.append(0)
out.append(out_sublist)
print(out)
These answers are effectively the same algorithm.
Just for your example it can be done with a bit of mapping.
The way you can verify that the last digit equals to a number is by applying a modulo-10 on the number.
my_list = [[22, 13, 31, 13],[17, 14, 24, 22]]
result_list = []
for sublist in my_list:
result_list.append(list(map(lambda x: 1 if x % 10 == 4 and x >= 14 and x != 19 else 0, sublist)))
print(result_list)
will yield:
[[0, 0, 0, 0], [0, 1, 1, 0]]