So I don't want to go into whether this is the most perfect code for the FizzBuzz challenge.
For those unfamiliar with FizzBuzz, there are four rules in printing out a range of 1-100:
Print out all numbers;
If the number is divisible by 3, print "Fizz" instead;
If the number is divisible by 5, print "Buzz" instead;
If the number is
divisible by both 3 and 5, print "FizzBuzz".)
I ran two implementations, to compare their speed:
# Code A
%%timeit
for i in range(1,10001):
if i % 15 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
# Code B
%%timeit
for i in range(1,10001):
if i % 5 == 0 and i % 3 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
Despite the extra if evaluation of Code B, it consistently ran quicker than Code A. Does a larger number result in a slower modulo? What is the underlying reason for this?
The main reason I could think of is perhaps optimization.
Version B uses the same operation a few times, namely:
i mod 5
i mod 3
A reasonably intelligent compiler/interpreter might spot this, and calculate these intermediate results. By doing so, it would be able to immediately calculate the entire if-block with only 2 mod operations.
In short, I think the code that ends up being executed might look something like this:
for i in range(1,10001):
a = i % 5
b = i % 3
if a == 0 and b == 0:
print('FizzBuzz')
elif b == 0:
print('Fizz')
elif a == 0:
print('Buzz')
else:
print(i)
However, the code in block A is perhaps too complicated. By that, I mean the compiler will always be forced to execute 3 mod operations. Unless it would somehow be able to spot that 15 = 3 * 5, and use that logic to re-work the if-statement.
Related
I am trying to practice writing these loops, and I had an exercise which asked me to print numbers from 0 to 20 that aren't divisible by 3 or 5.
For the while loop, I wrote this code:
#solution with while
i = 0
while i < 21:
i += 1
if i % 3 == 0 or i % 5 == 0:
continue
print(i)
Whereas, for the for...in loop, I struggled because I found out that I needed to use and instead of or here.
The code is as follows:
#solution with for
for k in range(21):
if k % 3 != 0 and k % 5 != 0:
print(k)
Why did I have to change the logical operator?
In my head, the first rows of the two codes do the same thing, iterate a number from 0 to 20. So the condition, after these, should be equal for both the iterations used.
Can anyone explain to me what am I missing here?
This isn't a loop type problem, the issue is in using different equality operators in your conditions - != instead of ==.
After changing or to and, the result stays the same because you've accidentally used De Morgan's second law (negation of disjunction):
Now, let's look at the code.
In the while loop:
the program doesn't print i:
if it's divisible by 3 (but not necessarily by 5)
or
if it's divisible by 5 (but not necessarily by 3).
In other words:
the program prints i:
if it's not divisible by 3
and
if it's not divisible by 5.
Noe, let's check, what says the condition in the for...in loop:
the program prints k:
if it's not divisible by 3
and
if it's not divisible by 5.
Looks like the same condition, doesn't it?
As you noticed, in the In other words: paragraph, we've naturally used the negation of disjunction.
To sum up, both programs for i / k lower than 21 print:
0
1
2
4
7
8
11
13
14
16
17
19
If you still aren't sure, try to replace the conditions between loops:
i = 0
while i < 21:
i += 1
if i % 3 != 0 and i % 5 != 0:
print(i)
for k in range(21):
if k % 3 == 0 or k % 5 == 0:
continue
print(k)
In while loop.
if i % 3 == 0 or i % 5 == 0: # this means when i is evenly divided by 3 or 5 then don't do anything.
continue
print(i) # means only print i when i is not evenly divided by 3 and 5
And in the for loop
if k % 3 != 0 and k % 5 != 0: # here this means print i when k is not evenly divided by 3 and 5. Which same as while loop
print(k)
You just reverse order and nothing. You can use the same method in both way and you will get the same result.
While loop
i = 0
while i < 21:
i += 1
if i % 3 != 0 and i % 5 != 0:
print(i)
For Loop
for a in range(21):
if a % 3 != 0 and a % 5 != 0:
print(a)
Because you have also changed the conditions for the results in the while loop you have used ==, but in for loop you have used != if you modify the code you will get the same output by or operator in both
for k in range(21):
if k % 3 == 0 or k % 5 == 0:
continue
print(k)
The two loop types are totally equivalent. You had to use and instead of or, and != instead of ==, because you reversed the logic.
In the first case, you are saying "if the number is divisible then skip it, else print it" while in the second one_ "if the number is not divisible then print (else do nothing)"_.
I have a problem with the task. The task is:
We say that number 1 is a super number. If a number x is super, then
the numbers 2x and 3x are also super. For example, since the number 1
is super, then the numbers 2 and 3 are super. As 2 and 3 are super,
then the numbers 4, 6 and 9 are super, and so on. At the same time,
numbers 10 and 7 are not super. Write a program that asks the user to
enter a natural number n. The program prints whether the entered
number is super.
And this is what I have done so far
num = int(input("Enter a natural number "))
if num <= 0:
print("That is not a natural number")
else:
if num % 5 == 0 or num % 7 == 0 or num % 11 == 0 or num % 13 == 0:
print("Number is not super.")
elif num == 1 or num % 2 == 0 or num % 3 == 0 or num % 8 == 0 or num % 9 == 0:
print("Number is super")
else:
print("Number is not super.")
The problem is that for some numbers like 62 it says that it is a super number, but it ain't..
Just following the definition of super number:
def is_super(k):
if k == 1: return True
if k % 2 == 0:
return is_super(k / 2)
if k % 3 == 0:
return is_super(k / 3)
return False
Some testing
print(is_super(9))
True
print(is_super(14))
False
print(is_super(32))
True
print(is_super(62))
False
To me it looks like you jumped in without first figuring out how you'd work it out manually.
Personally, I think the easiest way to start this would be recursively, though it'll be very inefficient with large numbers, so it's up to you if you then want to go and optimise it after doing the first version. I got it working pretty easily, but since it's a problem you need to solve, I'm not going to just copy and paste the answer.
It works something like this (psuedocode):
def is_super(i):
if i is below 1: not a super
if i is 1: is a super
if i is above 1: check if i/2 or i/3 is a super
There are some nice recursive solutions here, I'll propose a non-recursive one. As some of the comments hint, super numbers have a tell-tale factorization: they are all of the form 2x * 3y for x, y >= 0, and every integer of that form is a super number. This should become clear after some study because the only way to get a super number is to multiply an existing one by 2 or 3, and we start with 1. That leads to the following code to test for superness:
def is_super(n: int) -> bool:
if n < 1:
return False
while n % 3 == 0:
n //= 3
return n & (n - 1) == 0; // Suggested by #KellyBundy
I tried to find shortcut way to test for superness but failed to find anything better than this.
num = int(input("Enter a natural number "))
if num <= 0:
print("That is not a natural number")
else:
if num % 3 == 0:
while num % 3 == 0:
num = num / 3
print(num)
if num == 1 or num % 2 == 0 or num % 3 == 0:
print("Number is super")
else:
print("Number is not super")
elif num % 2 == 0:
while num % 2 == 0:
num = num / 2
print(num)
if num == 1 or num % 2 == 0 or num % 3 == 0:
print("Number is super")
else:
print("Number is not super")
else:
print("Number is not super")
This is what I've done so far but I don't think it will work for large numbers ?
I have a list a,
a = ['python', 'django', 'python with django']
What i want to do is ,
if number is divisible by 3 then print 'python'
if number is divisible by 5 then print 'django'
if number is divisible by 3 and 5 both then print 'python with django'
This is my code
for n, i in enumerate(range(20)):
if i % 3 == 0:
print n, a[0]
elif i % 5 == 0:
print n, a[1]
elif i % 3 == 0 and i % 5 == 0:
print n, a[2]
and O/P is
0 python
3 python
5 django
6 python
9 python
10 django
12 python
15 python
18 python
and i need this Result
0 python with django
3 python
5 django
6 python
9 python
10 django
12 python
15 python with django
18 python
Can i use List Comprehension or is there any pythonic way
Thanks in advance.
Your way seems fine but you have your code a little bit incorrect. Here is the correct code:
for n, i in enumerate(range(20)):
if i % 3 == 0 and i % 5 == 0:
print n, a[2]
elif i % 3 == 0:
print n, a[0]
elif i % 5 == 0:
print n, a[1]
You must have it check for if the number is divisible by 3 and 5 first. If you don't and it is divisible by 3 that meets the condition of the first if statement so it will not check any of the elif statements because elif is only checked if the previous if or elif statements were not met. The same goes for if the number is divisible by 5.
This should solve your FizzBuzz task.
a = ['python with django' if x%15 == 0 else ('python' if x%3 == 0 else 'django') for x in xrange(20)]
A list comprehension will probably end up looking too convoluted in this case. Just move the last of your three conditions to the top. Otherwise, if a number is divisble by 3 and by 5, the check for being divisible by 3 alone will be successful first and your elif chain means the combined check will never be reached. And by the way, you need not enumerate the range you iterate over, just use i in place of n.
To make the code a little less verbose (but also a little less straight-forward) you could get away with one check less:
for i in range(20):
if i % 3 == 0:
if i % 5 == 0:
print i, a[2]
else:
print i, a[0]
elif i % 5 == 0 :
print i, a[1]
I am new to python. I am trying to write a program that counts a range of values but for multiples of 3 and 4 adds 3 and 4 to them resepectively and when the number is multiple of both adds that number to it. So for instance 1,2,3,4,5,6,7,8,9,10,11,12
should read in the end program as: 1,2,6,8,5,9,7,12,10,11,24
But my code is getting stuck somewhere.
for i in range (1,20):
if i%3==0 and i%4==0:
i=i+12
if i%3==0:
i=i+3
if i%4==0:
i=i+4
print i
This line has a typo
if i%3==0 and 1%4==0: # your second condition is 1 % 4 == 0, which is always false
I think you meant
if i%3==0 and i%4==0:
It is better (accurate and cleaner) if you use a different variable.
for i in range (1,20):
n = i
if i%3==0 and i%4==0:
n=i+12
if i%3==0:
n=i+3
if i%4==0:
n=i+4
print n
Now you will notice this fixed it for the 9 case, but not the 12 case! We now need to add the use of elif. Also, if a number is a multiple of 3 and 4, then it is also a multiple of their lowest common multiple, in this case 12. So you could re-write your first step to just check for multiples of 12. This gives us:
for i in range (1,20):
n = i
if i%12==0
n=i+12 # or possibly i + i
elif i%3==0:
n=i+3
elif i%4==0:
n=i+4
print n
The reason this works is because without the elif the i was getting added to multiple times. For example, with 9, you get to 9%3 ==0, True. Now i is set to 12. Next statement? 12%4 ==0 True. So another 4 is added.
Alternatively, if you would like to do some crazy python stuff:
for i in range(1, 20):
print i + next((n for n in (12, 4, 3) if i % n == 0), 0)
(Shout out to Jon Clements for this 2-liner answer)
You're allowing multiples cases (if conditions) for each iteration.
I think you probably wanted to do exclusive cases.
Maybe something like:
for i in range(1, 20):
print i, "=>",
if i % 3 == 0 and i % 4 == 0:
i += i
elif i % 3 == 0:
i += 3
elif i % 4 == 0:
i += 4
print i
I need to print out numbers between 1 and n(n is entered with keyboard) that do not divide by 2, 3 and 5.
I need to use while or for loops and the remainder is gotten with %.
I'm new here and I just don't understand the usage of %?
I tried something like this:
import math
print("Hey. Enter a number.")
entered_number = int(input())
for i in range(1, entered_number):
if i%2 != 0:
print("The number", i, "is ok.")
else:
pass
if i%3 != 0:
print("The number", i, "is ok.")
else:
pass
if i%5 != 0:
print("The number", i, "is ok.")
help?
You need to test for all 3 conditions in one statement, not in 3:
for i in range(1, entered_number):
if i % 2 != 0 and i % 3 != 0 and i % 5 != 0:
print("The number", i, "is ok.")
The and operators here make sure that all three conditions are met before printing.
You are testing each condition in isolation, which means that if the number is, say, 10, you are still printing The number 10 is ok. because it is not divisible by 3. For numbers that are okay, you were printing The number ... is ok. 3 times, as your code tests that it is not divisible by 3 different numbers separately, printing each time.
If something divides by 7 then:
something % 7 == 0
If something divides by 7 and 9 then:
something % 7 == 0 and something % 9 == 0
Conversely, if something divides by 7 or 9 then:
something % 7 == 0 or something % 9 == 0
Something that does not divide by 7 or 9 is given by the expression:
not (something % 7 == 0 or something % 9 == 0)
You don't require the else: pass bits from your code and one if statement with an if-expression that has three %, == bits in it should suffice.
You should probably check the three conditions at the same time:
if i%2 != 0 and i%3 != 0 and i%5 != 0:
print("The number", i, "is ok.")
Otherwise, you would print the same message several times for a single number.
Anyway, for your second question, the% operation is called modulo and it gives you the remainder of a division. For instance, 5%3 = 2 because 5 = 3*1 + 2. And when you check i%2 != 0, you actually check if i can be divided by 2.
print("Hey. Enter a number.")
entered_number = int(input())
for i in range(1, entered_number):
if i%2 != 0 and i%3 !=0 and i%5!=0:
print("The number", i, "is ok.")
a%b returns the remainder when a is divided by b. Example:
>> 5%3
2
What you are doing wrong here is that you are printing after checking a single condition so it will print even if i is divisible by other numbers. For example if i is 3, it will satisfy the first condition and therefore print that the number is ok but it is actually divisible by 3.
I saw you've solved your problem but my answer may worth reading.
This problem is actually doing filtering over a list of numbers 1..n. You can define a base function to test if number x is dividable by number y, and then use this base function to filter the list to get the result.
Here's my version.
import math
from functools import partial
print("Hey. Enter a number.")
entered_number = int(input())
def not_dividable_by(x, y):
return False if x % y == 0 else True
number_list = range(1, entered_number)
for i in [2, 3, 5]:
test_func = partial(not_dividable_by, y=i)
number_list = filter(test_func, number_list)
for number in number_list:
print("%d is OK" % (number,))