I'm trying to become comfortable with python. I've been trying some simple activities that I've given in my beginning c++ classes when I was teaching. I did one involving functions and writing a file which worked flawlessly. I thought this one would be easier. It acts like it is in a silent endless loop, but it won't even let me trace it. Can someone see where I am going awry?
# Find Adam Numbers
def isAdamNumber(candidate):
isAdam = False
rev = reverse(candidate)
square = candidate * candidate
revsq = rev*rev
if revsq == reverse(square):
isAdam = True
return isAdam
def reverse(num):
rev=0
while num > 0:
rev = rev * 10 + num%10
num/=10
return rev
for x in range (11,25):
if isAdamNumber(x):
print(x, " is an adam number\n")
The quick fix is to change /= with the integer division version, //=
Inside the reverse function, you are going into an infinite loop. num value always will be greater than 0, therefore the while loop will continuously run. In python, you can get the reverse of the function without much effort. Convert the integer to string and reverse the string and now change the string back to integer.
def reverse(num):
num_str = str(num)[::-1]
return int(num_str)
I think this function definition can solve your problem.
To visualize the python to learn and teach, use this link
The problem has already been addressed by the other answers, so here's the expanded and simplified version of the slicing that's going on [this doesn't actually use slicing]:
def reverse(num):
rev = ''
num = str(num)
for i in range(len(num) - 1, -1, -1):
rev += num[i]
return int(rev)
This counts backward from the last element in the string version of num, and adds all the elements of num (in reverse order) to rev.
num > 0 is never False. Dividing a positive number by 10 repeatedly makes it smaller, but it never becomes zero, so the while loop keeps repeating.
Use //= instead. It rounds to the nearest integer, so it will reach 0.
This also wouldn't reverse numbers (unless I'm missing something). Alternatively, you can use
int(str(num)[::-1])
which converts the number to a string, reverses it using slicing, and turns it back into an integer.
I wrote a program to find out the primes in a list of numbers, just so practice formatting and all. Here is my code:
from math import *
#Defining range to be checked
a = range(1,10)
#Opening empty list
b = []
#Wilsons method for primes
for n in a:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
This code runs without issue and fairly fast, at least at this stage of use. However, when I include a while statement(see below), it is substantially slower.
from math import *
#Defining range to be checked
a = range(1,10)
#Opening empty list
b = []
#Wilson't method for primes
for n in a:
while n>1:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
Could anyone explain why that would be the case?
n.b: I know there are more efficient method to find primes. I am just practicing formatting and all, although I don't mind improving my code.
edit: mistaken addition of less than symbol rather than the appropriate greater than symbol. Corrected.
As pointed out by several people your code will result in an infinite loop as the value of n does not change within your while-loop.
You are probably not looking for a while loop in the first place. It should be sufficient to use the for loop without the first iteration (n = 1). If you insist on including n=1, using an if statement is a possible workaround:
a=range(1,10)
b=[]
for n in a:
if n>1:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
I have a list of numbers:
a = [1,2,3,4,5,19,22,25,17,6,73,72,71,77,899,887,44,124, ...]
#this is an abbreviated version of the list
I need to determine if there are duplicates in the list or not using the XOR ("^") operator.
Can anyone give me any tips? I'm a newbie and have never encountered this problem or used the XOR operator before.
I've tried several approaches (which have amounted to blind stabs in the dark). The last one was this:
MyDuplicatesList = [1,5,12,156,166,2656,6,4,5,9] #changed the list to make it easer
for x in MyDuplicatesList:
if x^x:
print("True")
I realize I'm probably violating a protocol by asking such an open-ended question, but I'm completely stumped.
Why XOR?
# true if there are duplicates
print len(set(a)) != len(a)
Ok, THIS is pythonic. It finds all the duplicates and makes a list of them.
a = [1,2,3,4,5,19,22,25,17,6,73,72,71,77,899,887,44,124,1]
b = [a[i] for i in range(len(a)) for j in range(i+1,len(a)) if i ^ j > 0 if a[i] ^ a[j] < 1]
print b
Simplified version of Dalen's idea:
a = [1,2,3,4,5,19,22,25,17,6,73,72,71,77,899,887,44,124,1]
def simplifyDalen(source):
dup = 0
for x in source:
for y in source:
dup += x ^ y == 0
return dup ^ len(source) > 0
result = simplifyDalen(a)
if result:
print "There are duplicates!"
else:
print "There are no duplicates!"
So far my bit index idea is the fastest (because it's one pass algorithm, I guess, not many to many)
When you xor two same numbers, you get 0. As you should know.
from operator import xor
def check (lst):
dup = 0
for x in lst:
for y in lst:
dup += xor(x, y)!=0
l = len(lst)
return dup!=(l**2 -l)
c = check([0,1,2,3,4,5,4,3,5])
if c:
print "There are duplicates!"
else:
print "There are no duplicates!"
BTW, this is extremely stupid way to do it. XORing is fast, but O(n**2) (always through whole set) is unnecessary loss.
For one thing, the iteration should be stopped when first duplicate is encountered.
For another, this really should be done using set() or dict().
But you can get the idea.
Also, using xor() function instead of bitwise operator '^' slows the thing down a bit. I did it for clarity as I complicated the rest of the code. And so that people know that it exists as an alternative.
Here is an example on how to do it better.
It's a slight modification of code suggested by Organis in comments.
def check (lst):
l = len(lst)
# I skip comparing first with first and last with last
# to prevent 4 unnecessary iterations. It's not much, but it makes sense.
for x in xrange(1, l):
for y in xrange(l-1):
# Skip elements on same position as they will always xor to 0 :D
if x!=y: # Can be (if you insist): if x^y != 0:...
if (lst[x] ^ lst[y])==0:
return 1 # Duplicate found
return 0 # No duplicates
c = check([0,1,2,3,4,5,4,3,5])
if c:
print "There are duplicates!"
else:
print "There are no duplicates!"
To repeat, XOR is not to be used for comparison, at least not in high-level programming languages. It's possible you would need similar thing in assembly for some reason, but eq works nicely there as anywhere. If we simply used == here instead, we would be able to check for duplicates in lists containing anything, not just integers.
XOR is fancy for other uses, as for ordinary bitwising (masking, unmasking, changing bits...), so in encryption systems and similar stuff.
XOR takes the binary repersentation of a number and then compares it bit-by-bit with another and outputs a 1 if the two bits are different and a 0 otherwise. Example: 1 ^ 2 = 3 because in binary 1 is 01 and 2 is 10 so comparing bit-by-bit we get 11 or 3. XORing a number with itself always gives 0, so we can use this property to check if two numbers are the same. There are myriad better ways to check for duplicates in a list than using XOR, but if you want / need to do it this way, hopefully the above information gives you an idea of where to start.
Well, lets use list items as bit indices:
def dupliXor(source):
bigs = 0
for x in source:
b = 1<<x
nexts = bigs ^ b
# if xor removes the bit instead
# of adding it then it is duplicate
if nexts < bigs:
print True
return
bigs = nexts
print False
a = [1,2,3,4,5,19,22,25,17,6,73,72,71,77,899,887,44,124,1]
dupliXor(a) # True
a = [1,2,3,4,5,19,22,25,17,6,73,72,71,77,899,887,44,124]
dupliXor(a) # False
this was one of the problems I was assigned in MyProgrammingLab. I've attempted to answer this problem over 45 times, but can't get it right.
Any help will be appreciated
Question:
In the following sequence, each number (except the first two) is the sum of the previous two numbers: 0, 1, 1, 2, 3, 5, 8, 13, .... This sequence is known as the Fibonacci sequence.
We speak of the i'th element of the sequence (starting at 0)-- thus the 0th element is 0, the 1st element is 1, the 2nd element is 1, the 3rd element is 2 and so on. Given the positive integer n, associate the nth value of the fibonacci sequence with the variable result. For example, if n is associated with the value 8 then result would be associated with 21.
My work:
def fib(n):
if n <= 1:
result == n
elif n >= 1:
result = fib(n-1)+fib(n-2)
else:
return result
It's because in all of your cases, you assign the result but don't return it.
So, for example, when fib(1) is called, Python returns None because you never told it to return result in that case. The same thing happens for, say, fib(45).
To correct this, just return result always. (This is a good idea no matter what type of program you are writing - functions should always have an explicit return value).
def fib(n):
if n <= 1:
result = n
elif n > 1:
result = fib(n-1)+fib(n-2)
return result # always return result!
Things to Know
You should be aware that this implementation of the Fibonacci sequence is the least efficient one out there. If you can ditch the recursive calls altogether and just use a while loop to calculate fib(n) - or, if you want recursion, store previously computed values of fib(n) instead of forcing it to compute all the way to fib(n) - you will have a much more efficient implementation.
Your code contained numerous issues, such as
Assigning without returning, which we've already discussed.
Using == instead of =. The first checks if the left and right hand side are equal, and returns True or False. The second actually assigns the value of the right hand side to the variable on the left hand side. Don't confuse checking for equality with assignment.
Using the same base case twice but telling Python to do something different in both cases. This is such a bad idea that I feel jonrsharpe in the comments is justified in saying "Seriously?". The reason for this is because doing this makes no sense and makes it hard to predict behaviour. The whole point of an if-else statement is to do different things in different cases.
Edit based on examples provided by OP. Indentation should only be four spaces, not eight. This is more of a stylistic issue than anything else, but it is the standard.
def fib(n):
if n < 2:
return n
else:
return fib(n-1)+fib(n-2)
You can essentially reduce it to this. You could even leave out the else and say:
def fib(n):
if n < 2:
return n
return fib(n-1)+fib(n-2)
but you said you need to have an else-case for whatever reason.
I wrote this one for my assignment. I know it's a little indirect, but it works and that's what's important :)
n = int(input("Insert a number: "))
i = 0
fib_list = [1, 1, 0]
for i in range (0,2):
if n == 0:
result = fib_list[2]
elif n <= 2:
result = fib_list[0]
for i in range (2,n):
result = fib_list[0] + fib_list[1]
fib_list.insert(0, result)
i += 1
result = fib_list[0]
By the way, you don't need to define an input to use in the myprogramminglab question.
I added the input version here because I used it in my tests.
I'm new to Python, and I'm playing around with recursive functions just for practice.
I made the following algorithm which takes a number as x and halves it until it is equal to 1. n is the number of times x has been halved.
def binary(x, n = 0):
print(n,":",x)
x = x // 2
n += 1
if x > 0:
binary(x, n)
return x
return x
I'm trying to make a loop that will call binary() with multiple values for x. I want my step to be doubled each iteration. I have it working with a while loop like the one below.
i = 1
while i < 1000000000:
print("when x is", i, ":")
binary(i)
i += i
For some reason though, I can't seem to achieve the same thing with a For loop. Here's what I have now.
for i in range(1,1000):
print("when x is", i, ":")
binary(i)
i += i
In the code above, i += i does not seem to effect the i in my header. I know that range() takes a third parameter called step, but I've tried this:
for i in range(1,1000, i += i):
# statements
This gives me a name error, and says "i is not defined".
Most of my experience with programming is in JavaScript and C#. In both of those languages I wouldn't of had any trouble doing this.
How would I get this to work in a For loop using Python 3?
The third parameter of range is indeed step. But you should use it with a computed value like:
for i in range(1,1000,2):
#statements
The reason why your i += i didn't worked is because, under the hood, the for-loop is executing something similar to i = next(...) at the end of an iteration, overiding your last increment.
Edit
You can achieve the desired effect using a generator, but it kinda kills the "trying to avoid while-loops" thing:
def myrange(start, stop):
i = start
while i < stop:
yield i
i += i
for i in myrange(1, 1000):
print(i)
Anyway, while-loops are perfectly valid constructs and I’d personnally go with one in this case. Do not forget that the for-loop has a rather different semantic in python than in both languages you’re used to. So trying to use a for-loop because you are able to do so with javascript seems like a bad idea if all what you need is a while-loop.
range can step by a fixed amount, but not a variable amount. Use a while-loop to increment i by i:
i += i
You could replace the while-loop with an iterator, such as:
import itertools as IT
for i in (2**i for i in IT.count()):
if i >= 1000000000: break
print("when x is", i, ":")
binary(i)
but I don't think this has any advantage over a simple while-loop.
If all you're doing is doubling i, then why not just raise it to the power?
for p in range(int(1000000000**0.5)):
print(binary(2**p)