0

Given an integer n between 0 and 10,0000,0000, count the number of integers smaller than n which contain the digits [2,0,1,8] in order.

So e.g. the number 9,230,414,587 should be counted, because removing the digits [9,3,4,4,5,7] leaves us with [2,0,1,8].

Example input and output:

n = 2018      ->  count =     1
n = 20182018  ->  count = 92237

My general thought is that: the maximum length of n is 10 and the worst situation is that we have to insert 6 digits into [2,0,1,8] and remove the duplicates and the numbers greater than n.

ileadall42
  • 631
  • 2
  • 7
  • 19
  • 3
    I'm sorry, this sounds like an interesting question but I am a little unclear on what exactly you want the algorithm to do. How did you get `92237` for the output of the `20182018` number? – Alerra Sep 04 '18 at 02:43
  • @Alerra sorry for the late explanation,`92237` Is the numbers of the all numbers which `< 20182018(n) ` .such as `20182017\20182016\20182014` This all < `20182018(n)` and find the numbers of the number meet the need. – ileadall42 Sep 04 '18 at 03:15
  • In a word,count the number which `< n` and meet the need! – ileadall42 Sep 04 '18 at 03:18
  • So, why does `20182015` not work but `20182016` and `20182014` do work? I'm sorry I am still confused by this. – Alerra Sep 04 '18 at 03:21
  • @Alerra uh..I just miss type it - -,it is some example.I update the description about how to define `2018` number.And what the algorithm do is to count the `2018` Number which < n – ileadall42 Sep 04 '18 at 03:24
  • So, if I understand correctly, we want to count the number of different numbers `< n` such that `2018` is contained in the digits of these numbers? – Alerra Sep 04 '18 at 03:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/179346/discussion-between-ileadall42-and-alerra). – ileadall42 Sep 04 '18 at 03:28
  • Do you know dynamic programming? – Pham Trung Sep 04 '18 at 03:48

2 Answers2

2

I don't see any own attempts to solve, so I'll give only clue:

You have 9-digits number (small numbers might be represented as 000002018) containing digit sequence 2,0,1,8.
Name them 'good' ones.
Let denote digit places from 1 to 9 right to left:

     number     532705183
digits     5  3  2  7  0  5  1  8  3
index      9  8  7  6  5  4  3  2  1

The most left '2' digit can occupy places from 4 to 9. How many good numbers contain the first 2 at k-th place? Let make function F2(l, k) for quantity of good numbers where 2 refers to digit 2, l is number length, k is place for the most left digit.

 .   .   .   .  2   .   .   .   .
                ^ 
                | 
 left part      k     right part should contain 0 1 8 sequence
 without 2's

 F2(9, k) = 9^(9-k) * Sum(F0(k-1, j) for j=1..k-1)

Overall quantity of good numbers is sum of F2(9, k) for all possible k.

GoodCount = Sum(F2(9, k) for k=4..9)

Explanation:

There are 9-k places at the left. We can put any digit but 2 there, so there are 9^(9-k) possible left parts.

Now we can place 0 at the right part and count possible variants for 018 subsequences. F0(...) will of course depend on F1(...) and F1 will depend on F8(...) for shorter numbers.

So fill tables for values for F8, F0, F1 step-by-step and finally calculate result for digit 2.

Hand-made example for 4-digit numbers containing subsequence 1 8 and k = position of the first '1':
k=2: there are 81 numbers of kind xx18
k=3: there are numbers of kind x1x8 and x18x
there are 9 subnumbers like x8, 10 subnumbers 8x, so (10+9)*9=171
k=4: there are numbers of kind
1xx8 (9*9=81 such numbers),
1x8x (9*10=90 numbers),
18xx (100 numbers),
so 81+90+100=271
Overall: 81+171+271=523

MBo
  • 77,366
  • 5
  • 53
  • 86
1

This is actually a relatively small problem set. If the numbers were much bigger, I'd opt to use optimised techniques to just generate all numbers that meet your criteria (those containing the digits in that order) rather than generating all possible numbers and checking each to ensure it meets the criteria.

However, the brute force method does your 20182018 variant in about ten seconds and the full 1,000,000,000 range in a little under eight minutes.

So, unless you need it faster than that, you may find the brute-force method more than adequate:

import re

num = 1000000000 # or 20182018 or something else.

lookfor = re.compile("2.*0.*1.*8")
count = 0
for i in range(num + 1):
    if lookfor.search(str(i)) is not None:
        count += 1
        #print(count, i) # For checking.
print(count)
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953