Multiplying all the digits of a number in python - python-3.x

If i have a number 101, i want to multiply all the digits of the number (1*0*1) but this result will become Zero. Instead how to split the number into 10 and 1 and multiply(10*1).
Similar examples,
3003033 -> 300*30*3*3 or
2020049 -> 20*200*4*9

You could use a negative look behind to check its not the start of the list and a positive look ahead for nums that are not 0 as your split point.
REGEX: Essentially this says split where the next num is not a 0 and it not the start of the line
/
(?<!^)(?=[^0])
/
gm
Negative Lookbehind (?<!^)
Assert that the Regex below does not match
^ asserts position at start of a line
Positive Lookahead (?=[^0])
Assert that the Regex below matches
Match a single character not present in the list below [^0]
0 matches the character 0 literally (case sensitive)
CODE
import re
from functools import reduce
def sum_split_nums(num):
nums = re.split(r'(?<!^)(?=[^0])', str(num))
total = reduce((lambda x, y: int(x) * int(y)), nums)
return " * ".join(nums), total
nums = [3003033, 2020049, 101, 4040]
for num in nums:
expression, total = sum_split_nums(num)
print(f"{expression} = {total}")
OUTPUT
300 * 30 * 3 * 3 = 81000
20 * 200 * 4 * 9 = 144000
10 * 1 = 10
40 * 40 = 1600

Let a and b be two integer numbers. Let c be a new number made by putting n zeros in the right side of b. Then multiplying a and c is equal to multiplying a and b and 10^n.
Now you can simplify what you want to do to the following: Multiply digits of your number to each other with the agreement that instead of 0, you will put 10. So actually you don't need to split your number.
Here I defined two functions. In both of them the idea is to convert your number to a string, run a for-loop on its digits and by an if condition in the case
1) multiply the previous result to the new digit if it is not 0, otherwise multiply to 10.
def multio1(x):
s = str(x)
ans = 1
for i in range(len(s)):
if s[i] != '0':
ans *= int(s[i])
else:
ans *= 10
return(ans)
2) multiply the previous result to the new digit if it is not 0, otherwise add one unit to the number of zeros. Then at the end put as many as number of zeros, zeros at the right side of your final result.
def multio2(x):
s = str(x)
ans = 1
number_of_zeros = 0
for i in range(len(s)):
if s[i] != '0':
ans *= int(s[i])
else:
number_of_zeros += 1
if number_of_zeros != 0:
ans = str(ans)
for i in range(number_of_zeros):
ans += '0'
ans = int(ans)
return(ans)
Now the multio1(x) and multio2(x) for x=101,3003033,2020049, both gives equal results shown in below.
10,81000,144000

That's kind of odd, but this code will work:
a = '3003033'
num = ''
last_itr = 0
tot=1
for i in range(len(a)-1):
if a[i]=='0' and a[i+1]<='9' and a[i+1]>'0':
tot*=int(a[last_itr:i+1])
last_itr=i+1
elif a[i]>'0' and a[i]<='9' and a[i+1]<='9' and a[i+1]>'0':
tot*=int(a[i])
last_itr=i+1
tot*=int(a[last_itr:len(a)])
print(tot)
Just put your number at a

Related

How to find the sum of prime numbers upto a certain range in Python?

I'm absolutely new to Python and programming in general so it'd be helpful if someone can give very beginner friendly help. I'm trying to get the sum of prime numbers upto say 50.
I used the below code but it adds additional 2 on my sum. for example sum of prime number upto 50 should be 326 but I get 328 as my output
upto = int(input("Find sum of prime numbers upto : "))
sum = 0
for num in range(2, upto + 1):
for i in range(2, num):
if (int(num % i) == 0):
break;
#If the number is prime then add it.
else:
sum += num
print("\nSum of all prime numbers upto", upto, ":", sum)
Your Code is working fine and the answer of " sum of prime numbers from 1 to 50" is 328 not 326, if you still have doubt about it you can check your result with this code below :
Explanation: Given a range [l, r], the task is to find the sum of all the prime numbers within that range.
# from math lib import sqrt method
from math import sqrt
# Function to compute the prime number
def checkPrime(numberToCheck) :
if numberToCheck == 1 :
return False
for i in range(2, int(sqrt(numberToCheck)) + 1) :
if numberToCheck % i == 0 :
return False
return True
# Function to iterate the loop
# from l to r. If the current
# number is prime, sum the value
def primeSum(l, r) :
sum = 0
for i in range(r, (l - 1), -1) :
# Check for prime
isPrime = checkPrime(i)
if (isPrime) :
# Sum the prime number
sum += i
return sum
# Driver code
if __name__ == "__main__" :
l, r = 1, 50
# Call the function with l and r
print(primeSum(l, r))
I set your range in the code above just copy and paste the code in your editor and run the code , you will see the result.
There are two parts you need to handle. One is to check if the number is a prime number or not. Second is to iterate through the range of numbers. Refer to the code below,
from math import sqrt
sum = 0
#some explanation here we are iterating from 50 all the way to 1. So you can indicate your range here. -1 is the step value which tells the difference between each iteration.
for i in range(50, 0, -1):
# Check whether it is a prime number here
bPrime = True #initialize a boolean here to be indicated by the loop below
for a in range(2, int(sqrt(i)) + 1):
if i % a == 0:
bPrime = False #definitely not a prime,break the loop and set boolean to false
break
bPrime = True #not ==0 so it is a prime, set boolean to true
if (bPrime) :
# Add up if it is a prime number
sum += i
#view the results
print(sum)
It should get you 328
Hi Sumit firstly Welcome to Stackoverflow :)
Now as per your question the sum of prime numbers upto range 50 is 328 only, not 326.
But if you want the sum of first 50 odd prime numbers then you can make minor change in your code as below which will give you 326 [which is the sum of odd prime nos till range 50]
upto = int(input("Find sum of prime numbers upto : "))
sum = 0
for num in range(3, upto+1):
for i in range(2, num):
if (int(num % i) == 0):
break;
#If the number is prime then add it.
else:
sum += num
print("\nSum of all prime numbers upto", upto, ":", sum)

Having an issue relating to finding an Armstrong number from a list in Python [duplicate]

n=int(input("Enter a Number: "))
x=0
y=0
z=0
while(n>0):
x=n%10
y=x**3
z=z+y
n=n//10
print (z)
#The z here is the same value which I enter, yet it doesn't work.
#If I enter 407 as n, z becomes (4^3)+(0^3)+(7^3) which is 407
if (z==n):
#But even when 407==407, it just wont print the bottom statement
print ("The number is Armstrong")
else:
print ("The number isn't Armstrong")
#it prints that it isn't an Armstrong number
After the while loop, n already became 4//10 which is 0, so it'll never equal z which is 407.
You will want to keep a copy of the original input for comparison.
As a general advice, use a debugger or at least print() your objects to see where the assignments went wrong.
Without using any built-in method
Armstrong number is 371 because 3**3 + 7**3 + 1**3 = 371. according this rule 123 is not Armstrong number because 1**3 + 2**3 + 3**3 is not equal to 123
def count_digit(n):
count = 0
while n > 0:
count += 1
n //= 10
return count
def is_armstrong(n):
given = n
result = 0
digit = count_digit(n)
while n > 0:
reminder = n % 10
result += reminder ** digit
n //= 10
return given == result
is_armstrong(371)
>> True
is_armstrong(123)
>> False
You can take in your initial number as a string so we can more easily convert it to a list. We can then map to create that list of ints. After we can use list comprehension to raise all int in that list to the power that is the len of our list. If the sum of this list equals our input, then we have an Armstrong number.
n = input('Enter a number: ')
nums = list(map(int, n))
raised = [i**len(nums) for i in nums]
if sum(raised) == int(n):
print('The number is Armstrong')
else:
print('The number is not Armstrong')
Expanded list comprehension:
raised = []
for i in nums:
i = i**len(nums)
raised.append(i)
print(raised)
Alternate for map:
nums = []
for i in n:
i = int(i)
nums.append(int(i))
I corrected your code:
n = int(input("Enter a Number: "))
x = 0
y = 0
z = 0
num = n
while n > 0:
x = n % 10
y = x**len(str(num))
z = z+y
n = n//10
print(z)
if (z == num):
print ("The number is Armstrong")
else:
print ("The number isn't Armstrong")
But you can still do it in many ways better. Look at the code of vash_the_stampede and ggorlen.
Or:
def isArmstrong(n):
print(f"{n} is {'' if int(n) == sum(int(i)**len(n) for i in n) else 'not '}an Armstrong number")
isArmstrong(input("Please enter a number: "))
Definition: a number n is an Armstrong number if the sum of each digit in n taken to the power of the total digits in n is equal to n.
It's important to keep track of the original number n, because it'll be needed to compare against the result of z (your variable representing the sum). Since you're mutating n in your while loop, there's no grounds for comparison against your original input, so if (z==n): isn't working like you expect. Save n in another variable, say, original, before reducing it to 0.
Additionally, your code has arbitrarily chosen 3 as the number of digits in the number. For your function to work correctly for any number, you'll need a way to count its digits. One way is to convert the number to a string and take the length.
I strongly recommend using descriptive variable names which reduces the chance of confusing yourself and others. It's only apparent that z represents your sum and x your remainder by virtue of reading through the code. If the code was any longer or more complex, it could be a nightmare to make sense of.
Lastly, Python is not a particularly flexible language from a style standpoint. I recommend adhering to the style guide as best as possible to keep your code readable.
Here's a working example:
def armstrong(n):
total = 0
original = n
digits = len(str(n))
while n > 0:
total += (n % 10) ** digits
n //= 10
return total == original
if __name__ == "__main__":
while 1:
print(armstrong(int(input("Enter a Number: "))))
Output:
Enter a Number: 407
True
Enter a Number: 1234
False
Enter a Number: 23
False
Enter a Number: 8
True
Enter a Number: 371
True
Try it!
total=0
def Armstrong(n):
m=list(n)
global total
for i in m:
total+=pow(int(i),len(n))
if total==int(n):
print ("it is Armstrong number")
else:
print("it is not Armstrong number")
Armstrong(input("enter your number"))
print(total)

Unexpected result for a large integer in python

I wrote a simple program to count the number of digits in n+1 where n is a large integer.The following test case outputs the answer as 34 but the answer is 33.
Test case - 999999999999999999999999999999990
Code -
#python3
import math
inp = eval(input())
if inp > 0:
digits = int(math.log10(inp+1))+1
elif inp == 0:
digits = 1
else:
digits = int(math.log10(-inp))+2
print(digits)
When I input a smaller integer,say 10 digits, it shows the correct answer, for example
when input = 9999999990, output is 10, which is correct.
math.log10() will evaluate to a double precision floating point number. It doesn't have enough precision to tell the result and the number 33 apart. You can use mpmath to evaluate log10 with higher precision. This code worked for me:
#python3
from mpmath import mp
mp.prec = 127 # set the precision to 127 bits
inp = int('999999999999999999999999999999990')
if inp > 0:
digits = int(mp.log10(inp))+1
elif inp == 0:
digits = 1
else:
digits = int(mp.log10(-inp))+2
print(digits)
Note that the precision is set to 127 bits. When evaluating a 40-digits number, we will run into the same problem as we had before. When the 40-digit number is very close to 10^41, the result of log10 might be a little bit more than 41 while the real value is a little bit less. This is why converting it so an integer yields 41.
Let's estimate how much precision is sufficient: The derivation of log10(x) is 1 / (x * ln(10)). So log10(x+1) - log10(x) is about 1 / (x * ln(10) ) for high x. We need a relative precision of about Delta_y / y, where Delta_y is ( log10(x+1) - log10(x) ) and y is log10(x). We can estimate the number of binary digits with log2( 1 / relative_precision ). This yields us log2( x * ln(x) ). For an x of 39 nines and one zero, this gives us about 139.4. So if we put
mp.prec = 140
we will get the correct result. Indeed
#python3
from mpmath import mp
mp.prec = 140
inp = int(39 * '9' + '0')
if inp > 0:
digits = int(mp.log10(inp))+1
elif inp == 0:
digits = 1
else:
digits = int(mp.log10(-inp))+2
print(digits)
print( len( str(inp) ) )
outputs:
40
40
Note that this might not be the best way of evaluating the number of digits. You could for example just use a loop, dividing by 10 each step. Or simply put
print( len( str(inp) ) )

Printing first combination among various combinations

So I have a question:
Given an even number (greater than 2), return two prime numbers whose sum will be equal to given number. There are several combinations possible. Print only first such pair
This is for additional reference:
*Input: The first line contains T, the number of test cases. The following T lines consist of a number each, for which we'll find two prime numbers.
Note: The number would always be an even number.
Output: For every test case print two prime numbers space separated, such that the smaller number appears first. Answer for each test case must be in a new line.
Constraints: 1 ≤ T ≤ 70
2 < N ≤ 10000
Example:
Input:
5, 74, 1024, 66, 8, 9990
Output: 3 71, 3 1021, 5 61, 3 5, 17 9973
Here is what I tried:
import math
def prime(n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
T = int(input("No of inputs: ")) #T is the no of test cases
input_num = []
for i in range(0,T):
input_num.append(input())
lst2= []
if T in range(1,71):
for i in input_num:
if (i in range(3,1000)) and (i % 2 == 0):
for j in range(0,i):
if prime(j) == True:
lst2.append(j)
for x in lst2:
for y in lst2:
if x + y == j:
print(x,end = ' ')
print(y)
This is only taking inputs but not returning outputs.
Also my code is currently intended for all the combinations but what I want is only the first pair and I am not able to do that
I found a more elegant solution to this problem here. Java, C, C++ etc versions of solution is also present there. I am going to give the python3 solution.
# Python 3 program to find a prime number
# pair whose sum is equal to given number
# Python 3 program to print super primes
# less than or equal to n.
# Generate all prime numbers less than n.
def SieveOfEratosthenes(n, isPrime):
# Initialize all entries of boolean
# array as True. A value in isPrime[i]
# will finally be False if i is Not a
# prime, else True bool isPrime[n+1]
isPrime[0] = isPrime[1] = False
for i in range(2, n+1):
isPrime[i] = True
p = 2
while(p*p <= n):
# If isPrime[p] is not changed,
# then it is a prime
if (isPrime[p] == True):
# Update all multiples of p
i = p*p
while(i <= n):
isPrime[i] = False
i += p
p += 1
# Prints a prime pair with given sum
def findPrimePair(n):
# Generating primes using Sieve
isPrime = [0] * (n+1)
SieveOfEratosthenes(n, isPrime)
# Traversing all numbers to find
# first pair
for i in range(0, n):
if (isPrime[i] and isPrime[n - i]):
print(i,(n - i))
return
# Driven program
n = 74
findPrimePair(n)

How to find which part of code requires optimization?

Given two integers m, n (1 <= m <= n) find all integers between m and n whose sum of squared divisors is itself a square. 42 is one such a number.
Code works correctly on sample inputs but it is rejected by automatic code checker and reports timeout error and asks to optimize the code...
while m < n :
list_divisors = []
temp_list = []
total = 0
for number in range (m+1) :
if m%(number+1) == 0 :
list_divisors.append(number+1)
for number in list_divisors :
total+= number*number
Codewars does not show what test cases it is failing for. It just shows Execution Timed Out (12000 ms) error. Below test cases passed during sample check.
Test.assert_equals(list_squared(1, 250), [[1, 1], [42, 2500], [246, 84100]])
Test.assert_equals(list_squared(42, 250), [[42, 2500], [246, 84100]])
Test.assert_equals(list_squared(250, 500), [[287, 84100]])
Try this based on your code. No data gets stored in a list. Total is the sum of squared of whole divisors. Then, if square-root of that total is a whole number, return the list.
import math
def list_squared(number):
total = 0
for x in range(1, number+1):
if number % x == 0:
total += x*x
bounds = math.sqrt(total)
if math.ceil(bounds) == math.floor(bounds):
return [number, total]
else:
return False
def all_numbers(start, end):
numbers = []
for x in range(start, end+1):
data = list_squared(x)
if data != False:
numbers.append(data)
return numbers
x = all_numbers(1, 10000)
print(x)
1..10000 checks takes 4.7s. I am sure it can be optimized further. Does this help you?
Even faster
Switching these two lines:
total = 0
for x in range(1, number+1):
with
total = 1 + number*number
for x in range(2, math.ceil((number+1)/2)):
will cut down your runtime to around half.
Even faster..er
def list_squared(number):
total = 0
x = 1
while x <= math.sqrt(number):
if number % x == 0:
if (number/x == x) :
total += x*x
else :
total += x*x + (number/x)*(number/x)
x += 1
bounds = math.sqrt(total)
if math.ceil(bounds) == math.floor(bounds):
return [number, total]
else:
return False
If you were to change list_squared a bit to loop through only square root of the number, you will get a runtime of half a second. The idea behind it is https://www.geeksforgeeks.org/find-divisors-natural-number-set-1/.
Let's take 42 as the number. Square root is 6.48. Let's just use 6. Start with 1. 42 is divisible by 1. 42 is also divisible by the result the division, which is 42.
Go to 2. 42 is divisible by 2. The result is 21. So, 21 is also a whole divisor. Repeat that through 6 and you've covered all divisors for 42. That cuts your runtime to sqrt(n) instead of half.
It looks like you never update the values of m or n. So if m < n is True on the first iteration of your loop, it will always be True and your while loop will be infinite. This would explain the timeout, probably because Codewars stops your code from executing if it hasn't finished after 12000ms.
To remedy this, you will have to update either m or n inside your while loop so that eventually the condition m < n evaluates to False, at which point your code will "drop through" the while loop.

Resources