optimize the python for loop - python

I have a problem where I need to find the number of unique numbers. No digits in the number would have been repeated.
Number like 11, 1123, 41124 wont qualify.
Numbers should be 1234, 12, or 987 like these would qualify.
My code works fine. But when the range go beyond 10^6. The code takes lots of time to execute. How can I optimize the same.
for i in xrange(10000000):# pow(10, n) 10, 100, 10000,...
j = str(i)
if j != j[::-1]:
for k in range(len(j)):
if j.count(j[k]) == 1:
if k == len(j)-1:
count += 1
#print j
else:
break
if len(j) == 1:
count += 1
print count

You are going about this in possibly the least efficient way possible, and the longer the number gets, the longer it will take. Your code should look more like this:
for i in xrange(10000000):
j = str(i)
if len(set(j)) == len(j):
count += 1
# print j
print count
This takes advantage of the fact a Python set can't contain duplicates (duplicates are eliminated). So, if the length of the set of the digits in the number is the same as the length of the original string of digits, we know no digits were duplicated.
You can even write it in one line:
print sum(len(set(j)) == len(j) for j in (str(i) for i in xrange(10000000)))
Others have suggested collections.counter which is useful if you want to know which digits were duplicated.

Related

Whats the better way of doing this

I've only been coding in python for a month and I tried making something that searches for duplicates in a user made list...
List = []
count = 0
Val = 0
usernum = int(input("How many numbers are in your list: "))
for i in range(0, usernum):
values = int(input("What is the number on the list: "))
List.append(values)
for i in range(0, len(List)):
if List[i] == List[Val]:
print("There are duplicates")
count += 1
if count == len(List):
Val += 1
continue
Your code does not work for various reasons:
You're missing your main variable: the list. Add it like this
List = []
BTW: List with a capital L is not an awesome choice, but still a much better choice than list with a lower case L which could cause all kinds of problems.
With that added, enter 1 and 1 and you'll find that even for a single number it will print "There are duplicates". That is because you compare
List[i] == List[Val]
where both i and Val are 0. The item compares against itself. That must no be the case.
All the if-logic is weird. It's unclear to me what you wanted to achieve. A common approach would be a nested loop in order to compare each item against each following item. Note how j starts at i+1
for i in range(0, len(List)):
for j in range(i+1, len(List)):
if List[i] == List[j]:
print("There are duplicates")
An even better approach would be to not implement that yourself at all but use other techniques like
if len(set(List)) < len(List):
print("There are duplicates")
where set() will give you the unique numbers only. If numbers have been removed because they were not unique (aka. duplicate), that set will have less numbers than the list.

I can't get count to work in my Python code

I'm trying to create a code that will print every number in a range set by the user, and then identify how many numbers in that range are odd numbers and how many are even.
I've tried a few different formats, but I'm very much a beginner and can't seem to nail down where I'm going wrong. I'm trying to keep the code as simple as possible.
for i in range(x,y+1):
print(i)
range = (x,y+1)
count_odd = 0
count_even = 0
for n in range:
if n%2==0:
count_even = count_even+1
else:
count_odd = count_odd+1
print("Number of even numbers :",count_even)
print("Number of odd numbers :",count_odd)
Currently when I run this, even numbers always comes to 0 and odd to 2.
On line 4 you have:
range = (x,y+1)
This is the tuple (x, y+1) not the range between them. So when you loop through it you are only looping through those two numbers. I assume in your case they are both odd. I would recommend removing that line and starting your second for loop like this:
for n in range(x, y + 1):
range is a builtin function, which returns an iterable from [start, end). You likely want something like:
count_odd = 0
count_even = 0
for n in range(x,y+1):
if n % 2 == 0:
count_even = count_even + 1
else:
count_odd = count_odd + 1
print("Number of even numbers :", count_even)
print("Number of odd numbers :", count_odd)
There's no point for a loop. If your range consists of even elements, then half of values is even and half is odd. If it consists og odd elements and starts from odd value then half+1 is odd and half-1 is even. It starts with even value then it's opposite.

While Loops - Increment a List

I'm stuck trying to figure out this while loop. It seemed simple at first but I keep running into errors. I think I just haven't used python in a while so it's hard to get back into the gist of things.
Write a while loop that will add 100 numbers to a list, starting from the number 100 and incrementing by 2 each time. For example, start from 100, then the next number added will be 102, then 104 and so on.
I have this so far;
count = 0
while count < 99:
count += 1
numbers.append(len(numbers)+2)
for x in numbers:
print(x)
But that is simply giving me 0-100 printed out when I want it to be 2,4,6,8,10,...
numbers = []
index = 0
number = 100
while index < 100:
number += 2
index += 1
numbers.append(number)
for x in numbers:
print(x)
With a few modifications, and using a while loop as per your exercise:
numbers = []
count = 0
while count < 100:
numbers.append(100 + (2*count))
count += 1
for x in numbers:
print(x)
Or with a for loop:
numbers = []
for i in range(100):
numbers.append(100 + (2*i))
for x in numbers:
print(x)
Or as a list comprehension:
numbers.extend([(100 + (2*el)) for el in range(100)])
Or as a recursion:
numbers = []
def rec(num):
if num < 100:
numbers.append(100 + (2*num))
rec(num + 1)
rec(0)
Something like this:
numbers = []
while len(numbers) != 100:
if len(numbers) > 0:
numbers.append(numbers[-1] + 2)
else:
numbers.append(100)
Little explanation:
You loop until your list has 100 elements. If list is empty (which will be at the beginning), add first number (100, in our case). After that, just add last number in list increased by 2.
Try numbers.extend(range(100, 300, 2)). It's a much shorter way to do exactly what you're looking for.
Edit: For the people downvoting, can you at least leave a comment? My initial response was prior to the question being clarified (that a while loop was required). I'm giving the pythonic way of doing it, as I was unaware of the requirement.

How can I continue the for loop of the outer side?

def countPrimes(self, n):
if n <= 1:
return 0
if n == 2:
return 1
count = 0
counted = [2, ]
for num in xrange(3, n+1, 2):
for c in counted:
if num % c == 0:
continue
count += 1
counted.append(num)
return count
I am writing a code for the solution of primes counting problems. I used counted as an array storing for primes that have been examined and use them for the examination for the next prime. I tried using continue to drop out the inner for loop then count += 1 and counted.append(num) would not be executed once the num is found not a valid prime. However, I met implementing problem here, as the continue statement would take me to another c instead of another num.
If I understand your question correctly, you want to know how to break the inner c loop, avoid the other code, and continue with another num. Like the other answers, you want to make use of break with some smart booleans. Here's what the loop might look like:
for num in xrange(3, n+1, 2):
next_num = False
for c in counted:
if num % c == 0:
next_num = True
break
if next_num:
continue
count += 1
counted.append(num)
This way, if you encounter a num that is divisible by c, you break out of the inner c loop, avoid adding num to the counted list.
It doesn't make a ton of sense to accumulate a count and a list of primes as you go. Introduces the chance for a mismatch somewhere. I've massaged the code a bit, with some more descriptive variable names. It's amazing how clear names can really make the algorithm make more sense. (At least for me it does)
def primesUpTo(n):
primes = []
if n > 1:
primes.append(2)
for candidate in xrange(3, n+1, 2):
for prime in primes:
candidate_is_prime = candidate % prime
if not candidate_is_prime: # We're done with this inner loop
break
if candidate_is_prime:
primes.append(candidate)
return primes
print len(primesUpTo(100))
Try using break instead of continue. See the documentation here. Basically break takes you out of the smallest enclosing loop, spitting you back into your higher-level loop for its next iteration. On the other hand, continue just jumps you on to the next iteration of the smallest closing loop, so you wouldn't go out to the higher-level loop first.

Calculating prime numbers

I am now doing the MIT opencourse thing, and already the second assignment, I feel it has left me out in the cold. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/pset1a.pdf
The specifics of it, are to write something that can calculate the 1000th prime number. We only know about the print, ==, =, 1=,if, else, elif, while, %, -,+,*,/, commands I think. We also don't yet know about importing libraries.
My Idea of how it would work is to take an odd number and try to divide it by, 3,4,5,6,7,8,9 and if %n !=0, then add a number to NumberofPrimes variable starting with 11 as the base of the tests, and assigning it a base value of 4 at the base of NumberofPrimes, though I don't know if that is even right, because I wouldn't know how to display the 1000th prime number.
Am I close?
The latest incarnation of it is as follows:
##calculate the 1000th prime number
potprime = 3
numberofprime = 1
cycle = if potprime%3 = 0:
break
if potpimre%4 = 0:
break
if potprime%5 = 0:
break
if potprime%6 = 0:
break
if potprime%7 = 0:
break
if potprime%8 = 0:
break
if potprime%9 = 0:
break
numberofprime + 1
potprime + 1
if potprime%2 == 0:
potprime = potprime + 1
if potprime != 0:
cycle
Where exactly am I going wrong? Walk me through it step by step. I really want to learn it, though I feel like I am just being left out in the cold here.
At this point, it would be more beneficial for me to see how a proper one could be done rather than doing this. I have been working for 3 hours and have gotten nowhere with it. If anybody has a solution, I would be more than happy to look at it and try to learn from that.
Looks like I am late
It is quite straight forward that if a number is not divisible by any prime number, then that number is itself a prime number. You can use this fact to minimize number of divisions.
For that you need to maintain a list of prime numbers. And for each number only try to divide with prime numbers already in the list. To optimize further it you can discard all prime numbers more than square root of the number to be tested. You will need to import sqrt() function for that.
For example, if you test on 1001, try to test with 3, 5, 7, 11, 13, 17, 19, 23, 29 and 31. That should be enough. Also never try to find out if an even number is prime. So basically if you test an odd number n, then after that test next number: (n + 2)
Have tested the below code. The 1000th prime number is 7919. Not a big number!!
Code may be like:
from math import sqrt
primeList = [2]
num = 3
isPrime = 1
while len(primeList) < 1000:
sqrtNum = sqrt(num)
# test by dividing with only prime numbers
for primeNumber in primeList:
# skip testing with prime numbers greater than square root of number
if num % primeNumber == 0:
isPrime = 0
break
if primeNumber > sqrtNum:
break
if isPrime == 1:
primeList.append(num)
else:
isPrime = 1
#skip even numbers
num += 2
# print 1000th prime number
print primeList[999]
The following code is gross, but since 1000 is indeed a small index, it solves your problem in a fraction of a second (and it uses only the primitives you are supposed to know so far):
primesFound = 0
number = 1
while primesFound < 1000:
number = number + 1 # start from 2
# test for primality
divisor = 2
numberIsPrime = True
while divisor*divisor <= number: # while divisor <= sqrt(number)
if number % divisor == 0:
numberIsPrime = False
break
divisor = divisor + 1
# found one?
if numberIsPrime:
primesFound = primesFound + 1
print number
You can test the solution here.
Now you should find a more efficient solution, optimize and maybe go for the 1000000-th prime...
For one thing, I'm pretty sure that in Python, if you want to have an if statement that tests whether or not A = B, you need to use the == operator, rather then the =.
For another thing, your algorithm would consider the number 143 to be prime, even though 143 = 11 * 13
You need keep track of all the prime numbers that you have already computed - add them to an array. Use that array to determine whether or not a new number that you are testing is prime.
It seems to me that you are jumping into the deep-end after deciding the kiddy-pool is too deep. The prime number project will be assignment 2 or 3 in most beginning programming classes, just after basic syntax is covered. Rather than help you with the algorithm (there are many good ones out there) I'm going to suggest that you attempt to learn syntax with the python shell before you write long programs, since debugging a line is easier than debugging an entire program. Here is what you wrote in a way that will actually run:
count = 4
n = 10 #I'm starting you at 10 because your method
#says that 2, 3, 5, and 7 are not prime
d = [2, 3, 4, 5, 6, 7, 8, 9] #a list containing the ints you were dividing by
def cycle(n): #This is how you define a function
for i in d: #i will be each value in the list d
if not n%i: #this is equal to if n%i == 0
return 0 #not prime (well, according to this anyway)
return 1 #prime
while count < 1000:
count += cycle(n) #adds the return from cycle to count
n += 1
print n - 1
The answer is still incorrect because that is not how to test for a prime. But knowing a little syntax would at least get you that wrong answer, which is better than a lot of tracebacks.
(Also, I realize lists, for loops, and functions were not in the list of things you say you know.)
Your code for this answer can be condensed merely to this:
prime_count = 1
start_number = 2
number_to_check = 2
while prime_count <= 1000:
result = number_to_check % start_number
if result > 0:
start_number +=1
elif result == 0:
if start_number == number_to_check:
print (number_to_check)
number_to_check +=1
prime_count +=1
start_number =2
else:
number_to_check +=1
start_number = 2
To answer your subsequent question, 'How do I keep track of all the prime numbers?
One way of doing this is to make a list.
primeList = [] # initializes a list
Then, each time you test a number for whether it is prime or not, add that number to primeList
You can do this by using the 'append' function.
primeList.append( potprime ) # adds each prime number to that list
Then you will see the list filling up with numbers so after the first three primes it looks like this:
>>> primeList
[11, 13, 17]
Your math is failing you. A prime number is a number that has 2 divisors: 1 and itself. You are not testing the numbers for primality.
I am very late on this but maybe my answer will be of use to someone. I am doing the same open course at MIT and this is the solution I came up with. It returns the correct 1000th prime and the correct 100,000th prime and various others in between that I have tested. I think this is a correct solution (not the most efficient I am sure but a working solution I think).
#Initialise some variables
candidate = 1
prime_counter = 1
while prime_counter < 1000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
print "The 1000th prime is: " + str(candidate)
While I was at it I went on and did the second part of the assignment. The question is posed as follows:
"There is a cute result from number theory that states that for sufficiently large n the product of the primes less than n is less than or equal to e^n and that as n grows, this becomes a tight bound (that is, the ratio of the product of the primes to e^n gets close to 1 as n grows).
Computing a product of a large number of prime numbers can result in a very large number,
which can potentially cause problems with our computation. (We will be talking about how
computers deal with numbers a bit later in the term.) So we can convert the product of a set of primes into a sum of the logarithms of the primes by applying logarithms to both parts of this conjecture. In this case, the conjecture above reduces to the claim that the sum of the
logarithms of all the primes less than n is less than n, and that as n grows, the ratio of this sum to n gets close to 1."
Here is my solution. I print the result for every 1,000th prime up to the 10,000th prime.
from math import *
#Initialise some variables
candidate = 1
prime_counter = 1
sum_logs = log(2)
while prime_counter < 10000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
# If the number is prime add its log to the sum of logs.
sum_logs = sum_logs + log(candidate)
if prime_counter%1000 == 0:
# For every 1000th prime print the result.
print sum_logs," ",candidate," ",sum_logs/candidate
print "The 10000th prime is: " + str(candidate)
Cheers,
Adrian
I came up with this solution in my interview, but I didn't get the job :( It has about 1/100 less iterations than the solution above:
from math import *
MAX_IDX=1000
MAX_IDX-=1
num_iter=0
l_pirme_list=[3]
candidate=l_pirme_list[0]
prime_counter=1
while prime_counter < MAX_IDX:
candidate+=2
#Cut the binary number in half. This is quite faster than sqrt()
bin_candidate=format(candidate, "2b")
max_prime_search=int(bin_candidate[:len(bin_candidate)/2+1],2)+1
# max_prime_search=sqrt(candidate)+1
candidate_is_prime=1
for prime_item in l_pirme_list:
num_iter+=1
if candidate % prime_item==0:
candidate_is_prime=0
break
elif prime_item > max_prime_search:
candidate_is_prime=1
break
if candidate_is_prime:
prime_counter+=1
l_pirme_list.append(candidate)
l_pirme_list.insert(0,2)
print "number iterations=", num_iter
print l_pirme_list[MAX_IDX]

Categories