Prime factorization of a number - python-3.x

I'm trying to write a program to find all the prime factors of a given number, and tried the following:
def factors(nr):
i = 2
factors = []
while i<nr:
if (nr%i)==0:
factors.append(i)
nr = nr/i
else:
i = i+1
return factors
My idea is the following. Start with i = 2, while i < the number, check if the module of the number and i = 0. If this is the case, add i to a list, and run the algorithm again, but now with the new number. However, my algorithm doesn't work. Any idea why?
I know that several right answers are posted on the site, but I would like to know why my program is incorrect.
Update
So if I let the programm run for example:
factors(38), yields [2].
factors(25), yields [5].
So it stops after it has added one number to the list.

The simplest change you can make to fix your problem is to change your while loop condition:
def factors(nr):
i = 2
factors = []
while i <= nr:
if (nr % i) == 0:
factors.append(i)
nr = nr / i
else:
i = i + 1
return factors
print factors(8)
print factors(9)
print factors(10)
Output
[2, 2, 2]
[3, 3]
[2, 5]

def ba(n):
pfa=[]
y=n
for i in range(n):
if (i!=0 and i!=1):
while (y%i==0):
pfa.append(i)
y=y/i
print(pfa)

Related

I want to fine 6th prime number. why execution is stuck after 3?

Q:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10001st prime number?
My code is:
def is_prime(num):
if all(num % i != 0 for i in range(2, num)):
return True
else:
return False
def find_nth_prime(nth):
lst_prime = []
num = 2
while len(lst_prime) < nth:
if is_prime(num):
lst_prime.append(num)
print(len(lst_prime), ":", lst_prime[-1])
num += 1
When I try to run find_nth_prime(6) it get stuck after finding "3" as prime. What am I missing here?
In your if statement inside while loop it keeps repeating at n=4 since n +=1 never happens as 4 is not a prime. Therefore take it out of the if statement.
Try using https://pythontutor.com/. It helps you visualize your code
def find_nth_prime(nth):
lst_prime = []
num = 2
while len(lst_prime) < nth:
if is_prime(num):
lst_prime.append(num)
print(len(lst_prime), ":", lst_prime[-1])
num += 1
Also you can do some improvments to your is_prime function. In that you don't have to take the whole range (2, num). It is enough to take the range 2 to square root of num. (2,int(num**0.5)+1) or use sqrt from python's math library

How to add each element in list to another element of same list in less time?

Input : l1 = [1,2,3,4,5,6]
Output : [7, 8, 9, 10, 11, 11]
To find the maximum sum of each pair of all elements in a list.
In general, i have to add each element in list to another element (not to itself).
Below is the code what i tried. I know this is complexity of (n^2)
Any better way to reduce complexity (can be both time and space) ?
Any better approach (may be with some modules or with just single for loop) ?
list l1 need not to be in sorted.
l2=[]
l3=[]
for i in range(len(l1)):
for j in range(len(l1)):
if i!=j:
l2.append(l1[i]+l1[j])
l3.append(max(l2))
l2.clear()
print(l3)
[7, 8, 9, 10, 11, 11]
Update:
Submitted this solution in hackerrank, but it fails for few cases.
Reason for failure is TimeLimitExceed (TLE). I assume, it's failing because of large numbers.
**Constraints:**
n = size_of_list
1<= n <= 4*10^4
1<= l1[i] <= 1024
1<= i <= n
1<= j <= n
j != i
Is it because of time-complexity, failing to handle these scenarios in above snippet ?
you can do something like this:
l1 = [1,2,3,4,5,6]
l2=[]
for i in range(len(l1)):
for j in range(i+1,len(l1)):
l2.append(l1[i]+l1[j])
l3=set(l2)
l2=list(l3)
print(l2)
output:
[3, 4, 5, 6, 7, 8, 9, 10, 11]
Sorting your list before processing it also helps.
Let me know if i have made any mistake.
You can do this in O(n).
The basic idea is to get the indices of the maximum element and the second maximum element in the list. Then for each element in the list, append the element + max_element, if the element is not the max_element. Otherwise, append the max_element + second_max_element.
I used the get_first_second_max_index to get the indices of the maximum element and the second maximum element because there might be identical elements in the list.
The code should look like this:
def get_first_second_max_index(nums):
if len(nums) < 2:
return None, None
first_max_index = 0 if nums[0] > nums[1] else 1
second_max_index = 0 if nums[0] <= nums[1] else 1
for index in range(2, len(nums)):
if nums[index] > nums[first_max_index]:
first_max_index, second_max_index = index, first_max_index
elif nums[index] > nums[second_max_index]:
second_max_index = index
return (first_max_index, second_max_index)
def max_sum_pair(nums):
res = []
if len(nums) >= 2:
first_max_index, second_max_index = get_first_second_max_index(nums)
for index in range(len(nums)):
if index == first_max_index:
res.append(nums[index] + nums[second_max_index])
else:
res.append(nums[index] + nums[first_max_index])
return res
nums = [1,2,3,4,5,6]
res = max_sum_pair(nums)
print(res)
For starters, we can use sorting to our advantage. The Python sorting method, sorted, operates in O(n log n) time. (See this question: What is the complexity of this python sort method?)
Once our numbers are sorted, the maximum sums are trivial. The maximum for a number is simply that number added to the last element in the sorted list or, if the number is the maximum element, the second to last element. Rewriting your code we could obtain:
l3 = []
l1 = sorted(l1)
for i in range(len(l1)):
if i + 1 == len(l1):
l3.append(l1[i] + l1[i - 1])
else:
l3.append(l1[i] + l1[-1])
print(l3)
I hope this helps. Let me know if I've misunderstood your question.

Function that fills in missing numbers to create complete sequence

I'm trying to create a function that will fill in any missing numbers in between two numbers in a list. The original list must be altered and cannot be new.
For example: [13,15,20] would return [13,14,15,16,17,18,19,20].
Note that I am not allowed to use a range function.
Here's my code:
def complete(list1):
i= 0
if len(list1) > 1:
for number in list1:
if number - list1[i+1] != -1:
number += 1
list1.insert(i + 1, number)
i += 1
return list1
else:
return list1
I got a "list index out of range" error.
Here is the source of your error:
...
for number in list1:
if number - list1[i+1] != -1:
...
i += 1
Basically, there comes a point (that point being the last number in list1) when i+1 gets you out of bounds and you are not doing anything to prevent that from happening. Indexing is tricky like that, so I would like to offer an indexing-free (well, almost) approach. By the way, from your comment to Bonfire's answer, I see that the task is to change original lists in-place. While mutating arguments is considered a very poor coding practice these days, here is a relatively efficient way of doing that:
import typing as t
def complete_sequence(partial: t.List[int]) -> t.List[int]:
# edge case
if len(partial) < 2:
return partial
# a lookup table for numbers we already have
observed = set(partial)
# append numbers we don't have
start = partial[0]
stop = partial[-1]
num = start + 1
while num < stop:
if not num in observed:
partial.append(num)
num += 1
# in-place sort
partial.sort()
return partial
As you see, instead of inserting values between existing numbers (paying O(n) time for each insertion), we can simply append everything (O(1) per insertion) and sort. This not only simplifies the logic (we no longer have to track those pesky indices), but also reduces computational time-complexity from O(n^2) to O(n*log(n)).
To achieve what you want to do I have made some changes to the logic:
def complete(list1):
if len(list1) < 2 : return list1
num = list1[0]
i = -1
while num < list1[-1]:
num += 1
i += 1
if num in list1: continue
if i < len(list1) - 1:
list1.insert(i + 1, num)
else:
list1.append(num)
return list1
print(complete([13, 14, 20]))
# [13, 14, 15, 16, 17, 18, 19, 20]
print(complete([13, 14, 15]))
# [13, 14, 15]

How many times should I loop to cover all cases of possible sums?

I am trying to solve this competitive programming problem using python3. The problem asks, given an array of size n, split the array into three consecutive, contiguous parts such that the first part has maximum sum and equals the sum of the third part. The elements in the array are positive integers.
My approach:
inputN = int(input())
inputString = input()
usableString = stringToList(inputString)
counting = 0
sum1 = usableString[0]
sum3 = usableString[-1]
maxSum1 = 0
countFromLeft = 1
countFromRight = 2
while counting < inputN-1:
if sum1 > sum3:
sum3 += usableString[-countFromRight]
countFromRight += 1
elif sum3 > sum1:
sum1 += usableString[countFromLeft]
countFromLeft += 1
elif sum1 == sum3:
maxSum1 = sum1
sum1 += usableString[countFromLeft]
countFromLeft += 1
counting += 1
print(maxSum1)
We read in the array elements and store them in a list usableString.
We set two variables sum1 and sum3 to the first and last elements of the list respectively.
We set a variable to keep track of the maximum sum of the first part of the list.
Finally, we set a variable counting to 0 which will represent the number of elements we have added from the list into sum1 or sum3.
The rest of the logic is in the while loop, which just checks if sum1 is larger than sum3 or the other way around and otherwise if they equal. After each iteration we add 1 to counting as an extra element has been included in a part. The while loop should stop when the number of elements used (i.e counting) is equal to the number of elements in the array - 1, since we added the first and last elements before entering the loop, which makes (array - 2), however, we still need to loop one additional time to check if sum1 and sum3 are equal.
I checked your submitted algorithm, and the problem is your stringToList function:
def stringToList(s):
list=[]
for elem in s:
if elem != " ":
list.append(int(elem))
return list
As far as I can tell, your main algorithm is completely fine, but stringToList does one crucial thing incorrectly:
>>> stringToList('2 4 6 8 10')
[2, 4, 6, 8, 1, 0]
# should be
[2, 4, 6, 8, 10]
As it treats each character individually, the two digits of 10 are turned into 1, 0. A simpler method which performs correctly would be to do the following:
# explanation
>>> input()
'2 4 6 8 10'
>>> input().split(' ')
['2', '4', '6', '8', '10']
>>> map(int, input().split(' ')) # applies the int function to all elements
<map object at 0x...>
>>> list(map(int, input().split(' '))) # converts map object into list
[2, 4, 6, 8, 10]
Sorry it took so long, I ended up making my own algorithm to compare to yours, ran my own tests, and then ran your code with the input to list method I just explained, and figured the only difference was your stringToList function. Took a while, but I hope it helps!
Just for the fun, here's my algorithm and turns out it was pretty similar to yours!
array = [1, 3, 2, 1, 4]
n = len(array)
slice = [0, n]
sum = [array[0], 0]
bestSum = 0
while slice[0] < slice[1]-1:
i = 0 if (sum[0] < sum[1]) else 1
slice[i] += 1-(2*i)
sum[i] += array[slice[i]]
if sum[0] == sum[1]: bestSum = sum[0]
# print(array[ : slice[0]+1], array[slice[0]+1 : slice[1]], array[slice[1] : ])
print(bestSum)

How does a value from a previous level in recursion go back up?

I'm trying to make a recursive function to get minimum number of coins for change, but I think my understanding of what each layer's return value in the stack is wrong. What I want is for the coin amount to be passed back up when the recursion reaches it's base case, but looking at the debugger, the coin case decreases on the way back up.
I've already tried to look at solutions for this problem, but they all seem to use dynamic programming, and I know that it's more efficient in terms of complexity, but I want to figure out how to do the recursion before adding the dynamic programming portion
def min_coin(coin_list, value, counter = 0):
if value == 0:
return 0
else:
for coin in coin_list:
if coin <= value:
sub_result = value - coin
min_coin(coin_list, sub_result, counter)
counter +=1
return counter
#counter += 1 #should add returning out from,
#return counter
coin_list = [5, 2, 1]
value = 8
print(min_coin(coin_list,value))
I want an output of 3, but the actual output is 1 no matter the value
You need to increment the counter before calling min_coin().
def min_coin(coin_list, value, counter = 0):
if value == 0:
return counter
else:
for coin in coin_list:
if coin <= value:
sub_result = value - coin
return min_coin(coin_list, sub_result, counter+1)
You can solve your task without recursion, answer from geekforcoders
# Python 3 program to find minimum
# number of denominations
def findMin(V):
# All denominations of Indian Currency
deno = [1, 2, 5, 10, 20, 50,
100, 500, 1000]
n = len(deno)
# Initialize Result
ans = []
# Traverse through all denomination
i = n - 1
while(i >= 0):
# Find denominations
while (V >= deno[i]):
V -= deno[i]
ans.append(deno[i])
i -= 1
# Print result
for i in range(len(ans)):
print(ans[i], end = " ")
# Driver Code
if __name__ == '__main__':
n = 93
print("Following is minimal number",
"of change for", n, ": ", end = "")
findMin(n)

Resources