Narcissistic number - python

Today I saw an interesting task. To make a program which outputs all "narcissistic numbers" (all digits are raised to the power of 3). My program has this code
for number in range(1, 408):
result = 0
for digit in str(number):
result += int(digit) ** 3
if result == number:
print(number)
The output is
1
153
370
370
371
407
Why does 370 appear twice?

You should unindent the last if statement, which runs after each digit:
for number in range(1, 408):
result = 0
for digit in str(number):
result += int(digit) ** 3
if result == number:
print(number)
As another answer notes, this can give you false duplicates if there is match in a number with trailing 0's. There is an added danger, though, of false positives if there is a number whose left X digits equal it, but whose total digits do not.

You're checking whether result==number after each digit in the number. You probably want this check in the outer for loop. As it is, it sees that 370 = 3**3 + 7**3, but it is also 3**3 + 7**3 + 0**3, so it's printed on both of those iterations.

Below code will return true or false if number is narcissistic:
def narcissistic(number):
number = str(number)
empty_arr = []
count = 0
for n in number:
n = int(n)
empty_arr.append(n ** len(number))
for n in empty_arr:
count = count + n
count = int(count)
number = int(number)
if count == number:
return True
else:
return False

I've done something like that to solve the problem:
import math;
def narcissistic( n ):
DecimalPlaces = 0 if n == 0 else math.floor(1 + math.log10(n))
soma = 0
digit = 0
NarcissisticSum = 0
i = 0
for i in range(1,DecimalPlaces):
digit = int((n % 10**i - digit) / (10**(i-1)))
NarcissisticSum += digit ** (DecimalPlaces)
lastDigit = int((n - soma) / (10**i))
NarcissisticSum += lastDigit ** (DecimalPlaces)
return NarcissisticSum == n

Related

How can I retain zero in python for calculation?

So I supposed to verify if the input number is a UPC number or not. I have to allowed leading zeros and accounted it in the calculation.
Here is my current code, it works for all number except number has leading zeros:
Condition for UPC code valid:
Calculate the sum of multiplying odd digit index by 3 and even digit index by 1 of the input number.
Calculate the sum we just did modulo 10, get result digit.
If the resulting digit is between 1 and 9 then subtract result digit from 10. If the result digit is 0, add 0 to the to the base number to get the completed number.
def UPC_code(num):
sum_digit = 0
index = 0
num_temp = str(num)[:-1]
len_nt = len(num_temp)
for digit in num_temp:
if (index + 1) % 2 != 0: # If number position is odd
sum_digit += int(digit) * 3 # Sum = digit * 3
if index < len_nt: # Increase index till end
index += 1
elif (index + 1) % 2 == 0: # If number position is even
sum_digit += int(digit) * 1 # Sum = digit * 1
if index < len_nt:
index += 1
# print(sum_digit)
res_digit = sum_digit % 10
if 1 <= res_digit <= 9:
res_digit = 10 - res_digit # Res digit meet condition = 10 - res digit
if res_digit == num % 10:
return True
elif res_digit != num % 10:
return False
else:
print("Something went wrong")
# End UPC_code()
Call UPC_code()
import code_check.py as cc
num = str(input())
num_int = int(num)
if cc.UPC_code(num_int) is True and num_int != 0:
print(num, "valid UPC code.")
else:
print("Not valid")
Expected input:
042100005264
Expected output:
042100005264 valid UPC code
Actual output:
Not valid
it works for all number except number has leading zeros
As you have doubtless discovered, python does not allow you to write 0700. Historically that would have meant 0o700, or 448, which is likely not what you want anyhow...
In this case the solution is simple. If you need to handle numbers like 00007878979345, handle strings.
Thus refactor your code to take a string. As a bonus, int("000008") is 8, so when you need the number as a number you don't even have to do anything.

How to not count negative input

is there a way to keep the counter going without counting the negatives and only to stop when the input is zero?
count = 0
total = 0
n = input()
while n != '0':
count = count + 1
total = total + int(n) ** 2
n = input()
print(total)
Here is an example of execution result.
Input: -1 10 8 4 2 0
Output: 184
Since you want only number to enter the loop you can use isnumeric() built in function to check that.
You need if() : break here.
num = input()
...
while(isnumeric(num)):
...
if(num == "0"):
break;
The response you wait for is:
ignore negative number
count positive numbers
stop when input is 0
count = 0
total = 0
n = int(input())
while (n != 0):
count += 1
if (n > 0):
total = total + n**2
num = int(input())
print(total)
Your code was already OK except that you did not cast the number n into int and you did not test n to take away negative values.
Execution:
When you enter -1 10 8 4 2 0, it should show 184
You can parse your Input to an integer (number) and check if it's larger than zero:
count = 0
total = 0
num = int(input())
while number != 0:
if number < 0:
continue
count += 1
total = total + num**2
num = int(input())
print(total)
The difference between pass, continue, break and return are:
pass = ignore me an just go on, usefull when you create a function that has no purpose yet
continue = ignore everything else in the loop and start a new loop
break = break the loop
return = end of a function - a return statement can be used to give an output to a function but also as a way to break out of the function like the break statement does in loops.

How to detect if the middle digit of an integer is "0" without converting it into a string?

Trying to make a function which detects the the middle digit of an odd number is 0 and returns True if it is, otherwise False. I really want to get this function to work without converting the integer to a string first.
This is what I have so far:
def test(n):
n = str(n)
if len(n) % 2 == 0:
return False
else:
left_side = n[:len(n)//2]
right_side = n[(len(n)//2):]
if right_side[:1] == "0" and ((not "0" in left_side)and (not "0" in right_side[2:])):
return True
else:
return False
print (test(0)) # True
print (test(101)) # True
print (test(123)) # False
print (test(21031)) # True
n = 12345
digits = []
while n:
digit = n % 10
digits.append(digit)
n //= 10
digit_count = len(digits)
if digit_count % 2:
middle = digit_count // 2
print(digits[middle])
Output:
3
Alternatively, using math.log10:
from math import log10
n = 12345
digit_count = int(log10(n)) + 1
middle = digit_count // 2
print(n // 10 ** middle % 10)
See these two answers:
Length of an integer in Python
How to take the nth digit of a number in python
this should do it. it does convert it to a string, but honestly it's faster, easier, and just more efficient.
num = int(input("number too test: "))
def test(number):
num_len = len(str(number))
print(num_len)
if num_len % 2 == 0:
return False
else:
number = str(number)
half = int((num_len-1)/2)
print(number[half])
if int(number[half]) is 0:
return True
else:
return False
test(num)
Not that it will make much difference in terms of performance, but you can use the log function to compute the number of zeros in a number and remove the rightmost half by dividing to the correct power of 10. For example:
import math
def test(n):
if n == 0:
return True
digits = math.ceil(math.log(n + 1, 10)) - 1
return digits % 2 == 0 and not (n // 10**(digits / 2) % 10)

Program that finds a numbers divisor

I've been making my own little program that finds the divisors for an inputted number.
The way it determines if a number can be divided with another number is if the result is an integer. If its a float, it should come out negative.
This is what I've got so far:
# Divider
Number = input("> ")
divider = 1
while True:
Number = int(Number)
divider = int(divider)
result = 0
result = int(result)
result = Number/divider
if isinstance(result, int):
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
if divider == Number + 1:
break
The problem is that when I run the program and input a number like "10" which should have more than one divisor (1,2,5,10) it comes out completely negative:
> 10
1 N
2 N
3 N
4 N
5 N
6 N
7 N
8 N
9 N
10 N
>>>
I wonder what I'm doing wrong.
First I'm going to clean up your code:
Number = 15
divider = 1
while True:
if divider == Number + 1:
break
Number = int(Number)
divider = int(divider)
result = Number/divider
if isinstance(result, int):
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
Now, what are they all return as negative? Simply because the / division returns a float (i.e. result is a float). What is the correct solution? Use the % modulo to check if the remainder is 0.
Number = 15
divider = 1
while True:
if divider == Number + 1:
break
Number = int(Number)
divider = int(divider)
result = Number%divider
if result == 0:
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
Output:
1 Y
2 N
3 Y
4 N
5 Y
6 N
7 N
8 N
9 N
10 N
11 N
12 N
13 N
14 N
15 Y
The division operator / always results in a floating number in Python 3, so the result will never be an instance of an integer.
You should instead use the modulo operator to test if the remainder is 0:
if number % divider == 0:
print("{} Y".format(divider))
else:
print("{} N".format(divider))
I would solve it using modulus. If the remainder is 0 then its divisible otherwise its not. No need to have any int or float checks.
num = input("> ")
#Assuming the num is an integer
divisors = [] #List of divisors
for i in range(1,num):
if num%i == 0:
divisors.append(i)
Output:
>>[1, 2, 5]
for divisor in range(1, number//2+1):
print("{} {}".format(divisor, "Y" if number % divisor == 0 else "N"))
Some additional advice:
Don't use capitals for variable names. It's good practice to name classes with capitals instead (and all-caps for constants).
It is enough to walk until number // 2 (the integer division) because between number // 2 and number there cannot be any more divisors.
DRY - don't repeat yourself (a very general rule in programming): Use the a if b else c operator to avoid repeating the print.
What about you just use modulo like in the following?
result = Number%divider
if result==0:
print("{} Y".format(divider))
num = int(input('Enter a number : '))
div = 1
count = 0
while True:
if(div == num+1):
break
result = num%div
if result == 0:
print('{} -- yes'.format(div))
count+=1
else:
print('{} -- No'.format(div))
div+=1
print('Total number of divisor : ', count)

Python: Code to find a number where first N digits are divisible by N (from 0-9)

I've been trying to write a recursive solution to a program to find a number where first N digits are divisible by N.
As an example: 3816547290, 3 is divisible by 1, 38 is divisible by 2, 381 is divisible by 3 and so on...
My recursive solution works fine while going "into" the recursion, but has issues when the stack unwinds (i.e. I don't specifically know how to backtrack or take steps on the way out
ARR = [0]*10
ARR[0] = 1 #dummy entry
def numSeq(pos, num):
if all(ARR):
print num
return True
if (pos>0) and (num%pos) != 0:
return False
for i in xrange(1,10):
if ARR[i] == 1:
continue
new_num = num*10 + i
if new_num%(pos+1) == 0:
ARR[i] = 1
numSeq(pos+1,new_num)
The problem with this code seems to be that it follows the number generation correctly while going into the recursion...so it correctly generates the number 123654 which is divisible by 6 and follows first N digits being divisible by N, but after it fails to find any further digits from 7-8 or 9 that divide 7, i don't get the next set of steps to "reset" the global ARR and begin from index 2, i.e. try 24xxxx,and eventually get to 3816547290
Thanks in Advance for your help!
EDIT: One condition I'd forgotten to mention is that each digit must be used exactly once (i.e. repetition of digits is disallowed)
2nd EDIT:
I was able to finally apply proper backtracking to solve the problem...this code works as is.
ARR = [0]*10
def numDivisibile(num,pos):
if all(ARR):
print num
return True
for i in xrange(0,10):
if ARR[i] == 1:
continue
new_num = num*10+i
#check for valid case
if new_num%(pos+1) == 0:
ARR[i] = 1
if numDivisibile(new_num, pos+1):
return True
#backtrack
ARR[i] = 0
return False
print numDivisibile(0, 0)
To generate all 10 digits integers where the first n digits are divisible by n for each n from 1 to 10 inclusive:
#!/usr/bin/env python3
def generate_ints_nth_digit_divisible_by_n(n=1, number=0):
number *= 10
if n == 10:
yield number # divisible by 10
else:
for digit in range(not number, 10):
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_ints_nth_digit_divisible_by_n(n + 1, candidate)
print("\n".join(map(str, generate_ints_nth_digit_divisible_by_n())))
Output
1020005640
1020061620
1020068010
...
9876062430
9876069630
9876545640
To get numbers where each digit occurs only once i.e., to find the permutations of the digits that satisfy the divisibility condition:
def divisibility_predicate(number):
digits = str(number)
for n in range(1, len(digits) + 1):
if int(digits[:n]) % n != 0:
return n - 1
return n
def generate_digits_permutation(n=1, number=0, digits=frozenset(range(1, 10))):
# precondition: number has n-1 digits
assert len(set(str(number))) == (n - 1) or (number == 0 and n == 1)
# and the divisibility condition holds for n-1
assert divisibility_predicate(number) == (n - 1) or (number == 0 and n == 1)
number *= 10
if n == 10:
assert not digits and divisibility_predicate(number) == 10
yield number # divisible by 10
else:
for digit in digits:
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_digits_permutation(n + 1, candidate, digits - {digit})
from string import digits
print([n for n in generate_ints_nth_digit_divisible_by_n()
if set(str(n)) == set(digits)])
print(list(generate_digits_permutation()))
Output
[3816547290]
[3816547290]
In your function, you never do return numSeq(...), this seems like causing the issue.
If you want to have a iterative solution, you can check the following:
def getN(number):
strNum = str(number)
for i in range(1, len(strNum)+1):
if int(strNum[:i]) % i != 0:
return i-1
return i
print getN(3816)
print getN(3817)
print getN(38165)
Output:
4
3
5
We can modify your recursive function a little to try different possibilities. Rather than have a global record (ARR) of used positions, each thread of the recursion will have its own hash of used digits:
def numSeq(pos, num, hash):
if pos != 1 and num % (pos - 1) != 0: # number does not pass the test
return
elif pos == 11: # number passed all the tests
print num
elif pos == 5:
numSeq(pos + 1,10 * num + 5,hash) # digit is 5 at position 5
elif pos == 10:
numSeq(pos + 1,10 * num,hash) # digit is 0 at position 10
else:
k = 2 if pos % 2 == 0 else 1 # digit is even at even positions
for i in xrange(k,10,2):
if hash & (1 << i): # digit has already been used, skip it
continue
numSeq(pos + 1,10 * num + i,hash | (1 << i))
numSeq(1,0,0) # 3816547290

Categories