Write an efficient algorithm in python to solve math problem - python

I can't came up with an algorithm to solve the following problem:
Generate an array of first n prime numbers.
Remove k numbers from this array in such way that after concatenating all numbers left we get the largest possible result.
E.G.
Input: 4 2
First value(4) is n
Second value(2) is k
Array [2, 3, 5, 7] is generated
the program have to remove numbers 2 and 3 from this array(to get 57, which is the max possible number we can get from this array after deleting k numbers and merging all the numbers left together).
e.g. If it removes 2 and 7 - we will get 35(which is not the max number). So, this solution is wrong.
Output: 57
This is the code I have so far:
def getInputedVals():
return [int(el) for el in input().split(" ")]
def get_primes_array(x):
primes = []
a = 2
# for a in range(2, 10000):
while(len(primes) != x):
for b in range(2, a):
if a % b == 0:
break
else:
primes.append(a)
a += 1
if len(primes) == x:
return primes
def combine_numbers(nums):
s = [str(i) for i in nums]
return int("".join(s))
# Algorithm to find the max number should be written here
def get_result(nums, n_nums_to_delete):
print("algorithm goes here")
def main(item):
primes = get_primes_array(item["n_first"])
summed = sum(primes)
# print(get_result(primes, item["n_nums_to_delete"]))
print("Primes: ", primes)
n_first, n_nums_to_delete = getInputedVals()
item = {"n_first": n_first, "n_nums_to_delete": n_nums_to_delete}
main(item)

You have the answer, sort your results and take the sorted list starting from the n_nums_to_delete :
def get_result(nums, n_nums_to_delete):
return sorted(nums)[n_nums_to_delete:]
As #Yuri Ginsburg mentioned in the comment, your prime number list is already sorted, so you can simply do :
def get_result(nums, n_nums_to_delete):
return nums[n_nums_to_delete:]

Related

Sum by Factors From Codewars.com

Sinopsis: my code runs well with simple lists, but when I attempt, after the 4 basic test its execution time gets timed out.
Since I don't want to look for others solution, I'm asking for help and someone can show me which part of the code its messing with the time execution in order to focus only into modify that part.
Note: I don't want a finally solution, just know which part of the code I have to change please
Exercise:
Given an array of positive or negative integers
I= [i1,..,in]
you have to produce a sorted array P of the form
[ [p, sum of all ij of I for which p is a prime factor (p positive) of ij] ...]
P will be sorted by increasing order of the prime numbers. The final result has to be given as a string in Java, C# or C++ and as an array of arrays in other languages.
Example:
I = [12, 15] # result = [[2, 12], [3, 27], [5, 15]]
[2, 3, 5] is the list of all prime factors of the elements of I, hence the result.
Notes: It can happen that a sum is 0 if some numbers are negative!
Example: I = [15, 30, -45] 5 divides 15, 30 and (-45) so 5 appears in the result, the sum of the numbers for which 5 is a factor is 0 so we have [5, 0] in the result amongst others.
`
def sum_for_list(lst):
if len(lst) == 0:
return []
max = sorted(list(map(lambda x: abs(x), lst)), reverse = True)[0]
#create the list with the primes, already filtered
primes = []
for i in range (2, max + 1):
for j in range (2, i):
if i % j == 0:
break
else:
for x in lst:
if x % i == 0:
primes.append([i])
break
#i add the sums to the primes
for i in primes:
sum = 0
for j in lst:
if j % i[0] == 0:
sum += j
i.append(sum)
return primes
`
Image
I tried to simplyfy the code as much as I could but same result.
I also tried other ways to iterate in the first step:
# Find the maximum value in the list
from functools import reduce
max = reduce(lambda x,y: abs(x) if abs(x)>abs(y) else abs(y), lst)

Python Program to Print all Numbers in a Range Divisible by a Given Number

Python Program to Print all Numbers in a Range Divisible by a Given Numbers
L=int(input()) #L=[2,4,5] take all input at a time to process with range number divisible with give inputs those numbers print output is 20,40 bcuz of 2,4,5 divisible 20, 40 only
L=int(input))
for i in l:
for j in range(1,50):
if j%i==0:
print(j)
I want out put 20,40
Range divisible with all list l
I'm not sure quite sure what you're asking, but I think the gist of it is that you want to print all numbers in a given range that are divisible by a list.
In that case, there is no need to do a type coercion to int on your list, I'm not sure why you did that.
my_list = [2, 4, 5]
# create an empty output list
output = []
# iterate through a range.
for i in range(1, 50):
# create a boolean array that checks if the remainder is 0 for each
# element in my_list
if all([i % j == 0 for j in my_list]):
# if all statements in the boolean list created above are true
# (number is divisible by all elements in my_list), append to output list
output.append(i)
print(output)
First you need to calculate the least common multiple (lcm) of the numbers in the list. Math library in python 3.9 has included a lcm function, so you can use it. If you dont have python 3.9 you can search some solutions.
import math
lcm = math.lcm(2,4,5)
At this point you know that every integer number that you multiply by 20 is going to be divisible by all the numbers in the list (2 * 20=40, 3 * 20=60 ...). So for a range you must divide the maximum range number (in your case 50) and truncate the result.
high = 50
low = 1
n = int(high/lcm)
Make a loop and multiply from 1 to n by the lcm result. Then for each result check if it is equal or higher than the lower range.
for j in range(1,n):
res = j*lcm
if res >= low:
print(res)
values = int(input('enter value count :'))
n = []
for k in range(values):
temp = int(input('enter int value :'))
n.append(temp)
for i in range(1,50):
count = 0
for j in n:
if i%j == 0:
count=count+1
else:
if count==len(n):
print(i,end=',')

Similarity Measure in Python

I am working on this coding challenge named Similarity Measure. Now the problem is my code works fine for some test cases, and failed due to the Time Limit Exceed problem. However, my code is not wrong, takes more than 25 sec for input of range 10^4.
I need to know what I can do to make it more efficient, I cannot think on any better solution than my code.
Question goes like this:
Problems states that given an array of positive integers, and now we have to answer based upon the Q queries.
Query: Given two indices L,R, determine the maximum absolute difference of index of two same elements lies between L and R
If in a range, there are no two same inputs then return 0
INPUT FORMAT
The first line contains N, no. of elements in the array A
The Second line contains N space separated integers that are elements of the array A
The third line contains Q the number of queries
Each of the Q lines contains L, R
CONSTRAINTS
1 <= N, Q <= 10^4
1 <= Ai <= 10^4
1 <= L, R <= N
OUTPUT FORMAT
For each query, print the ans in a new line
Sample Input
5
1 1 2 1 2
5
2 3
3 4
2 4
3 5
1 5
Sample Output
0
0
2
2
3
Explanation
[2,3] - No two elements are same
[3,4] - No two elements are same
[2,4] - there are two 1's so ans = |4-2| = 2
[3,5] - there are two 2's so ans = |5-3| = 2
[1,5] - there are three 1's and two 2's so ans = max(|4-2|, |5-3|, |4-1|, |2-1|) = 3
Here is my algorithm:
To take the input and test the range in a different method
Input will be L, R and the Array
For difference between L and R equal to 1, check if the next element is equal, return 1 else return 0
For difference more than 1, loop through array
Make a nested loop to check for the same element, if yes, store the difference into maxVal variable
Return maxVal
My Code:
def ansArray(L, R, arr):
maxVal = 0
if abs(R - L) == 1:
if arr[L-1] == arr[R-1]: return 1
else: return 0
else:
for i in range(L-1, R):
for j in range(i+1, R):
if arr[i] == arr[j]:
if (j-i) > maxVal: maxVal = j-i
return maxVal
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Please help me with this. I really want to learn a different and a more efficient way to solve this problem. Need to pass all the TEST CASES. :)
You can try this code:
import collections
def ansArray(L, R, arr):
dct = collections.defaultdict(list)
for index in range(L - 1, R):
dct[arr[index]].append(index)
return max(lst[-1] - lst[0] for lst in dct.values())
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Explanation:
dct is a dictionary that for every seen number keeps a list of indices. The list is sorted so lst[-1] - lst[0] will give maximum absolute difference for this number. Applying max to all this differences you get the answer. Code complexity is O(R - L).
This can be solved as O(N) approximately the following way:
from collections import defaultdict
def ansArray(L, R, arr) :
# collect the positions and save them into the dictionary
positions = defaultdict(list)
for i,j in enumerate(arr[L:R+1]) :
positions[j].append(i)
# create the list of the max differences in index
max_diff = list()
for vals in positions.values() :
max_diff.append( max(vals) - min(vals) )
# now return the max element from the list we have just created
if len(max_diff) :
return max(max_diff)
else :
return 0

How can I find the sum of numbers in a list that are not adjacent to a given number?

Given a list of integers and number, I want to find the sum of all numbers in the list such that numbers and before and after a given number are not added. The given number should also be excluded from the numbers used for the final sum.
Examples:
mylist=[1,2,3,4]
number=2
#output is 4
mylist=[1,2,2,3,5,4,2,2,1,2]
number=2
#output is 5
mylist=[1,7,3,4,1,7,10,5]
number=7
#output is 9
mylist=[1,2,1,2]
number=2
#output is 0
In the first example, only the number 4 is not adjacent to the number 2. Thus the sum is 4. In the last example, no numbers meet the criteria so the sum is 0.
This is what I tried:
def add(list1,num):
for i,v in enumerate(list1):
if v==num:
del list1[i-1:i+2]
print list1
add([1,7,3,4,1,7,10,5],7)
However, my code only works for first and third example.
I worked through your code and here is a working solution:
def check_around(array, index, num):
return True if array[index - 1] != num and array[index + 1] != num else False
def get_result(array, num):
arr = []
for i, number in enumerate(array):
if number != num:
if i == 0 and array[1] != num: # Beginning of list
arr.append(number)
elif (i > 0 and i < len(array) - 1) and check_around(array, i, num): # Middle of list
arr.append(number)
elif i == len(array) - 1 and array[i-1] != num: # End of list
arr.append(number)
return arr
test = [([1,2,3,4], 2),
([1,2,2,3,5,4,2,2,1,2], 2),
([1,7,3,4,1,7,10,5], 7),
([1,2,1,2], 2)]
for (arr, num) in test:
res = get_result(arr, num)
print(f'output is {sum(res)}')
#output is 4
#output is 5
#output is 9
#output is 0
The idea is to create a temp array that saves items that do belong in the summation. Otherwise, we ignore them.
I tried all the tests you gave and it seems to be working fine. Hope this helps.
Get the indexes of the element into a list. +1 and -1 to those will give you indexes of 'before' and 'after' elements. Then take the sum avoiding elements in all these indexes.
list=[1,2,2,3,5,4,2,2,1,2]
number=2
#get all indexes of that number
list_of_indexes=[i for i,x in enumerate(list) if x==number]
#no need to remove -1 if there b'coz we are going to enumerate over 'list'
before_indexes=[i-1 for i in list_of_indexes]
#no need to remove len(list) index if present
after_indexes=[i+1 for i in list_of_indexes]
#might contain duplicate values but no problem
all_indexes_to_avoid=list_of_indexes+before_indexes+after_indexes
sum=sum([x for i,x in enumerate(list) if i not in all_indexes_to_avoid ])
print(sum)
Output
5
Why not just use a if statement and generate a new list instead of removing from the list?
def add(list,num):
j=0
new_list=[]
for i in range(len(list)):
if (i<len(list)-1 and list[i+1]==num) or list[i]==num or list[j]==num:
pass
else:
new_list.append(list[i])
j=i
print(sum(new_list))
print(new_list)
return sum
add([1,2,3,4],2)
add([1,2,2,3,5,4,2,2,1,2],2)
add([1,7,3,4,1,7,10,5],7)
add([1,2,1,2],2)
OUTPUT
4
[4]
5
[5]
9
[4, 5]
0
[]

Multiplying every Nth element in a list by M

I have a problem I can't seem to figure out. I am very new to Python and have only been coding for three weeks. Any help is appreciated.
Problem:
We are passing in 3 inputs:
a list of numbers
a multiplier value, M
a value, N
You should multiply every Nth element (do not multiply the 0th element) by M. So if N is 3, you start with the 3rd element, which is index 2.
If there are less than N elements then you should output the unchanged input list.
I can't seem to figure this out. I have tried many different things here. Currently, I have the following, which is not working at all.
Provided:
import sys
M= int(sys.argv[2])
N= int(sys.argv[3])
numbers= sys.argv[1].split(',')
for i in range(0, len(numbers)):
numbers[i]= int(numbers[i])
My Code:
for N in numbers:
if numbers[i] > 0:
total = N * M
print(total)
else:
print(numbers)
Output:
I am not even close to what the output should be. Feeling lost on this. Here is what my code comes to. It looks like they want the output in a list.
Program Failed for Input: 1,2,3,4,5,6 5 3
Expected Output: [1, 2, 15, 4, 5, 30]
Your Program Output:
5
10
15
20
25
30
You could try a list comprehension with slicing.
numbers[N-1::N] = [x * M for x in numbers[N-1::N]]
A more elegant solution using list comprehensions ;)
[item*M if (index and not (index+1)%N) else item for index, item in enumerate(items)]
This solution is based on your original one. A more pythonic one would use for instance, a list comprehension so keep that in mind in the future,
output = [numbers[0]]
if len(numbers) >= N:
for i in range(1,len(numbers)):
if ((i+1)%N) is 0:
output.append(numbers[i]*M)
else:
output.append(numbers[i]);
else:
output = numbers
If N is not larger than the list size, the program constructs a new list of numbers with each Nth number being multiplied by M. This is done with a simple modulo operator. Indexing in Python starts with zero and i iterates through index values but your desired output counts the elements as if starting from 1 - thus i+1 in the modulo. If it is not every Nth - program just append the old value. If the list is shorter than N altogether, it assigns the whole unchanged list to the output list.
will this work for you?
res = []
for num in numbers:
if num > 0:
total = num * M
res.append(total)
if len(res) != len(numbers):
print (numbers)
else:
res.reverse()
print (res)
So after many attempts and bouncing this off of a friend who works as a programmer, I ended up with this that gave me the proper output:
newlist = []
if len(numbers) < N:
newlist = numbers
else:
for i in range(0, len(numbers)):
num = numbers[i]
if (i+1) % N == 0:
newlist.append(num*M)
else:
newlist.append(num)
i+=1
print(newlist)
# Input
import sys
M= int(sys.argv[2])
N= int(sys.argv[3])
# convert strings to integers
numbers= sys.argv[1].split(',')
for i in range(0, len(numbers)):
numbers[i]= int(numbers[i])
# if the length of our list is greater than our supplied value
# loop to multiply(starting at the 3rd position in the list) by M
if len(numbers) > N :
for num in range(2, len(numbers), 3) :
numbers[num] = numbers[num] * M
print(numbers)

Categories