How can I condense this simple "if" line of code? - python

I have a line of code in my program that checks if a number is divisible by several numbers.
However, the way I currently have it is extremely inefficient and ugly.
It currently looks like:
if(x % 1 == 0 and x % 2 == 0 and x % 3 == 0) and so forth for several other numbers. I was hoping someone could teach me how I could take out the long and chain and help me replace it with something that makes more sense so instead it will look like:
if(x % a[1,2,3] == 0)
Is this possible and if so can anyone please help me?
EDIT: The x % 1 == 0, x % 2 == 0, etc.. Is not the full equation. I am checking far more than % 1,2, and 3. I am looking for a solution that can take say.. 1 through 15. That is why I am not using x % 6.

if all(x % k == 0 for k in [1, 2, 3]):
print 'yay'

n = 1*2*3
if(x%n == 0):
#do stuff
Will work for any set of prime numbers.

for 1 through 15,you can use all(x % (k+1) == 0 for k in range(15)). for example::
>>> for x in range(10):
... if all(x % (k+1) == 0 for k in range(3)): #checks weather x is divisible by 1,2,3
... print x
...
0
6

lcm = LCM of set of number to divide i.e. (1,2,3....)
if(x % lcm == 0)
//pass

Related

Strange output when trying to find prime numbers Python

Ok, so I admittedly am kind of a noob, and I've been going through a course on udemy for programming. The problem is asking to write a function that finds all the prime numbers up to the number given. So I started writing the following code to extract the numbers that are not even, as well as the numbers not evenly divisible by 3 just to start:
def count_primes(num):
num_list5 = []
for i in range(num + 1):
print(i)
if i % 2 != 0 or i % 3 != 0:
num_list5.append(i)
return num_list5
When I call the function with a number of 100 like:
count_primes(100)
In the output, I get the num_list5 showing all the numbers in the range except for 6 and multiples of 6:
[1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14 ...]
Its like the if statement is doing an AND operation here... because 6 would be divisible by 2 AND 3. Is this a bug or something? Or am I not understanding and/or operations correctly?
What's weird is that it was working at one point and after making a change and reverting it, it started doing this...
I'm using VSCode and Jupyter notebooks and tried both Python 3.8.5 64-bit and 3.9.4 64-bit on Ubuntu 20.04
i % 2 != 0 or i % 3 != 0 is equal to not (i % 2 == 0 and i % 3 == 0) (De Morgan's laws)
It should be i % 2 != 0 and i % 3 != 0
If you are looking to generate all primes less than num, you should loop over all numbers j less than i and check if i%j is zero rather than just 2 and 3.
def count_primes(num):
num_list5 = []
for i in range(2, num + 1): # start at 2 because 1 and zero are not primes
print(i)
for j in range(2, i):
if i%j == 0:
break
else:
num_list5.append(i)
return num_list5
if __name__ == "__main__":
n = 100
print(count_primes(n))
Note that using Sieve of Eratosthenes method, this can be done more efficiently:
import math
def count_primes_sieve(num):
num_list5 = [False, False] + [True]*(num - 1)
for i in range(2, math.ceil(math.sqrt(num)) + 1):
if num_list5[i]:
j = i * i
while j < len(num_list5):
num_list5[j] = False
j += i
return [i for i, p in enumerate(num_list5) if p]
if __name__ == "__main__":
n = 100
print(count_primes_sieve(n))
We know some facts about prime numbers which you can use in your program. Negative numbers, 0 and 1 are not prime. 2 is the only even prime. A prime number only has itself and 1 as factors. From multiplication we know that if a x b = c then one of a, b is <= sqrt(c). That last fact helps us cut down the number of trial divisors we have to test. We can test for a prime by looking for a number that divides the target but is not the target itself or 1. If we find such a number then the target is not prime.
Here is some pseudocode to help:
function isPrime(num)
// 1, 0, negatives not prime.
if (num < 2)
return false
end if
// 2 is the only even prime.
if (num MOD 2 = 0)
return (num = 2)
end if
// Try odd factors up to square root.
limit <- 1 + sqrt(num)
for (test <- 3; test < limit; test <- test + 2)
if (num MOD test = 0)
// Not prime, we have found a factor.
return false
end if
end for
// If we get this far then num is prime.
return true
end function
After figuring out the propositional math and de Morgan's Law as someone pointed out, I was able to come up with a pretty simple solution using or and mod operators and only goes through a the sequence once:
def count_primes(num):
num_list5 = []
for i in range(2, num + 1):
if i == 2 or i == 3 or i == 5 or i == 7:
num_list5.append(i)
if not (i % 2 == 0 or i % 3 == 0 or i % 5 == 0 or i % 7 == 0):
num_list5.append(i)
return num_list5
print(count_primes(100))

Efficient way for checking number 3^x * 5^y

I want to check if number, based on lower and upper bound, has prime divisors only 3 and 5 and number should be multiplication of power of 3 and power of 5. My current solution is this. I want to optimize it, since checking powers with for loops isn't good way in my opinion. Thanks in advance.
def checkNum(x):
for i in range(1,50):
for j in range(1,50):
return x == (3**i) * (5**j)
def printResult(l, r):
for i in range(l,r):
if checkNum(i):
print(i)
Based on comments I think this is the best way:
def checkNum(x):
while x%3==0:
x = x //3
while x%5==0:
x = x//5
return x==1
I want to optimize it, since checking powers with for loops isn't good
way in my opinion.
Over a range of random numbers, we improve its speed by doing:
def checkNum0(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
while x % 15 == 0: # speed up the process
x = x // 15
while x % 5 == 0:
x = x // 5
while x % 3 == 0:
x = x // 3
return x == 1
Or we can use a nested loop and combine both divisions into one:
def checkNum(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
for divisor in (15, 5, 3):
while (quotient_remainder := divmod(x, divisor))[1] == 0:
x = quotient_remainder[0]
return x == 1

Can anyone help me with my python code for this list, not working how I think it should

So I have very, very limited coding knowledge and half the code I used here I learned today but what I was attempting to do was to create a list that was 2020 positive whole numbers long and which excluded all numbers that were divisible by 3 or 4 but not by 5. I was trying to figure out what the 2020th number was but I noticed that in my final list with the numbers excluded, it was still leaving them in towards the end!
This is the code I wrote:
numbers = [*range(1, 2165, 1)]
#print(numbers)
list1 = [ x for x in range(1, 2165) if x % 3 == 0 and x % 4 == 0 and x % 5 != 0 ]
#print(list1)
for x in list1:
numbers.remove(x)
print(len(numbers))
print(numbers)
Like I said I'm not very good at coding but it did seem to be working early on in the list as 12 was excluded and 60 was left in but towards the end, 2139 was left, which is divisible by 3.
I would appreciate any help.
2020 positive whole numbers long
For things like this, rather than iterating over a fixed range (in your case, from 1 to 2165, which doesn't produce 2020 numbers matching your conditions), it's usually more straightforward to build a generator that gives you numbers that you want, and take numbers from it via next() until you have as many as you need. In this case, given your conditions
def my_generator():
x = 0
while True:
x += 1
# skip all numbers that are divisible by (3 or 4) but are not divisible by 5
if ((x % 3 == 0) or (x % 4 == 0)) and (x % 5) != 0:
continue
yield x
# initialize the generator, and then grab exactly 2020 numbers from it
gen = my_generator()
numbers = [next(gen) for _ in range(2020)]
print("The 2020th number meeting the conditions is", numbers[-1])
# 3367
Note that, in your original question, your if condition was coded incorrectly, and I've fixed it here.
It might simplify your debugging if you just built the list directly by explicitly declaring the condition you're trying to match on rather than doing it in multiple steps. You can generate numbers in a single comprehension:
[x for x in range(1, 2165) if not(x % 3 == 0 and x % 4 == 0 and x % 5 != 0)]
or the logical equivalent:
[x for x in range(1, 2165) if x % 3 != 0 or x % 4 != 0 or x % 5 == 0]
If you're not convinced this is the same, you can test it against the numbers list generated by your original code:
>>> numbers == [x for x in range(1, 2165) if not(x % 3 == 0 and x % 4 == 0 and x % 5 != 0)]
True
2139 appears in this list because 2139 % 4 != 0.
If this doesn't match the condition you're trying to capture, having the code simplified should make it easier to find and fix the problem.

Python Fizzbuzz problems with loop

I've searched for the answer for about an hour, and it seems most people have coded fizzbuzz a different way than myself.
However, having tried everything to figure out why this simple code will not work I'm getting extremely frustrated.
Can anyone point out the simple problem I'm sure I'm having? The code runs but it just returns the value 1.
def fizzbuzz(intList):
for n in intList:
if n % 3 == 0 and n % 5 == 0:
return n.replace(str(n),"Fizzbuzz")
elif n % 3 == 0:
return n.replace(str(n),"Fizz")
elif n % 5 == 0:
return n.replace(str(n),"Buzz")
else:
return n
The first value it looks at is 1. Since 1%x is only 0 for an x of 1, it goes to the else and returns 1. And then it's done, because that's what return does.
That leads to the bigger problem, which is that you are starting a loop and then guaranteeing that you will leave that loop after only one iteration, because there's a return in every branch. You'll need to replace those return statements with either append()s to a list (don't forget to return the resulting list) or print() calls.
Also, if you started with something like 3, your code would try to use replace on an integer, which is not something you can do with integers. You would get a traceback.
The code is returning 1 because consider this list [1,2,3,4,5,6,7,8,9,10]. All three conditions will get false and the last else will return 1. If you want the answer, append them into list.
Something like this:
def fizzbuzz(intList):
temp = []
for n in intList:
if n % 3 == 0 and n % 5 == 0:
temp.append("Fizzbuzz")
elif n % 3 == 0:
temp.append("Fizz")
elif n % 5 == 0:
temp.append("Buzz")
else:
temp.append(n)
return temp
print fizzbuzz(range(1,20))
Perhaps if you take a look at this code you will
better understand yours. Although this is a completely
different implementation of fizzbuzz in Python3
#!/usr/bin/python3
for i in range(1,100):
msg = "Fizz" * bool(i%3==0)
msg += "Buzz" * bool(i%5==0)
if not msg:
msg = i
print(msg)
My skills in python are fairly average but i love using dicitonaries. Here is the Fizz Buzz program using dictionaries.Without an if.
for data in range(1, 101):
msg = [str((data % 3 == 0)), str((data % 5 == 0))]
// msg returns a list with ['True' ,'False'] depending on the condition
conveter = {"True False": "Fizz",
"False True": "Buzz",
"True True": "Fizz Buzz",
"False False": data
}
val = conveter[" ".join(msg)]
print(val)
I just implemented FizzBuzz as
for n in range(1, 100):
if n%15==0: print "FizzBuzz"
elif n%5==0: print "Buzz"
elif n%3==0: print "Fizz"
else: print n
The best thing with it that
It works
It fits into a tweet, with a margin
Years later, based on this...
FizzBuzz: For integers up to and including 100, prints FizzBuzz if the integer is divisible by 3 and 5 (15); Fizz if it's divisible by 3 (and not 5); Buzz if it's divisible by 5 (and not 3); and the integer otherwise.
def FizzBuzz():
for i in range(1,101):
print {
3 : "Fizz",
5 : "Buzz",
15 : "FizzBuzz"}.get(15*(not i%15) or
5*(not i%5 ) or
3*(not i%3 ), '{}'.format(i))
The .get() method works wonders here.
Operates as follows
For all integers from 1 to 100 (101 is NOT included),
print the value of the dictionary key that we call via get according to these rules.
"Get the first non-False item in the get call, or return the integer as a string."
When checking for a True value, thus a value we can lookup, Python evaluates 0 to False. If i mod 15 = 0, that's False, we would go to the next one.
Therefore we NOT each of the 'mods' (aka remainder), so that if the mod == 0, which == False, we get a True statement. We multiply True by the dictionary key which returns the dictionary key (i.e. 3*True == 3)
When the integer it not divisible by 3, 5 or 15, then we fall to the default clause of printing the int '{}'.format(i) just inserts i into that string - as a string.
Some of the output
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
how a python function should look like if we want to see the next result in the interactive mode of the python interpreter:
>>> fizz(15)
[ 1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz' ]
n = int(input())
out = []
for i in range(1, n):
if i % 3 == 0 and i % 5 == 0:
out.append("fizzbuzz")
continue
elif i % 3 == 0:
out.append("fizz")
continue
elif i % 5 == 0:
out.append("buzz")
continue
out.append(i)
print(out)
Answer as [1,2,'fizz']
x = int(input('Enter the number: '))
if x % 3 ==0 and x % 5 ==0:
print('FizzBuzz')
elif x % 3 ==0:
print('Fizz')
elif x % 5 ==0:
print('Buzz')
else:
print(f'{x} ¯\_(ツ)_/¯')

Euler #1 in Python, wrote program but got wrong answer

I've decided I want to work on the Euler problems in order to improve my Python skills, but I ran into a problem with the first one. You see, I wrote the program I thought would work trying to get an answer, and compared it to the one found on the solutions page located here. Here is the code that I wrote:
total = 0
for x in range(1000):
if x % 5 != 0 and x % 3 != 0:
total += x
print(total)
This gives me the answer 266,332, when the correct answer is 233,168 according to the solution linked before. I don't know why I got the wrong answer, and any help would be appreciated. Thanks!
You're missing a not in your application of De Morgan's Law:
total = 0
for x in range(1000):
if not (x % 5 != 0 and x % 3 != 0):
total += x
print(total)
not (x % 5 != 0 and x % 3 != 0) is equivalent to x % 5 == 0 or x % 3 == 0, the latter of which is stated in the page you link as the equivalent not x%5 or not x%3.
You are using the wrong condition. You have to test, when the rest is 0? With 3 and with 5. Additionally you have to use OR instead AND because you want both group of numbers.
If you use AND you are going to get only the numbers that are multiple of both, multiple of 3 and multiple of 5.
Try:
total = 0
for x in range(1000):
if x % 5 == 0 or x % 3 == 0:
total += x
print(total)
A couple of things are wrong with the program. For starters, your if statement checks the wrong condition--it checks to see whether or not it is NOT divisible by 3 or 5. It should be if x%3==0 or x%5==0:
Second, you have an indentation error, so nothing is being executed by the if statement. Indent the total+=x statement.
Your final code will look like this:
total = 0
for x in range(1000):
if x % 5 == 0 or x % 3 == 0:
total += x
print(total)
Best of luck, and happy coding!
try this:
def sumOfMultiples(number):
sum = 0
for i in range(1,number):
if i % 2 == 0 or i % 3 == 0:
sum += i
return sum
print (sumOfMultiples(15))

Categories