I need to make a program in Python that do this:
Write a program that, for a given sequence of digits, prints the number of different three-digit even numbers that can be formed from the given digits. When forming each three-digit even number, each element of the sequence of digits can be used at most once.
The first line of the standard input contains the number of digits N, such that 3≤N≤50000. In the second row is N digits separated by one space.
Print only one number to the standard output, the requested number of three-digit numbers.
n=int(input())
num=[]
for i in range (n):
num.append ()
Input
4
2 4 2 2
Output
4
Explanation
From the digits 2, 4, 2, 2, 4 different three-digit even numbers can be formed, namely 222, 224, 242, 422.
This is a general solution that checks all permutations of these digits and print even numbers out of them:
from itertools import permutations
k = 3
c = 0
n = int(input())
num = input().strip().split(" ")
perms = set(permutations(num, k))
for perm in perms:
t = int("".join(perm))
if t % 2 == 0 and len(str(t)) == k:
print(t)
c += 1
print(c)
This is another solution if you don't want to use this generalized approach and just want to solve it for 3 digits:
c = 0
n = int(input())
num = [int(x) for x in input().strip().split(" ")]
r = set()
for i in range(n):
for j in range(n):
for k in range(n):
if i == j or i == k or j == k:
continue
t = num[i] * 100 + num[j] * 10 + num[k]
if t % 2 == 0 and len(str(t)) == 3:
r.add(t)
print(r)
print(len(r))
First You should declare which user input u expect and how to handle false input.
Then the inputString is split into a list of Strings aka inputList. Now You can loop through each of those inputItem and check if they fit your expectations (is int and smaller then 10 ). Since You still deal with String Items You can try to cast ( convert them) into Int. That can fail and a unhandled failure could cripple Your script so it has to happen in an try- catch-block. If the casting works You wanna make sure to check your matchList if You allready added a simular number before You add the new Number to Your matchList.You do so again by looping through each item. If there is mo such number yet there is a last check for if the number is uneven or 0. In that case there is one possible combination less for each number that is 0 or uneven so they are counted in the variable minusOneCombi. That will be substrated from the maximum amount of combinations which is the amount of numbers in you matchList multiplied with itself (pow(2)). Be very careful with the Indentations. In Python they are determining the ends of if blocks and loops.
InputString=(input("Enter your number stream eg 1 0 0 5 ( non numeric signs and numbers greater 9 will be ignored): "))
inputList= inputString.split(‘ ’)
matchList=[]
minusOneCombi= 0
for inputItem in inputList:
try:
anInt= int(inputItem)
except ValueError:
# Handle the exception
print(“item is not an integer and therefore ignored”)
NotYetinMatchList= True
for MatchItem in MatchList:
If matchItem == inputItem:
notYetinMatchList= False
Break
If notYetinMatchList:
matchList.append(anInt)
if ((anInt % 2) != 0) OR (anInt ==0):
minusOneCombi++
NumofMatches=matchList.count()
NumOfMatchesPow= pow(NumofMatches,2)
Result=NumOfMatchesPow -minusOneCombi
Print(Result)
Related
I want to check if a given number can be formed by another number say b and reverse(b). For example 12 == 6+6, 22 == 11 + 11 and 121 == 29+92. One thing I have figured out is if the number is multiple of 11 or it is an even number less than 20, then it can be formed. I tried to implement this below:
num = 121
if num%11==0:
print('Yes')
else:
if num%2==0 and num<20:
print('Yes')
else:
for j in range(11,(int(num)//2)+1):
if j+int(str(j)[::-1])==num:
print('Yes')
break
However, if the condition goes into the for loop, it gives TLE. Can any other conditions be given?
Update: If the reversed number has trailing zeroes, it should be removed and then added. For example: 101 == 100+1. I am looking for an optimized form of my code. Or I think I am missing some conditions which can take O(1) time, similar to the condition if num%11==0: print('Yes')
All the previous answers are not really a check. It's more a brute force try and error.
So let's do it a little bit smarter.
We start with a number, for example 246808642. we can reduce the problem to the outer 2 place values at the end and start of the number. Let us call this values A and B at the front and Y and Z on the back. the rest, in the middle, is Π. So our number looks now ABΠYZ with A = 2, B = 4, Π = 68086, Y = 4 and Z = 2. (one possible pair of numbers to sum up for this is 123404321). Is A equal to 1, this is only possible for a sum greater 10 (An assumption, but i guess it works, some proof would be nice!).
so if it is a one, we know that the second last number is one greater by the carry over. So we ignore A for the moment and compare B to Z, because they should be the same because both are the result of the addition of the same two numbers. if so, we take the remaining part Π and reduce Y by one (the carry over from the outer addition), and can start again at the top of this chart with Π(Y-1). Only a carry over can make B one bigger than Z, if it's so, we can replace B by one and start with 1Π(Y-1) at the top. B-1!=Z and B!=Z, we can stop, this isnt possible for such a number which is the sum of a number and its reversed.
If A != 1, we do everything similiar as before but now we use A instead of B. (I cut this here. The answer is long enough.)
The code:
import time
def timing(f):
def wrap(*args, **kwargs):
time1 = time.time()
ret = f(*args, **kwargs)
time2 = time.time()
print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))
return ret
return wrap
#timing
def check(num):
num = str(num)
if (int(num) < 20 and int(num)%2 == 0) or (len(num) ==2 and int(num)%11 == 0):
return print('yes')
if len(num) <= 2 and int(num)%2 != 0:
return print('no')
# get the important place values of the number x
A = num[0]
B = num[1]
remaining = num[2:-2]
Y = num[-2]
Z = num[-1]
# check if A = 1
if A == '1':
# A = 1
# check if B == Z
if B == Z:
# so the outest addition matches perfectly and no carry over from inner place values is involved
# reduce the last digit about one and check again.
check(remaining + (str(int(Y)-1) if Y != '0' else '9'))
elif int(B)-1 == int(Z):
# so the outest addition matches needs a carry over from inner place values to match, so we add to
# to the remaining part of the number a leading one
# we modify the last digit of the remaining place values, because the outest had a carry over
check('1' + remaining + (str(int(Y)-1) if Y != '0' else '9'))
else:
print("Not able to formed by a sum of a number and its reversed.")
else:
# A != 1
# check if A == Z
if A == Z:
# so the outest addition matches perfectly and no carry over from inner place values is involved
check(B + remaining + Y)
elif int(A) - 1 == int(Z):
# so the outest addition matches needs a carry over from inner place values to match, so we add to
# to the remaining part of the number a leading one
# we modify the last digit of the remaining place values, because the outest had a carry over
check('1' + B + remaining + Y)
else:
print("Not able to formed by a sum of a number and its reversed.")
#timing
def loop_check(x):
for i in range(x + 1):
if i == int(str(x - i)[::-1]) and not str(x - i).endswith("0"):
print('yes, by brute force')
break
loop_check(246808642)
check(246808642)
Result:
yes, by brute force
loop_check function took 29209.069 ms
Yes
check function took 0.000 ms
And another time we see the power of math. Hope this work for you!
You can brute force it like this:
def reverse_digits(n):
return int(str(n)[::-1])
def sum_of_reversed_numbers(num):
for i in range(num + 1):
if i == reverse_digits(num - i):
return i, num - i
return None
print("Yes" if sum_of_reversed_numbers(num) else "No")
Can you provide the constraints of the problem?
Here is something you can try:
i = 0
j = num
poss = 0
while(i<=j):
if(str(i)==str(j)[::-1]):
poss = 1
break
i+=1
j-=1
if(poss):
print("Yes")
else:
print("No")
You can do it without str slicing:
def reverse(n):
r = 0
while n != 0:
r = r*10 + int(n%10)
n = int(n/10)
return r
def f(n):
for i in range(n + 1):
if i + reverse(i) == n:
return True
return False
print('Yes' if f(101) else 'No')
#Yes
The basic idea of my solution is that you first generate a mapping of digits to the digits that could make them up, so 0 can be made by either 0+0 or 1+9, 2+8 etc. (but in that case there's a carried 1 you have to keep in mind on the next step). Then you start at the smallest digit, and use that code to check each possible way to form the first digit (this gives you candidates for the first and last digit of the number that sums with its reverse to give you the input number). Then you move on the second digit and try those. This code could be greatly improved by checking both the last and the first digit together, but it's complicated by the carried 1.
import math
candidates = {}
for a in range(10):
for b in range(10):
# a, b, carry
candidates.setdefault((a + b) % 10, []).append((a, b, (a + b) // 10))
def sum_of_reversed_numbers(num):
# We reverse the digits because Arabic numerals come from Arabic, which is
# written right-to-left, whereas English text and arrays are written left-to-right
digits = [int(d) for d in str(num)[::-1]]
# result, carry, digit_index
test_cases = [([None] * len(digits), 0, 0)]
if len(digits) > 1 and str(num).startswith("1"):
test_cases.append(([None] * (len(digits) - 1), 0, 0))
results = []
while test_cases:
result, carry, digit_index = test_cases.pop(0)
if None in result:
# % 10 because if the current digit is a 0 but we have a carry from
# the previous digit, it means that the result and its reverse need
# to actually sum to 9 here so that the +1 carry turns it into a 0
cur_digit = (digits[digit_index] - carry) % 10
for a, b, new_carry in candidates[cur_digit]:
new_result = result[::]
new_result[digit_index] = a
new_result[-(digit_index + 1)] = b
test_cases.append((new_result, new_carry, digit_index + 1))
else:
if result[-1] == 0 and num != 0: # forbid 050 + 050 == 100
continue
i = "".join(str(x) for x in result)
i, j = int(i), int(i[::-1])
if i + j == num:
results.append((min(i, j), max(i, j)))
return results if results else None
We can check the above code by pre-calculating the sums of all numbers from 0 to 10ⁿ and their reverse and storing them in a dict of lists called correct (a list because there's many ways to form the same number, eg. 11+11 == 02 + 20), which means we have the correct answers for 10ⁿ⁻¹ we can use to check the above function. Btw, if you're doing this a lot with small numbers, this pre-calculating approach is faster at the expense of memory.
If this code prints nothing it means it works (or your terminal is broken :) )
correct = {}
for num in range(1000000):
backwards = int(str(num)[::-1])
components = min(num, backwards), max(num, backwards)
summed = num + backwards
correct.setdefault(summed, []).append(components)
for i in range(100000):
try:
test = sum_of_reversed_numbers(i)
except Exception as e:
raise Exception(i) from e
if test is None:
if i in correct:
print(i, test, correct.get(i))
elif sorted(test) != sorted(correct[i]):
print(i, test, correct.get(i))
Stole the idea from #Doluk. I was asked this question in a test today. I couldn't solve it then. With Doluk's idea and thinking seriously on it below is a decision tree kind for one level of recursion. I might be wrong as I haven't ran this algorithm.
Let n be the number, we want to check if special
case 1: leading number is not 1
case 1a: no carry over from inner addition
abcdefgh
hgfedcba
x x => (a+h) < 10
if both ends are same in n, strip both sides by one digit and recurse
case 1b: carry over from inner addition
1
abcdefgh
hgfedcba
(x+1)......(x) => (a+h+1) < 10
if left end is 1 greater than right end in n, strip both sides by one digit, add digit 1 on the left and recurse
case 2: leading number is 1
case 2a: no carry over from inner addition
1 1
abcdefgh
hgfedcba
1x x => (a+h) >= 10
strip - if second and last digit are same, strip two digits from left and one from right, from the remaining number minus 1 and recurse.
case 2b: carry over from inner addition
case 2bi: a+h = 9
11
abcdefgh
hgfedcba
10......9
strip - two from left and one from right and recurse.
case 2bj: a+h >= 10
11 1
abcdefgh
hgfedcba
1(x+1)......x
strip - two from left and one from right and subtract 1 from number and recurse.
In my question, they gave me an array of numbers and they asked me to find numbers which of them are special (Which can be formed by the sum and reverse of that number).
My brute force solution was to iterate from 0 to 1000000 and insert them into the set and last check for each element in the set.
Time Complexity: O(n)
Space Complexity: O(n)
where n is the highest number allowed.
I need to take a number, lets say 6, and then find the smallest 4 digit number, whose digits do not repeat and add up to 6.
For example(These will not add up to the same number):
1023
3045
2345
These numbers are all ok because their digits do not repeat and are four digits
While:
1122
3344
123
These are not ok, because they either are not four digits or their numbers repeat
I'm currently at a roadblock where I can find said four digit number, but one: it is in a list which the program i need to plug this into wont accept and two: the digits aren't in the same order as the answers on the program (ie the smallest four digit number that does not have repeat digits, but adds up to six is 1023, but my program returns 0123, which is incorret.
Here is my current code:
x = 6
Sum = 0
#Find the four digit number
for i in range (999, 10000):
#Find the sum of those numbers
Sum = sum(map(int, str(i)))
#Check if sum is = to x
if Sum == x:
num = i
#Get rid of any identical numbers
result = list(set(map(int, str(num))))
#Make sure the length is 4
if len(result) == 4:
print(result)
#Output [0,1,2,3]
Any help on how I could change this to work for what I want would be great
Using recursive algorithm:
def get_num(n, s, v=""):
for el in range(1 if v=="" else 0, 10):
if str(el) not in v:
temp_sum=sum(int(l) for l in v+str(el))
if(temp_sum>s):
break
elif len(v)==n-1:
if(temp_sum==s):
return v+str(el)
else:
ret=get_num(n, s, v+str(el))
if(ret): return ret
Outputs:
print(get_num(4,6))
>> 1023
I've changed your program to print i instead of result, and break out of the loop when it finds the first number (which logically must be the smallest):
x = 6
Sum = 0
#Find the four digit number
for i in range (999, 10000):
#Find the sum of those numbers
Sum = sum(map(int, str(i)))
#Check if sum is = to x
if Sum == x:
num = i
#Get rid of any identical numbers
result = list(set(map(int, str(num))))
#Make sure the length is 4
if len(result) == 4:
print(i)
break
This program will print 1023.
You could neaten it up a bit by turning it into a function with x as a parameter and returning the result instead of breaking and printing. Also it looks as if the num variable is redundant, you can just stick with i.
Changed your code a little:
x = 6
Sum = 0
result={}
#Find the four digit number
for i in range (999, 10000):
#Find the sum of those numbers
Sum = sum(map(int, str(i)))
#Check if sum is = to x
if Sum == x:
num = i
aux = ''.join(list(set(map(str, str(num)))))
if not aux in result:
result[aux] = []
result[aux].append(i)
for k in result:
print(k, min(result[k]))
You might be interested in itertools package which is designed for solving combinatoric problems like yours.
for n in combinations(range(10),4):
if sum(n)==6 and n[0]!=0:
print(n)
break
combinations method used here returns a generator of all tuples of length 4 that contains distinct digits from 0 to 9, they are sorted alphabetically.
You need to use from itertools import combinations to make it work.
Since you need the smallest integer, you can stop the search at the first encountered with a break:
sum=6 # The sum of digits required.
found=0
for i in range(1000, 10000): # i from 1000 to 9999.
a=i%10;
b=i//10%10
c=i//100%10
d=i//1000%10
if (a!=b)&(a!=c)&(a!=d)&(b!=c)&(b!=d)&(c!=d)&(a+b+c+d==sum):
found=True
break
if found:
print(i)
else:
print('Not found such a number.')
def find_outlier(lstOfints):
for integer in lstOfints:
#print(integer)
if integer % 2 ==1:
integer
elif integer % 2 == 0:
integer
return integer
I keep getting the incorrect answer and I don't know what's going on.
This is the problem:
You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N.
This seems to work for me:
def find_outlier(lstOfints):
if lstOfints[0] % 2 == 1 and lstOfints[1] % 2 == 1:
for integer in lstOfints[2::]:
if integer % 2 == 0:
return integer
elif lstOfints[0] % 2 == 0 and lstOfints[1] % 2 == 0:
for integer in lstOfints[2::]:
if integer % 2 == 1:
return integer
else:
if lstOfints[0] % 2 == lstOfints[2] % 2:
return lstOfints[1]
else:
return lstOfints[0]
Firstly, I am seeing if this list is either all odds, or all evens, bar the outlier. Then if it is even, it goes through the list looking for an odd number, the same for if the list is all odd. However, if the outlier is in the first two numbers, then it checks to see whether the outlier is the first number or the second number by comparing the modulos to the modulo of the third number in the list.
A pythonic answer might be something like that:
def find_outlier(lst):
mods = [n % 2 for n in lst]
return lst[mods.index(0)] if sum(mods[:3]) > 1 else lst[mods.index(1)]
print(find_outlier([5, 31, 57, 45, 9, 17, 8, 37, 123, 67])) # --> 8
print(find_outlier([4, 30, 56, 44, 8, 16, 7, 36, 122, 66])) # --> 7
Explanation: first create the list of all n % 2 for all n in the provided list. Then you simply have to check the sum of the first 3 elements of this new list to know whether the outlier is odd or even. Then find index of the outlier remainder (either 0 or 1) and return the corresponding integer from the first list...
There are many things to change in your code, so I will try to change it at steps to get it working at the end.
Run the function from the question
Well, I tested your code here and I see why it is confusing. I have this script:
def find_outlier(lstOfints):
for integer in lstOfints:
#print(integer)
if integer % 2 ==1:
integer
elif integer % 2 == 0:
integer
return integer
print(find_outlier([1,3,4,5]))
print(find_outlier([1,2,3,4]))
...and if I run it, we get this:
$ python disparity.py
5
4
It is just printing the last number! Why so?
Why is it always printing the last number from the list?
Well, because you just return at the end of the function. You expect the function to return from inside the if statement, but you did not used the return command. It is easy to solve:
def find_outlier(lstOfints):
for integer in lstOfints:
if integer % 2 ==1:
return integer
elif integer % 2 == 0:
return integer
return integer
print(find_outlier([1,3,4,5]))
print(find_outlier([0,2,3,4]))
So now we run it and get
$ python disparity.py
1
0
Now it is just returning the first element!
Why is it now always printing the first number from the list?
It prints the first element because your if statements are complementary. Given any element, regardless of its parity, it modulo 2 will be either 0 or 1. If it is zero, the first if returns; if it is 1, the second returns! Since it is true to all elements, it is true to the first one, so the function ends at the very first iteration.
This is not the algorithm you want. What you want is to first know which parity is the outlier, and then look for the outlier number.
How to discover which parity is an outlier if I don't know which number is the outlier?
Since the list has at least three elements, that is easy: we consider two scenarios.
The first scenario is, the outlier is one of the first three elements. In this case, we will have one outlier parity and two "normal" parities.
The second scenario is, the outlier is not one of the first three elements. In this case, we will have three equal parities, and the outlier will be the opposite one.
So, if we count the number of even numbers and odd numbers in the first three values, we know that the parity with less numbers is the outlier one.
If there are more even numbers than odd numbers (either two even and one odd, or three even and no odd), then we know the outlier is odd.
If there are more odd numbers than even numbers, we know the outlier is even.
Now, how to do it in code?
To do that, I will write pieces of code below that, at then end, put together, will give us the answer. First I create two variables to count the even and odd numbers (with 0 at first).
even_numbers = 0
odd_numbers = 0
Then, I see if the first element is even. If so, I increment the counter of even numbers:
if listOfints[0] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
Then I do the same thing with the second and third elements:
if listOfints[1] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
if listOfints[2] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
If we have more even numbers than odd numbers, we know the outlier parity is odd (that is, the rest of the division of the outlier to 2 is 1); if we have more odd numbers than even numbers, the outlier parity will be even (that is, the rest will be zero)
if even_numbers > odd_numbers:
outlier_parity = 1
else:
outlier_parity = 0
So, now I know if the outlier number is even or odd, I agree. But I want to know what is the number!
Now that we do know the parity of the outlier, we just need to look for it:
for integer in lstOfints:
if integer % 2 == outlier_parity:
return integer
Bundling all together, this is our new function:
def find_outlier(lstOfints):
even_numbers = 0
odd_numbers = 0
if lstOfints[0] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
if lstOfints[1] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
if lstOfints[2] % 2 == 0:
even_numbers = even_numbers + 1
else:
odd_numbers = odd_numbers + 1
if even_numbers > odd_numbers:
outlier_parity = 1
else:
outlier_parity = 0
for integer in lstOfints:
if integer % 2 == outlier_parity:
return integer
print(find_outlier([1,3,4,5]))
print(find_outlier([0,2,3,4]))
Does it work? Let's test:
$ python disparity.py
4
3
Oh, it worked! Not bad, right? :)
Some considerations
This code here isn't the most elegant, but my purpose here is mostly that you understand what is going on. It could be done with a waaaaaay shorter, more readable function, but since you are still looking for basic concepts, I did a more detailed, explainable function, which is kind of cumbersome as a consequence.
my solution is:
def find_outlier(integers):
odd = []
even = []
for i in integers:
if i% 2 != 0:
odd.append(i)
elif i% 2 == 0:
even.append(i)
if len(odd) < len(even):
return odd[0]
else:
return even[0]
I am currently trying to use the luhn method to determine whether a credit card is valid or not in python and here is what I have so far:
print('What is your Credit Card number? :) (please put a space between each number)')
a = [int(x) for x in input().split()]
lengthy = len(a)
print(lengthy)
a.reverse()
print(a)
listx2 = []
listx1 = []
for x in range(len(a)):
modulus = x % 2
print(x, a[x])
if modulus != 0:
listx2.append(a[x]*2)
else:
listx1.append(a[x])
print(listx2)
print(listx1)
I don't know how to do the next step which is getting the sum of all of the digits of the numbers multiplied by two.(listx2) I have looked at different programs with the luhn method but I just can't seem to pick that part out. Thanks!
This is my interpretation of the Luhn algo.
def luhn(sequence):
digits = [int(digit) for digit in str(sequence)] # converts a full string of nums to a list comp of individual numbers
odd = digits[-1::-2] # string stepping (-1) indicates last item in list (-2) means to travel back another 2
even = digits[-2::-2]
checksum = 0
checksum += sum(odd)
evenmod = []
for digit in even:
if digit * 2 > 9:
digit = digit * 2
digit = int(str(digit)[0]) + int(str(digit)[1])
else:digit = digit * 2
evenmod.append(digit)
checksum += sum(evenmod)
if checksum % 10 == 0:
return True
else:
return False
print luhn(378282246310005)
print luhn(111111111111111)
print luhn(4751290083628479)
print luhn(5573485043994670)
Separate the even and the odd indeces to separate lists, then use a for statement to loop through the list, multiplying the list entries by two.
Notice the if statement that catches the issue with (e.g) 8 * 2 = 16.
Use sum:
summed_x2 = sum(listx2)
I saw this question somewhere.
There is a 8 digit number. First digit from left to right tells how many zeroes in the number. Second digit tells you how many 1s in the number, third digit tells u how many 2 in the number and so on till 8th digit which tells u how many 7 in the number. Find the number.
So I wrote a piece of code in python to find out the digit. Apart from the conditions mentioned above, I have few additional checks like 'sum of digits should be 8' and 'no 8 or 9 should be present in the number'. I've pasted the code below. This is just brute force since I take every number and check for conditions. I was curious to know if there is any better way of solving the problem
def returnStat(number, digit, count):
number = str(number)
digit = str(digit)
print "Analysing for ",digit," to see if it appears ",count, " times in ",number,"."
actCnt = number.count(digit)
count = str(count)
actCnt = str(actCnt)
if (actCnt == count):
return 1
else:
return 0
def validateNum(number):
numList = str(number)
if '8' in numList:
print "Skipping ",number, " since it has 8 in it"
return (-1)
elif '9' in numList:
print "Skipping ",number, " since it has 9 in it"
return (-1)
elif (sum(int(digit) for digit in numList) != 8):
print "Skipping ",number, " since its sum is not equal to 8"
return (-1)
index = 0
flag = 0
for num in numList:
if (returnStat(number,index,num)) :
index = index+1
continue
else:
flag = 1
break
if (flag == 1):
return (-1)
else:
return number
for num in range(0,80000000):
number = '{number:0{width}d}'.format(width=8,number=num)
desiredNum = "-1"
desiredNum = validateNum(number)
if (desiredNum == -1):
print number," does not satisfy all "
continue
else:
print "The number that satisfies all contition is ",number
break
You can go further than to simply say that digits of 8 or 9 are impossible.
Can the last digit ever be greater than 0? The answer is no. If the last digit was 1, this means there is one 7 somewhere else. However, if there is a 7, it means that the same number has occurred 7 times. This is clearly impossible. Thus the last digit has to be 0.
So we have xxxxxxx0.
What about the second to last digit?
If xxxxxx10, then there has to be at least one 6, which means the same number occurred 6 times. We can try 60000010, but this is incorrect, because there is a 1, which should be reflected in the second digit. The second to last digit can't be higher than 1 because 2 means there are 2 sixes, which in turn means one number occurred six times while another number also occurred 6 times, which is impossible.
So we have xxxxxx00.
If xxxxx100, then there has to be at least one 5, which means the same number occurred 5 times. Let us start with 51000100. Almost, but there are now 2 1s. So it should be 52000100. But wait, there are now one 1. and one 2. So we try 52100100. But now we only have 4 0s. We can't have xxxxx200 because this means there are 2 5s, which is impossible as explained above.
So we have xxxxx000.
If xxxx1000, we can try 40001000, nope, 41001000, nope, 42101000.
Ah there it is. 42101000.
Even if you iterate over all 8 digit numbers with no 8s or 9s in them, there's not many possibilities (actually, 8^8 = 1<<24 ~= 17 million).
Here's a naive program that tries them all:
import itertools
for digs in itertools.product(range(8), repeat=8):
counts = [0] * 8
for d in digs:
counts[d] += 1
if counts == list(digs):
print digs
It completes (with exactly one solution) in 15 seconds on my machine.
To make it faster, you can only consider 8-digit numbers whose digits add up to 8. Here's the same code as before, but now it uses sum_k to produce the possibilities. (sum_k(n, k) generates all n-digit tuples where all the digits are less than 8 which sum to k).
def sum_k(n, k):
if k < 0 or n * 7 < k: return
if n == 1:
yield k,
return
for d in xrange(8):
for s in sum_k(n-1, k-d):
yield (d,) + s
for digs in sum_k(8, 8):
counts = [0] * 8
for d in digs:
counts[d] += 1
if counts == list(digs):
print digs
This code completes in 0.022 seconds on my machine.
Adapting the code to solve the general case produces these solutions:
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000