I came across this problem in which you will take an integer as a input from the user and then return the nearest greater number with unique digits.
First it seem like an easy one and i wrote it's code which gave me an desired outputs but for some inputs returns an integer with repeating digits or a unique number with higher value then expected,
I want to know why my code is showing different behaviour than expected and what would be the right answer to this problem.
Also i don't know what to do when a digit will become two digit number how to make it unique eg. 9999
code
n = int(input("enter a no.:"))+1 #taking input adding 1 to make sure if the input is
#unique it should return higher no. with uniq
a =[] #creating an empty list
while n!=0: #loop to store digits in a list
a.append(n%10) #at index 0 ones digit is stored
n = int(n/10) #at index 1 tens digit is stored an so on...
while len(set(a)) != len(a): #checking if the list is unique
for i in range(0,len(a)): #
occur = a.count(a[i]) #taking occurence of a list item
if occur != 1: #if no. is repeated
a[i]+=occur-1 #incrementing the repeating digit.
a.reverse() #converting list to integer and printing
n = 0
for i in a:
n = n*10+i
print(n)
Behaviour
1.Printing repeating digits for some inputs
2.Printing Higher values than expected for some inputs
3.When a digit becomes a two digit no. it treats it like a single digit
Some outputs
enter a no.:1233
output: 1234 #desired output: 1234
enter a no.:7885
output: 7896 #desired output: 7890
enter a no.:7886
output: 8008 #desired output: 7890
enter a no.:999
output: 2013 #desired output: 1023
You're probably over complicating this for yourself.
Would something like this work rather than doing all of the conversions?
n = int(input("enter a no.:"))+1 #taking input adding 1 to make
#sure if the input is unique then
#program does't return the input itself
a = str(n) # simply convert to a string
while len(set(a)) != len(a): #checking if the string is unique
n += 1
a = str(n)
print(n)
Why not simply increment the number until you find one with unique digits?
def next_uniq(n):
a = str(n)
while len(set(a)) != len(a):
a = str(int(a) + 1)
return a
for i in [1233, 7885, 7886, 999]:
print(next_uniq(i))
# 1234, 7890, 7890, 1023
Related
I created a function that allows users to confirm if a number is prime. The code works great, but loses efficiency when a large number is passed through it. Any tips to cut down on time taken to process when confirming large numbers (i.e. 1999999) is prime?
Here is my code. The timing inefficiencies are a result of python asking the computer to divide number by each element in the list 'x' then placing remainder values into a separate list, to then count the number of occurrences for 0.
def is_prime(number):
x = list(range(1, number + 1,1))
numbers = []
if number < 1:
answer1 = "False. Must be positive integer greater than 1."
# For loop is iterating over list 'x'
for i in x:
# number entered divided by each element in the list to find remainder value. Remainder value
# is added to the list for each result.
numbers.append(number % i)
if number == 1:
answer1 = "False. Must be positive integer greater than 1."
# Count function/attribute used to count occurance of 0 in list 'x'
# If 0 appears more than twice on the list that indicates the number entered has more than two
# factors; thus not prime.
elif number > 1 and numbers.count(0) <= 2:
answer1 = "True"
else:
answer1 = "False"
return answer1
num = [int(d) for d in str(input("Enter the number:"))]
even,odd = 0,0
for i in range(0,len(num)):
if i % 2 ==0:
even = even + num[i]
else:
odd = odd + num[i]
print(abs(odd-even))
What does the first line mean for taking strings as input?
The line:
num = [int(d) for d in str(input("Enter the number:"))]
will error out if anything but digits are entered. If only digits are entered, then they end up being individual integer entries in num. For example, for the input 124, the resulting value of num will be [1, 2, 4]. The code will then go on to process each of those single digit numeric values.
BTW, the call to str() is redundant, as input already returns a string value.
Sum of all digits between numbers
Kriti has two numbers, her tution teacher give a task to her. The task is that, she wants to find the sum of all digits appearing between those two numbers.
For Ex:
Num1 = 8 and Num2 = 13
Output: 27
(8 + 9 + 1 + 0 + 1 + 1 + 1 + 2 + 1 +3)
Input Format
Input the Number1 Input the Number2
Constraints
0 <= Number1 <=1000000000
Number1 <= Number2 <=1000000000
(Negative Numbers and Decimals are not allowed)
Output Format
Display the Sum of all digits appearing between Number1 and Number2
Sample Input 0
8
13
Sample Output 0
27
MY CODE
a=int(input())
b=int(input())
ls=0
lst=[]
s=0
for i in range(a,b+1):
lst.append(i)
for i in lst:
if i<10:
s=s+i
else:
for j in str(i):
s=s+int(j)
print(s)
This code almost clear 5/7 test cases but the problem of remaining two cases is the value of number range is 1000000000 if the input of the digits are maximum it will shows runtime error how to solve this problem efficient time with the given constrains constrains. The problem I mentioned here was a hackerrank platform that contest was conducted by my college staff and it's finished by an hour ago
If you approach this from a digit position's perspective, you can achieve O(log10 N).
def sumDigits(n1,n2):
if n2==0 or n1>n2: return 0
p1,d1 = divmod(n1,10) # extract last digits
p2,d2 = divmod(n2,10) # and prefixes
if p1==p2:
# same prefix: sum of last digits, digit count * sum of prefix digits
return sum(range(d1,d2+1)) + (d2-d1+1)*sumDigits(p1,p2)
else:
# different prefixes: recurse lower, upper, middle ranges
return sumDigits(p1*10+d1,p1*10+9) \
+ sumDigits(p2*10, p2*10+d2) \
+ sumDigits(p1+1,p2-1)*10 + (p2-p1-1)*45 # full middle range
For each digit position you can perform the calculation recursively by isolating the lower, middle and upper partial ranges and multiplying the sum of digits for the middle prefixes.
For example: from 1234 to 4567
If the numbers have the same prefix before the last digits, then we only need to compute the sum of the last digits between the two numbers and recurse for the sum of digits in the prefix (which will occur once for every last digit in the range)
Otherwise, break down the problem into lower, middle and upper ranges:
1234-1239 ... 124x-455x ... 4560-4567
The middle part will have all ending digits (0...9) for every number in the range 124x to 455x.
So the last digit part will have a sum of 45 (∑0..9) 332 times (456-124).
Each prefix in the middle range will be present 10 times (once for each ending digit)
So we can compute the sum of digits for numbers in the middle range using sumDigits(124,455) * 10 + (456-124) * 45
The 1234-1239 and 4560-4567 ranges can be computed by recursion (they have a common prefix by definition)
output:
sumDigits(8,13) # 27
sumDigits(1234,4567) # 52723
sumDigits(123456789,987654321) # 35514403389
verification:
sum(sum(map(int,str(n))) for n in range(8,13+1)) # 27
sum(sum(map(int,str(n))) for n in range(1234,4567+1)) # 52723
sum(sum(map(int,str(n))) for n in range(123456789,987654321+1))# takes too long
Your first for loop is definitely useless. You should just iterate over range(a, b + 1) don't put it in a list - this makes interpreter hold all of the values in memory, while you only need one at any point in time, which is why you must use range. This will save whole lot of time and memory.
Other than that, there might be just a slight improvement to calculations. Here is what i'd come up with:
for i in range(a, b + 1):
s += sum(map(int, str(i)))
So I guess I would do it like this:
a = int(input())
b = int(input())
result = 0
for i in range(a, b+1):
# so here we want to get the digits of i and add them up
current_length=len(str(i))
if current_length == 1:
result+=int(i)
else if current_length > 1:
for k in str(i).split(""):
result += int(k)
print(result)
I think this maybe faster than your approach, but I'm not sure, also you may need to tweak this code a bit, as I whipped it up on my phone, and could not really test it.
You don't need a list to keep track of the numbers. You just need a running sum. You can convert each number to a string. The string is iterable and allows you to find the sum of individual digits.
sum = 0
for i in range(a, b + 1):
digits = str(i)
for d in digits:
sum += int(d)
I am working on a problem where I have to output the smallest number bigger than N consisting of the same digits as N. If there is no such number, I must print "0" as the output. This is the code I have for now...
n = int(input())
copy = n+1
while True:
if sorted(str(n)) == sorted(str(copy)):
print(copy)
break
else:
copy+=1
I can not find a way to catch if a number has no such numbers, so, therefore, "0." I was thinking a try expect block but it somehow catches infinite loops. Any idea of how to implement this, or any other suggestions? Thank you!
SAMPLE INPUT/OUTPUT
input 1: 156
output 1: 165
input 2: 330
output 2: 0 (No such number fulfills the condition)
input 3: 27711
output 3: 71127
I have a different approach to the problem:
If all digits sorted in descending order, then output is always -1. For example, 321.
For other cases, we need to process the number from rightmost side (why? because we need to find the smallest of all greater numbers)
Algorithm
Traverse the given number from rightmost digit, keep traversing till you find a digit which is smaller than the previously traversed digit. For example, if the input number is “534976”, we stop at 4 because 4 is smaller than next digit 9. If we do not find such a digit, then output is “Not Possible”.
Now search the right side of above found digit ‘d’ for the smallest digit greater than ‘d’. For “534976″, the right side of 4 contains “976”. The smallest digit greater than 4 is 6.
Swap the above found two digits, we get 536974 in above example.
Now sort all digits from position next to ‘d’ to the end of number. The number that we get after sorting is the output. Finally, for above example, We get “536479” which is the next greater number for input 534976.
In last step we should check weather the result is a 32-bit number or not.
Code
def nextGreaterElement(n):
n = list(str(n))
N = len(n)
for x in range(N - 1, 0, -1):
if n[x] > n[x - 1]:
i = x - 1
break
else:
return -1
swap = i + 1
pos = i
for x in range(swap, N):
if n[pos] < n[x] < n[swap]:
swap = x
n[pos], n[swap] = n[swap], n[pos]
ans = int(''.join(n[:pos + 1]) + ''.join(sorted(n[pos + 1:])))
return ans if len(bin(ans)[2:]) < 32 else -1
print(nextGreaterElement(123))
# 132
I'm new to python ( and programming ) And i'm stuck in the Project Euler 4. The problem says :
"A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers."
Here's what i've come to so far :
ProductOfThree = []
ProductOfThreeSTR = []
PalindromicNumber = []
#This first for loop displays all the results possible from the product of two 3 digit Number
for k in range(100, 1000):
for j in range(k, 1000):
Result = k * j
ProductOfThree.append(Result)
#This second loop converts the list of number to a list of string
for i in ProductOfThree:
a = str(i)
ProductOfThreeSTR.append(a)
#The third loop compare the digit of each number of the list to find all the palindromic number of that list
for d in ProductOfThreeSTR:
if len(d) == 6:
if (d[0] == d[5]) and (d[1] == d[4]) and (d[2] == d[3]):
PalindromicNumber.append(d)
elif len(d) == 5:
if (d[0] == d[4]) and (d[1] == d[3]):
PalindromicNumber.append(d)
#And finally here the program display the largest number of the list, which contains only the palindromic numbers
Largest = PalindromicNumber[0]
for p in PalindromicNumber:
if Largest <= p:
Largest = p
print(Largest)
The program displays the number 99999 . After re-reading the program, i've figured out that the if statement with the len(d) == 5 is useless cause we want to display the largest number and a number with 6 digit is always greater that a number with five digit. After removing this part of the program, I'm having the result that i'm supposed to have ( 906609 ). But I'm still wondering, even if we are trying to find the palindromic number with 5 digit, normally they should be ignored when we will display the largest number of the list, so why it is giving the 99999 result?
I think that the easiest way to do this is create the palindrome list using strings but get the max using integers. This is what I came up with:
x = 100
pal = []
while x < 1000:
for i in range(100,1000):
for j in range(100,1000):
prod = str(i*j)
if prod == prod[::-1]:
pal.append(int(prod))
x = x+1
print(max(pal))
The problem is that in your last loop, when you're looking for the largest value, you compare strings instead of integers. Do this and it will give you the result you expect:
Largest = int(PalindromicNumber[0])
for p in PalindromicNumber:
if Largest <= int(p):
Largest = int(p)
According to python docs string comparison uses lexicographical ordering:
The comparison uses lexicographical ordering: first the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted.
//This would be more precise
def largestpalin(n):
lowerbound=0
upperbound=0
for i in range(1,n+1):
upperbound=upperbound*10
upperbound=upperbound+9
lowebound=int(1+lowerbound/10)
maxproduct=0
for i in range(upperbound,lowerbound-1,-1):
for j in range(i,lowebound-1,-1):
product=i*j
if product<maxproduct:
break
num=product
reverse=0
while(num!=0):
rem=num%10
reverse=reverse*10+rem
num=num//10
if product==reverse and product>maxproduct:
maxproduct=reverse
return maxproduct
n=3
res=largestpalin(n)
print(res)