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)
Related
write a function named sums that takes 3 arguments: 2 lists of integers nums1 and nums2, and an integer target; then return a tuple containing indices i and j of the two numbers in nums1 and nums2, respectively, where the numbers at that indices add up to target (i.e, nums1[i] + num2[j] = target). If there is no solution, return “Not found”. The function sums must contain exactly only one loop (either a for-loop or a while-loop), otherwise you will get no point. A nested-loop is considered as more than one loop.
def sums(nums1, nums2, target):
nums1 = [11, 2, 15, 7, 8]
nums2 = [2, 3, 4, 5]
target_number = 9
for i in range(len(nums1)):
for j in range(len(nums2)):
total = nums1[i] + nums2[j]
if total == target:
a = (nums1[i], nums2[j])
print(a)
This is the code that i have written and i am struggling to get the index values can anyone please help!
You can solve it in O(n) with a dictionary and a single for loop;
nums1 = [11, 2, 15, 7, 8]
nums2 = [2, 3, 4, 5]
target_number = 9
def sums(nums1, nums2, target):
d = dict(zip(nums2, range(len(nums2))))
for i,n in enumerate(nums1):
remainder = target-n
if remainder in d:
return (i, d[remainder])
return 'Not found'
sums(nums1, nums2, target_number)
Output: (3, 0)
Be aware that while there is a single for loop, the code is looping to construct the dictionary, it's just not visible directly.
Here's an alternative solution using basic index incrementing. It's not as efficient as using a dictionary and finding the difference, as this naively iterates over b as many times as there are items in a. In the worst case, with two equal-length lists, this solution is O(n^2).
Although it may actually be faster in smaller cases, if there happens to be a bottlneck around the creation of any of the intermediate data structures that #mozway uses. I'm only speculating on this, I don't actually know.
def target_sum_idxs(a, b, target):
i = j = 0
while i < len(a):
if a[i] + b[j] == target:
return i, j
j += 1
if j == len(b):
i += 1
j = 0
return "Not found"
Demo:
>>> target_sum_idxs(nums1, nums2, target=9)
(3, 0)
>>> target_sum_idxs(nums2, nums1, target=9)
(0, 3)
>>> target_sum_idxs(nums1, nums2, target=999)
'Not found'
just one little thing.
Check that the variable in the if statement is really your parameter, not the "target_number" variable.
Also, in the if statement, you need to stop execution, maybe you can use a break or return the tuple.
I would use something like this:
def sums(nums1, nums2, target):
for i in range(len(nums1)):
for j in range(len(nums2)):
total = nums1[i] + nums2[j]
if total == target:
a = (i, j)
return a
return "Not found"
Function to find minimum number of eliminations such that sum of all adjacent elements is even:
def min_elimination(n, arr):
countOdd = 0
# Stores the new value
for i in range(n):
# Count odd numbers
***if (arr[i] % 2):
countOdd += 1***
# Return the minimum of even and
# odd count
return min(countOdd, n - countOdd)
# Driver code
if __name__ == '__main__':
arr = [1, 2, 3, 7, 9]
n = len(arr)
print(min_elimination(n, arr))
Please help me with the if condition. When the code does if(number%2) then control is going inside the if since the first element of list is an odd number. Is there any difference between if(number%2) and if(number%2==0). Because when I tried if(number%2==0) control didn't go inside the if as the number was odd (check first element of the list).
This is a simple version of the above.
def min_elimination(arr):
lst1 = [n for n in arr if n%2] # List of all odd numbers
lst2 = [n for n in arr if not n%2] # List of all even numbers
lst = max(lst1, lst2, key=lambda x: len(x))
return lst
print(min_elimination([1, 2, 3, 7, 9]))
I believe your code works fine as-is. It correctly returns the minimum number of eliminations necessary to achieve the result, not the result itself.
is there any difference between if(number%2) and if(number%2==0)
Yes, if number % 2 is the same as saying if number % 2 == 1, which is the opposite of saying if number % 2 == 0. So switching one for the other will break your program's logic.
I might simplify your code as follows:
def min_elimination(array):
odd = 0
# Stores the new value
for number in array:
# Count odd numbers
odd += number % 2
return min(odd, len(array) - odd)
Where min_elimination([1, 2, 3, 7, 9]) returns 1, there is one (1) elimination necessary to make the sum of all adjacent elements even.
The only way two integers can add up to be even is that both integers should be odd, or both integers should be even. So your question basically wants to find whether there are more odd number in the array, or even numbers:
def min_elimination(arr):
return len(min([n for n in arr if n%2],[n for n in arr if not n%2],key=len))
print(min_elimination([1, 2, 3, 7, 9]))
Output:
1
You can use numpy to compare the number of odd numbers in the array to the number of even numbers in the array:
import numpy as np
def min_elimination(arr):
return len(min(arr[arr%2],arr[any(arr%2)],key=len))
print(min_elimination(np.array([1, 2, 3, 7, 9])))
Output:
1
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:]
I am having an issue where I have been given an array of numbers [1,3,5] and need to find the least amount of numbers that could add to a specific number. Each number has a weight and I need to calculate the most efficient. For example if the number was 6 I would need to use [5,1] instead of [3,3] as 5 has a greater importance. In the case of 12 it would be [5,5,1,1] instead of [3,3,3,3]
I have already tried implementing dictionaries and arrays but the problem solving part is what I am having trouble with.
A valid way to do it, not relying on the presence of 1 in the list, is to try to use as many of the largest numbers as possible, and recursively try to obtain the remainder:
If no solution can be found, the function will return None
def solve(numbers, target):
'''Return a list of the largest of numbers whose sum is target,
None if impossible'''
if not numbers:
return None
# make sure that numbers is sorted
numbers = list(sorted(numbers))
# get the largest number and remove it from the list
largest = numbers.pop()
# we start with as many times the largest number as possible
quotient, remainder = divmod(target, largest)
# did we reach the target?
if remainder == 0:
return [largest] * quotient
# if not, try with a deacreasing number of times the largest
# (including 0 times)
for n in range(quotient, -1, -1):
remainder = target - n * largest
# and recursively try to obtain the remainder with the remaining numbers
solution = solve(numbers, remainder)
if solution:
return [largest] * n + solution
else:
return None
Some tests:
solve([1, 3, 5], 12)
# [5, 5, 1, 1]
solve([3, 5], 12) # no 1, we have to use smaller numbers
# [3, 3, 3, 3]
solve([7, 3, 4], 15)
# [7, 4, 4]
solve([3, 4], 5) # Impossible
# None
Keep looping, until n = 0, by taking away the largest number, then smaller numbers if n < 0.
As pointed out by Thierry Lathuille, This will probably not work if there is no 1 in your array. If that is the case, you might want to fiddle with the if n < 0 lines.
n = int(input())
a = [1, 3, 5]
ans = []
while n > 0:
n -= max(a)
if n == 0:
ans.append(max(a))
break
if n > 0:
ans.append(max(a))
if n < 0:
n += max(a)
a.pop(a.index(max(a)))
print(ans)
I am trying to do a challenge in Python, the challenge consists of :
Given an array X of positive integers, its elements are to be transformed by running the following operation on them as many times as required:
if X[i] > X[j] then X[i] = X[i] - X[j]
When no more transformations are possible, return its sum ("smallest possible sum").
Basically you pick two non-equal numbers from the array, and replace the largest of them with their subtraction. You repeat this till all numbers in array are same.
I tried a basic approach by using min and max but there is another constraint which is time. I always get timeout because my code is not optimized and takes too much time to execute. Can you please suggest some solutions to make it run faster.
def solution(array):
while len(set(array)) != 1:
array[array.index(max(array))] = max(array) - min(array)
return sum(array)
Thank you so much !
EDIT
I will avoid to spoil the challenge... because I didn't find the solution in Python. But here's the general design of an algorithm that works in Kotlin (in 538 ms). In Python I'm stuck at the middle of the performance tests.
Some thoughts:
First, the idea to remove the minimum from the other elements is good: the modulo (we remove the minimum as long as it is possible) will be small.
Second, if this minimum is 1, the array will be soon full of 1s and the result is N (the len of the array).
Third, if all elements are equal, the result is N times the value of one element.
The algorithm
The idea is to keep two indices: i is the current index that cycles on 0..N and k is the index of the current minimum.
At the beginning, k = i = 0 and the minimum is m = arr[0]. We advance i until one of the following happen:
i == k => we made a full cycle without updating k, return N*m;
arr[i] == 1 => return N;
arr[i] < m => update k and m;
arr[i] > m => compute the new value of arr[i] (that is arr[i] % m or m if arr[i] is a multiple of m). If thats not m, thats arr[i] % m < m: update k and m;
arr[i] == m => pass.
Bascially, we use a rolling minimum and compute the modulos on the fly until all element are the same. That spares the computation of a min of the array periodically.
PREVIOUS ANSWER
As #BallpointBen wrote, you'll get the n times the GCD of all numbers. But that's cheating ;)! If you want to find a solution by hand, you can optimize your code.
While you don't find N identical numbers, you use the set, max (twice!), min and index functions on array. Those functions are pretty expensive. The number of iterations depend on the array.
Imagine the array is sorted in reverse order: [22, 14, 6, 2]. You can replace 22 by 22-14, 14 by 14-6, ... and get: [8, 12, 4, 2]. Sort again: [12, 8, 4, 2], replace again: [4, 4, 4, 2]. Sort again, replace again (if different): [4, 4, 2, 2], [4, 2, 2, 2], [2, 2, 2, 2]. Actually, in the first pass 14 could be replaced by 14-2*6 = 2 (as in the classic GCD computation), giving the following sequence:
[22, 14, 6, 2]
[8, 2, 2, 2]
[2, 2, 2, 2]
The convergence is fast.
def solution2(arr):
N = len(arr)
end = False
while not end:
arr = sorted(arr, reverse=True)
end = True
for i in range(1, N):
while arr[i-1] > arr[i]:
arr[i-1] -= arr[i]
end = False
return sum(arr)
A benchmark:
import random
import timeit
arr = [4*random.randint(1, 100000) for _ in range(100)] # GCD will be 4 or a multiple of 4
assert solution(list(arr)) == solution2(list(arr))
print(timeit.timeit(lambda: solution(list(arr)), number=100))
print(timeit.timeit(lambda: solution2(list(arr)), number=100))
Output:
2.5396839629975148
0.029025810996245127
def solution(a):
N = len(a)
end = False
while not end:
a = sorted(a, reverse=True)
small = min(a)
end = True
for i in range(1, N):
if a[i-1] > small:
a[i-1] = a[i-1]%small if a[i-1]%small !=0 else small
end = False
return sum(a)
made it faster with a slight change
This solution worked for me. I iterated on the list only once. initially I find the minimum and iterating over the list I replace the element with the rest of the division. If I find a rest equal to 1 the result will be trivially 1 multiplied by the length of the list otherwise if it is less than the minimum, i will replace the variable m with the minimum found and continue. Once the iteration is finished, the result will be the minimum for the length of the list.
Here the code:
def solution(a):
L = len(a)
if L == 1:
return a[0]
m=min(a)
for i in range(L):
if a[i] != m:
if a[i] % m != 0:
a[i] = a[i]%m
if a[i]<m:
m=a[i]
elif a[i] % m == 0:
a[i] -= m * (a[i] // m - 1)
if a[i]==1:
return 1*L
return m*L