I have written this short function to calculate the number of factors a number has as a part of my program, however I have noticed that it does not work in certain cases.
Here is my code:
def divisors(n):
number_of_factors = 0
max_test_num = int(math.ceil(math.sqrt(n))+1)
for i in xrange(1,max_test_num):
if n%i ==0:
number_of_factors += 2
if i*i == n:
number_of_factors -= 1
return number_of_factors
Now if the number has a pair of divisors which are coprime, then the result returned is 2 too big.
For example, with input as 20, it returns 8, when the correct answer is 6.
Any suggestions on how to fix this or simply a better way to do this?
Thanks in advance
max_test_num = int(math.ceil(math.sqrt(n))+1)
This makes you count elements twice, for example, with 20: ceil(sqrt(20))+1 = 5, so the condition if n%i ==0 applies for both 4 and 5, and for each you increase by 2.
The +1 in the mentioned line is redundant, remove it.
Related
I am having some trouble writing a function that will sum all the elements of a list or multiply all the elements of a list together based on whether the first element of the list is odd or even.
I would like to get something like this.
def simpleSum(mylist):
#Write your code
number = 1
for n in mylist:
if n % 2 != 0:
return sum(mylist)
else:
number *= n
return number
print(simpleSum([1, 2, 4, 5]))
print(simpleSum([2, 4, 5, 6]))
I added the number = 1 and number *= n based on what I've seen on the internet, but I don't really understand why I have to use number = 1 and also what number *= n is doing.
I would like my output to be
12
240
but so far I keep getting
12
2
Very new to python, and I'm not really sure what I'm doing wrong. I originally tried using
for n in mylist:
if n[0] % 2 != 0:
but I kept getting an error telling me that n[0] is not scriptable.
Any brief explanation would help me tremendously. Thank you in advance.
there
The answer to your question is extremely simple. All you need to correct is your logic or your syntax.
Let us break your program down and try to understand where the error is.
def simpleSum(mylist):
#Write your code
number = 1
for n in mylist:
if n % 2 != 0:
return sum(mylist)
else:
number *= n
return number
print(simpleSum([1, 2, 4, 5]))
print(simpleSum([2, 4, 5, 6]))
The code for n in mylist returns one element of the list at a time, and not the position, so when you say n[0], it returns an error as it is not a list and doesn't have any indexes.
Next up, looking at your logical or syntax error:
If you notice carefully, n becomes the next index of the list everytime. This means that everytime it checks whether the number is odd or even. If it is odd, it returns with the sum, but if it is even, it returns with number multiplied by n. Since it returns at first entry itself, i.e, at the first index itself, this means that if the number is even, the result will be that number(because 1*n=n) and if it is odd, it will return the sum of the whole list.
To change this, the following logic is used.
Create function:
If the first index of the list i.e., mylist[0] is odd:
return the sum
Otherwise/else:
return the product
The code to reproduce this would be:
def simpleSum(mylist):
#Write your code
if mylist[0] % 2 != 0:
return sum(mylist)
else:
number = 1
for n in mylist:
number *= n
return number
print(simpleSum([1, 2, 4, 5]))
print(simpleSum([2, 4, 5, 6]))
Judging by your desired output and inputs, you want the list of numbers multiplied if the first element is even and the sum of the list of numbers if the first element is odd.
number = 1 acts as a base value for multiplication.
number *= n equals to number = number * n
Consider the following code. First, it checks whether the first value of the list is odd or even. Then it calculates and returns values accordingly.
def simpleSum(mylist):
if (mylist[0] % 2) == 0:
number = 1
for n in mylist:
number *= n
return number
else:
return sum(mylist)
print(simpleSum([1, 2, 4, 5]))
print(simpleSum([2, 4, 5, 6]))
I don't think your code is doing what you want. If I'm reading your description correctly, it sounds like you want to know whether the first element of your list is even or odd before you add or multiply all the elements together.
In that case, you want something like this:
if my_list[0] % 2 == 0:
print(sum(my_list)
else:
num = 1
for n in my_list:
num *= n
print(num)
The reason you need to set num = 1 is because num *= n multiplies num by n, and if num doesn't have an initial value, you can't multiply it by n!
you can use functools.reduce for the multiplication part
from functools import reduce
from operator import mul
def my_func(some_list):
return sum(some_list) if some_list[0] % 2 else reduce(mul, some_list)
print(my_func([1, 2, 4, 5]))
print(my_func([2, 4, 5, 6]))
output
12
240
I am in need of your help again. I'm writing a code that determines whether a number is a semiperfect number or not by returning a boolean value. So first I thought I would make a list of the factors of the number excluding the number itself
def isSemiPerfect(n):
factor = []
for i in range(n-1, 0, -1):
if n%i == 0:
factor.append(i)
If I were to check for the number 12, it would return
factor = [1, 2, 3, 4, 6]
Then I need to make a code to use recursion to check if you add certain numbers it would be equal to 12
True = 6 + 4 + 2 or 6 + 3 + 2 + 1
Can someone tell me how I can use recursion to do trial and error? Like I'll always start with the biggest number and try a path with the next biggest number until I've tried all combinations.
I know there isn't a lot to go on with I just hope that you can tell me how I can use recursion effectively. Thank you!
You can think about it this way.
The question "Can [1,2,3,4,6] sum to 12"?
Is the same as "Can [2,3,4,6] sum to 11" or "Can [2,3,4,6] sum to 12"?
One uses the first element (and has lower sum) and the other does not use the first element and has the same sum.
so a start function would be:
def f(lst,sum_left):
return f(lst[1:], sum_left-lst[0]) or f(lst[1:],sum_left)
However, this function does not know when to stop. So we need some base cases.
Obviously, if sum is 0, the answer is trivially yes:
if sum_left == 0:
return true
Another base case is, if the sum is < 0, we have taken a too big element and we can never recover.
if sum_left < 0:
return true
Also, we can risk running out of elements like [1,2] can never sum to 50, so we add a base case if there are no elements in the list:
if not lst:
return false
Putting it all together:
def f(lst, left):
if left == 0:
return True
if left < 0:
return False
if not lst:
return False
return f(lst[1:],left-lst[0]) or f(lst[1:],left)
I am trying to build a function that will take a number and return a list. If the number is even, the second integer of the list will be the number divided by two. If it is odd, then following number will be number multiplied by 3 plus one and so on until it reaches 1.
For example:
Function(5) will give
[5, 16, 8, 4, 2, 1]
My code is:
def Collatz(n):
out=[]
while n>1:
if n%2==0:
out.append(n/2)
elif n%2!=0:
out.append((n*3)+1)
print(out)
Collatz(20)
It doesn't produce anything. Any suggestion? I want to do this with while loop.
This code is close to be working, a few insights and improvements:
Change n inside the while loop (otherwise n remains larger than 1 and you get infinity loop)
Use lower case in function names and use underscore to separate between words
def collatz(n):
out = [n]
while n > 1:
if n % 2 == 0:
n = int(n / 2)
elif n % 2 != 0:
n = (n * 3) + 1
out.append(n)
print(out)
# [5, 16, 8, 4, 2, 1]
collatz(5)
It is because the while loop never terminates, this is because you aren't actually changing the value of n each time. So before you append to the array say something like n=n/2 (or whatever the calculation is) then append n. This means that n will eventually reach one and you get a print out
The problem with your code is you are not decrementing the value of n which is leading to an infinite loop.
Every time when you are appending a new value in the list you also need to update the value for n.
Try this:
def Collatz(n):
out=[]
while n>1:
if n%2==0:
out.append(n//2)
#updating n
n= n//2
elif n%2!=0:
out.append((n*3)+1)
#updating n
n= (n*3)+1
print(out)
Collatz(20)
Output:
[10, 5, 16, 8, 4, 2, 1]
Try this:
def Collatz(n):
l=[n]
while l[-1]!=1:
x=l[-1]/2 if l[-1]%2==0 else l[-1]*3+1
l.append(int(x))
return l
Here's a version that works.
def Collatz(n):
out=[n]
while n>1:
if n%2==0:
n = n/2
else:
n = (n*3)+1
out.append(int(n))
return out
print(Collatz(5))
Some notes on your version:
Your loop never updates "n" so n stays at its initial value forever, leaving you in an infinite loop.
The "elif" can be simply "else" - if the value is not even, then it's odd (assuming we're working with integers)
If you want the initial value to be in the list, we should probably initialize the list that way.
In your problem statement, you say you need the function to "return a list". Printing from inside the function is fine if that's really all you need, but if we actually return the list with a return statement, then the list it generates can be used by other code.
If you're using Python 3, the operation n/2 will return a float, even if n was an integer to start. If we only want integers in our list, we need to do one of two things:
Make it explicitly integer division with n//2
Or re-cast n to an integer with int(n) before we insert it into the list. (Which is how I did it here.)
Notice that your code doesn't change n.Therefore your loop never terminates. Check this out:
def collatz(n):
my_list = [n]
while n > 1:
if n % 2:
n = n * 3 + 1
else:
n = n / 2
my_list.append(n)
return(my_list)
I’m trying to create a program that lists all the primes below an inputted number, and I came up with the code:
def primes():
num = 20
numlist = list(range(1,num+1))
i = len(numlist)
for j in numlist[2:]:
ans = divisible(j,i)
if ans:
numlist.remove(j)
print(numlist)
def divisible(m,n):
if m!=n and m%n==0:
return True
elif n == 1:
return False
else:
divisible(m, n-1)
primes()
(I used an in-browser IDE so the num part was a proxy for the input.)
My idea was to create a separate function divisible() that when inputted two ints, m and n, would check if n divides m. I'm not sure if I was right in my recursion, but I wrote divisible(m,n-1) the idea was that it would iterate through all the integers from n downward and it would return True if any n divided m, or False if it reached 1.
In the main code, m iterated through all the numbers in a list, and n is the total number of elements in the same list. I put the print(numlist) inside the if statement as an error check. The problem I’m having is nothing is printing. The code returned literally nothing. Is there something I’ve missed in how recursion works here?
There's a lot wrong here:
You've made a common beginner's recursion error in that you have a recursive function that returns a value, but when you call it recursively, you ignore the returned value. You need to deal with it or pass it along.
It seems like this modulus is backward:
if ... and m%n==0:
Maybe it should be:
if ... and n % m == 0:
You're code doesn't appear to be calculating primes. It's looks like it's calculating relative primes to n.
You start your list of numbers at 1:
numlist = list(range(1,num+1))
But you start testing at index 2:
for j in numlist[2:]:
Which is the number 3 and you never check the divisibility of the number 2.
Even with all these fixes, I don't feel your algorithm will work.
Your divisible function doesn't return anything if it falls into else part. change it as
def divisible(m, n):
if m!=m and m%n==0:
return True
elif n==1 :
return False
else:
return divisible(m,n-1)
This should work
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
My solution:
def findDuplicate(nums):
slow = fast = finder = 0
while fast is not None:
slow = nums[slow]
fast = nums[nums[fast]]
if fast is slow:
return slow
return False
nums = [1,2,2,3,4]
print findDuplicate(nums)
My above solution works and gives me o/p 2 but it doesn't work for every input for example it doesn't work for [11,15,17,17,14] or [3,1,2,6,2,3] and gives me error IndexError: list index out of range. I am not able to find patterns and am not able to track down the exact problem. Also tried to change my while condition:
while fast is not None and nums[nums[fast]] is not None:
your help will be greatly appreciated! Thank you.
Since the numbers are between 1 and n and you have been told there is only one duplicate, you can use difference between the sum of the numbers in the array and the sum of numbers from 1 to n to get the duplicate.
def findDuplicate(l):
n = len(l) - 1 # Get n as length of list - 1
return sum(l) - (n * (n + 1) / 2) # n*(n+1)/2 is the sum of integers from 1 to n
So the duplicate is the sum of the list - n*(n+1)/2
Of course, this doesn't generalize to finding duplicates for any list. For that case, you need to use #Jalepeno112 's answer.
The fact that the first one works is a fluke. Let's look at what it does on the first pass.
nums = [1,2,2,3,4]
# slow starts as index 0. So now, you've reassigned slow to be nums[0] which is 1.
# so slow equals 1
slow = nums[slow]
# now you are saying that fast equals nums[nums[0]].
# nums[0] is 1. nums[1] is 2
# so fast = 2
fast = nums[nums[fast]]
On the next pass, slow will be nums[1] which is 2. fast will be nums[nums[2]] which is nums[2] which is 2. At this point slow and fast are equal.
In your second example, you are getting an IndexError because of fast = nums[nums[fast]] If the value at nums[fast] is not a valid index, then this code will fail. Specifically in the second example, nums[0] is 11. nums doesn't have an element at index 11, so you get an error.
What you really want to be doing is performing a nested for loop on the array:
# range(0,len(nums)-1) will give a list of numbers from [0, to the length of nums-1)
# range(1, len(nums)) does the same,
# except it will start at 1 more than i is currently at (the next element in the array).
# So it's range is recomputed on each outer loop to be [i+1, length of nums)
for i in range(0,len(nums)-1):
for j in range(i+1,len(nums)):
# if we find a matching element, return it
if nums[i] == nums[j]:
return nums[i]
# if we don't find anything return False
return False
There are likely other more Pythonic ways to achieve this, but that wasn't your original question.
first you must ensure all numbers in list satisfy your constrains.
to find duplicated numbers in a list Use Counter in collections it will return each number and number of occurrence example :
>>> from collections import Counter
>>> l=Counter([11,15,17,17,14])
>>> l
Counter({17: 2, 11: 1, 14: 1, 15: 1})
to get the most common one use :
>>> l.most_common(n=1)
[(17, 2)]
where n is the number most common numbers you want to get
def duplicates(num_list):
if type(num_list) is not list:
print('No list provided')
return
if len(num_list) is 0 or len(num_list) is 1:
print('No duplicates')
return
for index,numA in enumerate(num_list):
num_len = len(num_list)
for indexB in range(index+1, num_len):
if numA == num_list[indexB]:
print('Duplicate Number:'+str(numA))
return
duplicates([11,15,17,17,14])
duplicates([3,1,2,6,2,3])
duplicates([])
duplicates([5])
l=[]
n= int(input("the number of digit is :"))
l=[0 for k in range(n)]
for j in range(0,n):
l[j]=int(input("the component is"))
print(l)
b=0; c=0
for i in range(n):
if l[i]== l[n-1-i]:
b=1;c=i
if b==1:
print("duplicate found! it is",l[c])
elif b==0:
print("no duplicate")
The answer is unfinished. It tries to convert the array to a linked list. So far it found where the slow pointer and fast pointer met, but this is the halfway solution. To get the solution, we need to initialize another pointer from the beginning of the linked list and walk towards each other. When they meet, that point is the where cycle is detected, in our question it is where the single point is:
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow,fast=0,0
while True:
slow=nums[slow]
fast=nums[nums[fast]]
if slow==fast:
break
slow2=0
while True:
slow2=nums[slow2]
slow=nums[slow]
if slow==slow2:
return slow2