Step 1: Find the number of digits your answers are likely to fall in. In your example it is 2 or 3. Step 2: For a given number size (number of digits) Step 2a: Pick the possibilities for the first (most significant digit). Find the min and max number starting with that digit (ascend or descending order of rest of the digits). If both of them fall into the range: step 2ai: Count the number of digits starting with that first digit and update that count Step 2b: Else if both max and min are out of range, ignore. Step 2c: Otherwise, add each possible digit as second most significant digit and repeat the same step
Solution for your case:
For the size of number 2, i.e. __:
0_ : Ignore since it starts with 0 2_ : Minimum=20, Max=25. Both are in range. So update count by 3 (second digit might be 0,3,5) 3_ : Minimum=30, Max=35. Both are in range. So update count by 4 (second digit might be 0,2,3,5) 5_ : Minimum=50, Max=53. Both are in range. So update count by 3 (second digit might be 0,2,3)
For size 3:
0__ : Ignore since it starts with 0 2__ : Minimum=200, max=253. Both are in range. Find the number of ways you can choose 2 numbers from a set of {0,0,3,3,5}, and update the count. 3__ : Minimum=300, max=353. Both are in range. Find the number of ways you can choose 2 numbers from a set of {0,0,2,3,5}, and update the count. 5__ : Minimum=500, max=532. Both are out of range. Ignore.
More interesting is the case when the maximum limit is 522 (instead of 400):
5__ : Minimum=500, max=532. Max out of range. 50_: Minimum=500, Max=503. Both in range. Add number of ways you can choose one digit from {0,2,3,5} 52_: Minimum=520, Max=523. Max out of range. 520: In range. Add 1 to count. 522: In range. Add 1 to count. 523: Out of range. Ignore. 53_: Minimum=530, Max=532. Both are out of range. Ignore. def countComb(currentVal, digSize, maxVal, minVal, remSet): minPosVal, maxPosVal = calculateMinMax( currentVal, digSize, remSet) if maxVal>= minPosVal >= minVal and maxVal>= maxPosVal >= minVal return numberPermutations(remSet,digSize, currentVal) elif minPosVal< minVal and maxPosVal < minVal or minPosVal> maxVal and maxPosVal > maxVal: return 0 else: count=0 for k in unique(remSet): tmpRemSet = [i for i in remSet] tmpRemSet.remove(k) count+= countComb(currentVal+k, digSize, maxVal, minVal, tmpRemSet) return count
In your case: countComb('',2,400,20,['0','0','2','3','3','5']) + countComb('',3,400,20,['0','0','2','3','3','5']) will give an answer.
def calculateMinMax( currentVal, digSize, remSet): numRemain = digSize - len(currentVal) minPosVal = int( sorted(remSet)[:numRemain] ) maxPosVal = int( sorted(remSet,reverse=True)[:numRemain] ) return minPosVal,maxPosVal numberPermutations(remSet,digSize, currentVal): Basically number of ways you can choose (digSize-len(currentVal)) values from remSet. See permutations with repeats.