finding divisor with condition with python using 'if' and 'while' - python

trying to find how many divisors in 120, and printing divisors
div_n = 1
count = 0
n = 120
while div_n <= n:
if n % div_n == 0:
print(div_n)
count += 1
div_n += 1
print('number of divisor that 120 is {}.'.format(count))
the output should be
1
2
3
4
5
6
8
10
12
15
20
24
30
40
60
120
number of divisor that 120 is 16
But the problem I'm trying to solve says the code is not meeting the requirements.
If there is nothing wrong, or more information is needed let me know.

You can use this:
def get_factors(n):
ret = []
for i in range(1, n+1):
if not n % i:
ret.append(i)
return ret
factors = get_factors(120)
print(*factors, sep='\n')
print('Total factors:', len(factors))
Output:
1
2
3
4
5
6
8
10
12
15
20
24
30
40
60
120
Total factors: 16

Your code, once properly indented, works just fine. So I suspect the requirement you don't meet is that of speed - try the code with n=120000000.
When you look for divisors you don't need to check all the numbers from 1 to n: just check numbers from 1 to int(sqrt(n)) - when you find a divisor lower than the square root you have also found a related divisor, greater than the square root. In your example, when you find 2 you also find 60, and so on.
So I would do something like:
def divisors(n):
divs = []
divs2 = []
r = int(sqrt(n))
for d in range(1,r):
q,m = divmod(n,d)
if m == 0:
divs.append(d)
divs2.append(q)
if n % r == 0:
divs.append(r)
for d in divs:
print(d)
for d in divs2[::-1]:
print(d)
print(f'Divisors for {n}: {len(divs)+len(divs2)}')
EDIT: there was a small bug - if n happened to be a perfect square, my code would count its square root twice. So we better stop at int(sqrt(n))-1 and handle the square root separately.

Related

How to execute 0 when printing out the loop? I've been trying to print out the factorial in python. I need 0 to be printed in the output

def fact(n):
f=1
for num in range(1,n+1):
if num==0:
return 1
else:
f=f*num
print(num,f)
n=int(input())
fact(n)
#here is my code, but the output should be
0 0
1 1
2 2
3 6
4 24
5 120
6 720
instead of
1 1
2 2
3 6
4 24
5 120
6 720
Can you tell me what is wrong and what should I add to the code?
0, 0 can't really be part of the factorial because then all following numbers would have to be multiplied by 0, making them all zero. I guess you could just print it out first.
def fact(n):
f=1
print(0, 0)
for num in range(1,n+1):
f=f*num
print(num,f)
n=int(input())
fact(n)
Taking for granted that 0! = 1 and 1! = 1, then you already have the two first numbers of your sequence. So you can multiply by num+1 to avoid multiplying by zero. Then you take your output before doing the next multiplication.
def fact(n):
f=1
for num in range(n+1):
print(num,f)
f=f*(num+1)
fact(5)
0 1
1 1
2 2
3 6
4 24
5 120
You can also create a lookup table if you want:
def fact(n):
FACT=[]
f=1
for num in range(n+1):
FACT += [f]
f=f*(num+1)
return FACT
F = fact(n)
F[0]
>>> 1
F[4]
>>> 24
range should start from 0, hence range(0, n+1) or just range(n+1) because in your code the condition is never hit
when the condition is hit you should have a print: print(0, 0)
def fact(n):
f=1
for num in range(0,n+1):
if num==0:
print(num, num) # num is just 0
else:
f=f*num
print(num,f)
Remarks:
the return is really needed? it is always 1 independently from n
0! = 1 by definition. Maybe print(0, 1)?

Finding the n-th number that consists of only 2 or 3

I am really struggling with this program. I would appreciate any kind of help.
For a natural number we say that it is strange if it is completely composed of digits 2 and 3. The user enters a natural number. The program prints the n-th strange number.
Numbers that are considered strange are 2, 3, 22, 23, 33...
n = int(input())
current_number = 1
counter_strange = 0
counter = 0
while counter_strange < n:
x = current_number
while x < n:
k = x % 10
if k != 2 or k != 3:
counter += 1
else:
break
if counter >= 1:
counter_strange += 1
current_number += 1
print(current_number-1)
Strange numbers come in blocks. A block of 2 1-digit numbers, followed by a block of 4 2-digit numbers, then 8 3-digit numbers. You can do the math and determine which block of k-digit numbers a given index n is, and how far into that block it lies. Convert that distance into a base-2 number, zero-filled to k digits, then replace 0 by 2 and 1 by 3. Convert the result back to an int:
from math import log2, ceil
def strange(n):
"""returns the nth strange number"""
#first determine number of digits:
k = ceil(log2(n+2)) - 1
#determine how far is in the block of strange k-digit numbers
d = n - (2**k - 1)
#convert to base 2, zfilling to k digits:
s = bin(d)[2:].zfill(k)
#swap 2,3 for 0,1:
s = s.replace('0','2').replace('1','3')
#finally:
return int(s)
for n in range(1,10): print(n,strange(n))
Output:
1 2
2 3
3 22
4 23
5 32
6 33
7 222
8 223
9 232
You can use a while loop with itertools.product in a generator function. Using a generator will allow you to create a stream from which you can access strange numbers on the fly:
import itertools
def strange():
c = 0
while True:
yield from map(''.join, itertools.product(*([['2', '3']]*(c:=c+1))))
s = strange()
for _ in range(10):
print(int(next(s)))
Output:
2
3
22
23
32
33
222
223
232
233

usage of continue loop, and or

I'm quite new in Python. I have searched on site but I couldn't find solution for that pease show me if I missed.
I am trying to understand loops and "and" "or" I did some experiment with these elements but I confused.
Bellow code I was expecting code pass the numbers which isn't dividable by 3 or 5 and print rest. But suprisingly It print the numbers which is dividable by 15! (other words which is dividable by 3 and 5)
for x in range(100):
if x % 3 != 0 or x % 5 != 0:
continue
print(x)
output:
0
15
30
45
60
75
90
And this one I was expecting it will pass the number which isn't dividable 3 and 5 But it prints the numbers which is dividable 3 or 5 as I wanted in my first example.
for x in range(100):
if x % 3 != 0 and x % 5 != 0:
continue
print(x)
output:
0
3
5
6
9
10
12
15
18
20
.............
I don't understand what I am missing. I'm aware that I can make it happen with if, elif and else form but I wanted to learn more about "continue" usage. I'd appereciate if you help me.
Thank you!
You may have an easier time understanding what's happening just by walking through the numbers and seeing what your logic does for each number. You have walked into a logic equivalence that can be confusing, and is expressed in De Morgan's Laws. Essentially you can say
(x % 3 != 0 or x % 5 != 0) = !(x % 3 == 0 and x % 5 == 0)
so your first logic test is checking whether a number is divisible by both 3 and 5, which are the multiples of 15. And your second test is
x % 3 != 0 and x % 5 != 0 = !(x % 3 == 0 or x % 5 == 0)
so you are testing whether a number is divisible by either 3 or 5.
The continue keyword will essentially end the current iteration of the loop, and jump directly to the start of the loop to re-evaluate the loop condition (see https://docs.python.org/3.8/tutorial/controlflow.html).
So, in your first block of code, any time x is not divisible by 3 or 5, it will not print the number, meaning the only numbers which are printed are those which are divisible by both 3 and 5.
You can clear up the or logic like this:
for x in range(100):
if x % 3 != 0: # skip 1,2,4,5,7,8,10,11,13,14,16....
continue
if x % 5 != 0: # skip 1,2,3,4,6,7,8,9,11,12,13,14,16...
continue
print(x) # only numbers that pass both checks 0,15,30,...
With this, only 0, 15, 30, ... get through
If you convert it with boolean algebra,
if x % 3 != 0 or x % 5 != 0:
is the same as
if x % 3 == 0 and x % 5 == 0:
which gives the same results (0,15,30,...)

Converting Yes to 1 and No to 0 in python

I have a csv file few columns are as Yes/No's I have tried most of the solutions on stack over flow nothing seems to be working.
sample['colval'] = sample['colval'].apply(lambda x: 0 if x=='N' else 1)
For example, I used the above code on my data. It converted everything to 1's, as in Y to 1 and N to 1.
So many other examples too, all yielded similar results, few resulting in 'None' as output for Y/N.
sample.colval[0:20]
0 N
1 N
2 N
3 N
4 N
5 N
6 N
7 N
8 N
9 N
10 N
11 Y
12 N
13 N
14 N
15 N
16 N
17 N
18 Y
19 N
Name: colval, dtype: object
Please help, Thank you
Found it difficult to repeat given the older version of Python and no access to the original data but your output above suggests whitespace in with the value. Try
sample['colval'] = sample['colval'].apply(lambda x: 0 if x.strip()=='N' else 1)

Python While loop to calculate smallest common multiple

This is meant to calculate the smallest common multiple of 1-20.
I can't seem to figure out why the while loop won't end. Can anyone help me out?
i = 1
j = 1
factors = 0
allfactor = False
while allfactor == False:
while j < 21:
if i % j == 0:
factors = factors + 1
j = j + 1
else:
break
if factors == 20:
allfactor = True
break
else:
i = i + 1
j = 1
factors = 0
The least common multiple of the numbers 1..20 is 232792560.
To get to that number you just need to look at the numbers 1 to 20. You need at least all prime numbers: 2, 3, 5, 7, 11, 13, 17 and 19.
In addition, you need another 2 to calculate 4, and two more 2s for 16. To get a 9 you also need another 3.
So you end up with:
2 * 2 * 2 * 2 * 3 * 3 * 5 * 7 * 11 * 13 * 17 * 19 = 232792560
And you can easily confirm that using Python:
>>> all(map(lambda x: 232792560 % x == 0, range(1, 21)))
True
I.e. all numbers are divisors of said number; and per the proof above (its construction) there is no smaller number.

Categories

Resources