how to calculate the sum of elements other than the specified indices? - python-3.x

I have a 3*3 array of values
array([[20, 10, 30],
[35, 45, 25],
[15, 25, 35]])
I want to create a function where, when I pass a number argument it should sum all the rows and column elements smaller than the elements which fall on the number.
def sum_con (ar,a):
y=a-1
z=ar[0][0]+ar[0][1]+ar[1][0]+ar[1][1]
return z
sum_con(array,2)
>>110
But you can see this code is not dynamic as it is not scaleable.
Can someone provide code for doing the same functionality for n shaped array.?

For "other than", simply do the sum as usual and subtract/add accordingly:
def sum_con(a, n):
return a.sum() - a[n].sum() - a[:,n].sum() + a[n,n]
This will make the n'th row and column "disappear" when summing.
For "smaller than", it's even easier:
def sum_con_2(a, n):
return a[:n,:n].sum()

Related

Combination of elements in a list leading to a sum K

I have been struggling with a programming problem lately, and I would appreciate any help that I could get.
Basically, the input is a list of numbers (both positive and negative, also, note that the numbers can repeat within the list), and I want to find the combinations of the numbers that lead upto a sum K.
For example,
List - [1,2,3,6,5,-2]
Required sum - 8
Output - Many combinations like : [5,3], [5,2,1], [6,3,1,-2]... and so on
I do understand that there are solutions available to this problem using module functions like “itertools.combinations” or using recursion - subset of sum (works efficiently only for positive numbers on the list), but I am looking for an efficient solution in python3 for lists upto a 100 numbers.
Any and every help would be appreciated.
You are trying to compute the sum over all subsets, not combinations.
This will never be efficient for 100 numbers (atleast in no way I know, either in C++ or in Python), because you need to actually compute all sums, and then filter.
This takes O(n*2^n) time using a method called Dynamic Programming - Sum over Subsets (DP-SOS). The following is the most efficient code possible:
a, k = [1, 2, 3, 6, 5, -2], 8
dp = [0] * (1 << len(a))
for idx, val in enumerate(a):
dp[1 << idx] = a[idx]
for i in range(len(a)):
for mask in range(len(dp)):
if mask & (1 << i):
dp[mask] += dp[mask^(1<<i)]
answer = []
for pos, sum in enumerate(dp):
if sum == k:
answer.append([val for idx, val in enumerate(a)
if (1 << idx) & pos])
Using itertools seems unnecessary to me, though you might get an answer in almost the same (or slightly longer) time, because the bitwise operators even in python are pretty fast.
Nevertheless, using itertools:
from itertools import chain, combinations
a, k = [1, 2, 3, 6, 5, -2], 8
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
answer = list(filter(lambda x: sum(x) == k, powerset(a)))
If you want to scale to 100 numbers, there might not be an exact solution, you would need to use heuristics and not compute the answer explicitly, because if the array is [8, 0, 0, ...(100 times)] then there are 2^99 subsets which you can anyways never compute explicitly or store.

Hi i am new to python and was wondering how do i find the max value in my search algorithm?

Hi so im currently taking discrete structures and algorithm course and have to work with python for the first time so im having a little trouble getting my function find the max value in the list can you take a look at my code because im trying to also convert to pseudocode:
def max_search(numbers):
numbers = [1, 5, 9, 3, 4, 6]
max = numbers = [0]
for i in range(1, len(numbers)):
if numbers[i] > max:
max = numbers[i]
max_search(numbers)
print(max)
Use the max method provided for list
max(numbers)
When you write the code for maximum number in a list, start by thinking of base cases, which will be.
Maximum can be pre-defined constant, say -1 if the list is empty
Maximum is the first element in the list, if the list only has one element.
After that, if the list is longer, you assign the first element of the list as maximum, and then you iterate through the list, updating the maximum if you find a number which is greater than the maximum.
def max_search(numbers):
#Maximum of an empty list is undefined, I defined it as -1
if len(numbers) == 0:
return -1
#Maximum of a list with one element is the element itself
if len(numbers) == 1:
return numbers[0]
max = numbers[0]
#Iterate through the list and update maximum on the fly
for num in numbers:
if num >= max:
max = num
return max
In your case, you are overwriting the numbers argument with another list inside the function [1, 5, 9, 3, 4, 6], and you are recursively calling the same functions with same arguments, which will lead to Stack Overflow
I have made some changes
def max_search(numbers):
max = -1 # if numbers contains all positive number
for i in range(len(numbers)):
if numbers[i] > max:
max = numbers[i]
max = max_search([1, 5, 9, 3, 4, 6])
print(max)

Can't seem to get this for loop to work with range

numbers = [5, 9, 13, 17, 21]
for list in range(5,22,4):
print(numbers[list], end =" ")
Can't seem to get it to work, keep getting
IndexError: list index out of range
Your numbers variable has an index from 0-4 (python starts at 0 and increments from there) - your range command is giving you the numbers:
[5, 9, 13, 17, 21]
You're telling python that you want to go from the number 5 to the number 22, in steps of 4. This means that when you try and print numbers[list], the variable list is actually the index 5 on the iteration of the for loop, and will be outside of the index range of the numbers variable, since it only has indices 0, 1, 2, 3, and 4
Your code seems to confuse two approaches to solving the same task.
One is printing the existing list of numbers:
numbers = [5, 9, 13, 17, 21]
for number in numbers:
print(number, end=" ")
# or, alternatively
for index in range(len(numbers)):
print(numbers[index], end=" ")
Another is generating the same sequence of numbers using range() function:
for number in range(5,22,4):
print(number, end=" ")
# or, reusing one of the previous approaches
numbers = range(5,22,4)
for number in numbers:
print(number, end=" ")
Bear in mind that range() creates a range object, which is suitable for enumeration and indexing, but does not support other list operations like slicing, concatenation and repeating (concatenation with itself). If you want to get numbers as a list, write explicitly:
numbers = list(range(5,22,4))
and then you can do:
for number in numbers * 2:
print(number, end=" ")
which will print your sequence of numbers twice.

Python: Use a for loop to get Nth number out of a list

I need to get every 3rd value out of a list and add it to a new list.
This is what I have so far.
def make_reduced_samples(original_samples, skip):
skipped_list = []
for count in range(0, len(original_samples), skip):
skipped_list.append(count)
return skipped_list
skip is equal to 3
I get the indexes and not the value of the numbers in the list.
It gives me [0,3,6]. Which are the indexes in the list and not the value of the indexes.
The example I am given is:
In this list [12,87,234,34,98,11,9,72], you should get [12,34,9].
I cannot use skipped_list = original_samples[::3] in any way.
You need to append the value of the original_samples array at the index. Not the index (count) itself.
def make_reduced_samples(original_samples, skip):
skipped_list = []
for count in range(0, len(original_samples), skip):
skipped_list.append(original_samples[count])
return skipped_list
The correct, most pythonic, and most efficient way to do that is to use slicing.
lst = [12, 87, 234, 34, 98, 11, 9, 72]
skipped_list = lst[::3]
print(skipped_list) # [12, 34, 9]
If the step does not obey a linear relation (which it does here), then you could use a list-comprehension with enumerate to filter on the index.
skipped_list = [x for i, x in enumerate(lst) if i % 3 == 0]
print(skipped_list) # [12, 34, 9]
One liner:
skipped_list = [j for (i,j) in enumerate(original_samples, start=1) if i % 3 == 0]

Get a list of all number in a certain range containing only certain digits without checking each number

Is there a way to create a list of all numbers less than 10,000 that do not contain any of the digits 0, 2, 4, 5, 6, 8? Of course one can simply type something like:
bads = ['0', '2', '4', '5', '6', '8']
goods = []
for n in range(1, 10000, 2):
if not any(bad in str(n) for bad in bads):
goods.append(n)
However, I'm looking for a method which instead considers the digits 1, 3, 7, 9 and creates all possible unique strings of permutations of these numbers of size 4 or less, duplicate digits allowed. Does itertools, for example, have something that would easily do this? I looked at the permutations method, but that doesn't produce numbers with repeated digits from the collection, and the product method doesn't seem to be what I'm after either, given that it simply would return Cartesian products of 1, 3, 5, 7 with itself.
Here's a simple-minded approach using permutations and combinations_with_replacement from itertools:
from itertools import permutations, combinations_with_replacement
def digit_combinations(power_of_ten):
numbers = set()
for n in range(1, power_of_ten + 1):
for combination in combinations_with_replacement("1379", n):
numbers |= set(permutations(combination, len(combination)))
return sorted(int(''.join(number)) for number in numbers)
print(digit_combinations(4))
OUTPUT
[1, 3, 7, 9, 11, 13, 17, 19, ..., 9971, 9973, 9977, 9979, 9991, 9993, 9997, 9999]
It could be made more space efficient using generators, but depending on the range, it might not be worth it. (For up to 10,000 there are only 340 numbers.) For numbers to 10^4, this code takes roughly as long as your simple example. But for 10^7, this code runs over 40x faster on my system than your simple example.
Could you include your idea for the generator?
Here's a basic rework of the code above into generator form:
from itertools import permutations, combinations_with_replacement
def digit_combinations_generator(power_of_ten):
for n in range(1, power_of_ten + 1):
for combination in combinations_with_replacement("1379", n):
for number in set(permutations(combination, len(combination))):
yield int(''.join(number))
generator = digit_combinations_generator(4)
while True:
try:
print(next(generator), end=', ')
except StopIteration:
print()
break
This does not return the numbers sorted, it just hands them out as fast as it generates them.

Resources